github.com/rpdict/ponzu@v0.10.1-0.20190226054626-477f29d6bf5e/docs/src/Interfaces/Item.md (about)

     1  title: Item Package Interfaces
     2  
     3  Ponzu provides a set of interfaces from the `system/item` package which extend 
     4  the functionality of the content in your system and how it interacts with other 
     5  components inside and outside of Ponzu. 
     6  
     7  ---
     8  
     9  ## Interfaces
    10  
    11  ### [item.Pushable](https://godoc.org/github.com/rpdict/ponzu/system/item#Pushable)
    12  Pushable, if [HTTP/2 Server Push](https://http2.github.io/http2-spec/#PushResources) 
    13  is supported by the client, can tell a handler which resources it would like to 
    14  have "pushed" preemptively to the client. This saves follow-on roundtrip requests 
    15  for other items which are referenced by the Pushable item. The `Push` method, the 
    16  only method in Pushable, must return a `[]string` containing the `json` field tags 
    17  of the referenced items within the type.
    18  
    19  ##### Method Set
    20  ```go
    21  type Pushable interface {
    22      // the values contained in []string fields returned by Push must be URL paths
    23      Push(http.ResponseWriter, *http.Request) ([]string, error)
    24  }
    25  ```
    26  
    27  ##### Implementation
    28  The `Push` method returns a `[]string` containing the `json` tag field names for
    29  which you want to have pushed to a supported client and an error value. The values 
    30  for the field names **must** be URL paths, and cannot be from another origin.
    31  
    32  ```go
    33  type Post struct {
    34      item.Item
    35  
    36      HeaderPhoto string `json:"header_photo"`
    37      Author      string `json:"author"` // reference `/api/content/?type=Author&id=2`
    38      // ...
    39  }
    40  
    41  func (p *Post) Push(res http.ResponseWriter, req *http.Request) ([]string, error) {
    42      return []string{
    43          "header_photo",
    44          "author",
    45      }, nil
    46  }
    47  ```
    48  
    49  ---
    50  
    51  ### [item.Hideable](https://godoc.org/github.com/rpdict/ponzu/system/item#Hideable)
    52  Hideable tells an API handler that data of this type shouldn’t be exposed outside 
    53  the system. Hideable types cannot be used as references (relations in Content types).
    54  The `Hide` method, the only method in Hideable, takes an `http.ResponseWriter, *http.Request` 
    55  and returns an `error`. A special error in the `items` package, `ErrAllowHiddenItem` 
    56  can be returned as the error from Hide to instruct handlers to show hidden 
    57  content in specific cases.
    58  
    59  ##### Method Set
    60  ```go
    61  type Hideable interface {
    62      Hide(http.ResponseWriter, *http.Request) error
    63  }
    64  ```
    65  
    66  ##### Implementation
    67  ```go
    68  func (p *Post) Hide(res http.ResponseWriter, req *http.Request) error {
    69      return nil
    70  }
    71  ```
    72  
    73  ---
    74  
    75  ### [item.Omittable](https://godoc.org/github.com/rpdict/ponzu/system/item#Omittable)
    76  Omittable tells a content API handler to keep certain fields from being exposed 
    77  through the JSON response. It's single method, `Omit` takes no arguments and 
    78  returns a `[]string` which must be made up of the JSON struct tags for the type 
    79  containing fields to be omitted and an error value.
    80  
    81  ##### Method Set
    82  ```go
    83  type Omittable interface {
    84      Omit(http.ResponseWriter, *http.Request) ([]string, error)
    85  }
    86  ```
    87  
    88  ##### Implementation
    89  ```go
    90  type Post struct {
    91      item.Item
    92  
    93      HeaderPhoto string `json:"header_photo"`
    94      Author      string `json:"author"`
    95      // ...
    96  }
    97  
    98  func (p *Post) Omit(res http.ResponseWriter, req *http.Request) ([]string, error) {
    99      return []string{
   100          "header_photo",
   101          "author",
   102      }, nil
   103  }
   104  ```
   105  
   106  ---
   107  
   108  ### [item.Hookable](https://godoc.org/github.com/rpdict/ponzu/system/item#Hookable)
   109  Hookable provides lifecycle hooks into the http handlers which manage Save, Delete,
   110  Approve, and Reject routines. All methods in its set take an 
   111  `http.ResponseWriter, *http.Request` and return an `error`.
   112  
   113  ##### Method Set
   114  
   115  ```go
   116  type Hookable interface {
   117      BeforeAPICreate(http.ResponseWriter, *http.Request) error
   118      AfterAPICreate(http.ResponseWriter, *http.Request) error
   119  
   120      BeforeAPIUpdate(http.ResponseWriter, *http.Request) error
   121      AfterAPIUpdate(http.ResponseWriter, *http.Request) error
   122  
   123      BeforeAPIDelete(http.ResponseWriter, *http.Request) error
   124      AfterAPIDelete(http.ResponseWriter, *http.Request) error
   125  
   126      BeforeAdminCreate(http.ResponseWriter, *http.Request) error
   127      AfterAdminCreate(http.ResponseWriter, *http.Request) error
   128  
   129      BeforeAdminUpdate(http.ResponseWriter, *http.Request) error
   130      AfterAdminUpdate(http.ResponseWriter, *http.Request) error
   131  
   132      BeforeAdminDelete(http.ResponseWriter, *http.Request) error
   133      AfterAdminDelete(http.ResponseWriter, *http.Request) error
   134  
   135      BeforeSave(http.ResponseWriter, *http.Request) error
   136      AfterSave(http.ResponseWriter, *http.Request) error
   137  
   138      BeforeDelete(http.ResponseWriter, *http.Request) error
   139      AfterDelete(http.ResponseWriter, *http.Request) error
   140  
   141      BeforeApprove(http.ResponseWriter, *http.Request) error
   142      AfterApprove(http.ResponseWriter, *http.Request) error
   143  
   144      BeforeReject(http.ResponseWriter, *http.Request) error
   145      AfterReject(http.ResponseWriter, *http.Request) error
   146  
   147      // Enable/Disable used exclusively for addons
   148      BeforeEnable(http.ResponseWriter, *http.Request) error
   149      AfterEnable(http.ResponseWriter, *http.Request) error
   150  
   151      BeforeDisable(http.ResponseWriter, *http.Request) error
   152      AfterDisable(http.ResponseWriter, *http.Request) error
   153  }
   154  ```
   155  
   156  ##### Implementations
   157  
   158  #### BeforeAPICreate
   159  BeforeAPICreate is called before an item is created via a 3rd-party client. If a 
   160  non-nil `error` value is returned, the item will not be created/saved.
   161  
   162  ```go
   163  func (p *Post) BeforeAPICreate(res http.ResponseWriter, req *http.Request) error {
   164      return nil
   165  }
   166  ```
   167  
   168  #### AfterAPICreate
   169  AfterAPICreate is called after an item has been created via a 3rd-party client.
   170  At this point, the item has been saved to the database. If a non-nil `error` is
   171  returned, it will respond to the client with an empty response, so be sure to 
   172  use the `http.ResponseWriter` from within your hook appropriately.
   173  
   174  ```go
   175  func (p *Post) AfterAPICreate(res http.ResponseWriter, req *http.Request) error {
   176      return nil
   177  }
   178  ```
   179  
   180  #### BeforeApprove
   181  BeforeApprove is called before an item is merged as "Public" from its prior 
   182  status as "Pending". If a non-nil `error` value is returned, the item will not be
   183  appproved, and an error message is displayed to the Admin. 
   184  
   185  ```go
   186  func (p *Post) BeforeApprove(res http.ResponseWriter, req *http.Request) error {
   187      return nil
   188  }
   189  ```
   190  
   191  #### AfterApprove
   192  AfterApprove is called after an item has been merged as "Public" from its prior
   193  status as "Pending". If a non-nil `error` is returned, an error message is 
   194  displayed to the Admin, however the item will already be irreversibly merged.
   195  
   196  ```go
   197  func (p *Post) AfterApprove(res http.ResponseWriter, req *http.Request) error {
   198      return nil
   199  }
   200  ```
   201  
   202  #### BeforeReject
   203  BeforeReject is called before an item is rejected and deleted by default. To reject
   204  an item, but not delete it, return a non-nil `error` from this hook - doing so 
   205  will allow the hook to do what you want it to do prior to the return, but the item
   206  will remain in the "Pending" section.
   207  
   208  ```go
   209  func (p *Post) BeforeReject(res http.ResponseWriter, req *http.Request) error {
   210      return nil
   211  }
   212  ```
   213  
   214  #### AfterReject
   215  AfterReject is called after an item is rejected and has been deleted.
   216  
   217  ```go
   218  func (p *Post) AfterReject(res http.ResponseWriter, req *http.Request) error {
   219      return nil
   220  }
   221  ```
   222  
   223  #### BeforeSave
   224  BeforeSave is called before any CMS Admin or 3rd-party client triggers a save to 
   225  the database. This could be done by clicking the 'Save' button on a Content editor, 
   226  or by a API call to Create or Update the Content item. By returning a non-nil 
   227  `error` value, the item will not be saved.
   228  
   229  ```go
   230  func (p *Post) BeforeSave(res http.ResponseWriter, req *http.Request) error {
   231      return nil
   232  }
   233  ```
   234  
   235  #### AfterSave
   236  AfterSave is called after any CMS Admin or 3rd-party client triggers a save to 
   237  the database. This could be done by clicking the 'Save' button on a Content editor, 
   238  or by a API call to Create or Update the Content item.
   239  
   240  ```go
   241  func (p *Post) AfterSave(res http.ResponseWriter, req *http.Request) error {
   242      return nil
   243  }
   244  ```
   245  
   246  #### BeforeDelete
   247  BeforeDelete is called before any CMS Admin or 3rd-party client triggers a delete to 
   248  the database. This could be done by clicking the 'Delete' button on a Content editor, 
   249  or by a API call to Delete the Content item. By returning a non-nil `error` value,
   250  the item will not be deleted.
   251  
   252  ```go
   253  func (p *Post) BeforeDelete(res http.ResponseWriter, req *http.Request) error {
   254      return nil
   255  }
   256  ```
   257  
   258  #### AfterDelete
   259  AfterSave is called after any CMS Admin or 3rd-party client triggers a delete to 
   260  the database. This could be done by clicking the 'Delete' button on a Content editor, 
   261  or by a API call to Delete the Content item.
   262  
   263  ```go
   264  func (p *Post) AfterDelete(res http.ResponseWriter, req *http.Request) error {
   265      return nil
   266  }
   267  ```
   268  
   269  #### BeforeAPIDelete
   270  BeforeDelete is only called before a 3rd-party client triggers a delete to the 
   271  database. By returning a non-nil `error` value, the item will not be deleted.
   272  
   273  ```go
   274  func (p *Post) BeforeAPIDelete(res http.ResponseWriter, req *http.Request) error {
   275      return nil
   276  }
   277  ```
   278  
   279  #### AfterAPIDelete
   280  AfterAPIDelete is only called after a 3rd-party client triggers a delete to the 
   281  database.
   282  
   283  ```go
   284  func (p *Post) AfterAPIDelete(res http.ResponseWriter, req *http.Request) error {
   285      return nil
   286  }
   287  ```
   288  
   289  #### BeforeAPIUpdate
   290  BeforeAPIUpdate is only called before a 3rd-party client triggers an update to 
   291  the database. By returning a non-nil `error` value, the item will not be updated.
   292  
   293  ```go
   294  func (p *Post) BeforeAPIUpdate(res http.ResponseWriter, req *http.Request) error {
   295      return nil
   296  }
   297  ```
   298  
   299  #### AfterAPIUpdate
   300  AfterAPIUpdate is only called after a 3rd-party client triggers an update to 
   301  the database.
   302  
   303  ```go
   304  func (p *Post) AfterAPIUpdate(res http.ResponseWriter, req *http.Request) error {
   305      return nil
   306  }
   307  ```
   308  
   309  #### BeforeAdminCreate
   310  BeforeAdminCreate is only called before a CMS Admin creates a new Content item.
   311  It is not called for subsequent saves to the item once it has been created and 
   312  assigned an ID. By returning a non-nil `error` value, the item will not be created.
   313  
   314  ```go
   315  func (p *Post) BeforeAdminCreate(res http.ResponseWriter, req *http.Request) error {
   316      return nil
   317  }
   318  ```
   319  
   320  #### AfterAdminCreate
   321  AfterAdminCreate is only called after a CMS Admin creates a new Content item.
   322  It is not called for subsequent saves to the item once it has been created and 
   323  assigned an ID.
   324  
   325  ```go
   326  func (p *Post) AfterAdminCreate(res http.ResponseWriter, req *http.Request) error {
   327      return nil
   328  }
   329  ```
   330  
   331  #### BeforeAdminUpdate
   332  BeforeAdminUpdate is only called before a CMS Admin updates a Content item. By 
   333  returning a non-nil `error`, the item will not be updated.
   334  
   335  ```go
   336  func (p *Post) BeforeAdminUpdate(res http.ResponseWriter, req *http.Request) error {
   337      return nil
   338  }
   339  ```
   340  
   341  #### AfterAdminUpdate
   342  AfterAdminUpdate is only called after a CMS Admin updates a Content item.
   343  
   344  ```go
   345  func (p *Post) AfterAdminUpdate(res http.ResponseWriter, req *http.Request) error {
   346      return nil
   347  }
   348  ```
   349  
   350  #### BeforeAdminDelete
   351  BeforeAdminDelete is only called before a CMS Admin deletes a Content item. By
   352  returning a non-nil `error` value, the item will not be deleted.
   353  
   354  ```go
   355  func (p *Post) BeforeAdminDelete(res http.ResponseWriter, req *http.Request) error {
   356      return nil
   357  }
   358  ```
   359  
   360  #### AfterAdminDelete
   361  AfterAdminDelete is only called after a CMS Admin deletes a Content item.
   362  
   363  ```go
   364  func (p *Post) AfterAdminDelete(res http.ResponseWriter, req *http.Request) error {
   365      return nil
   366  }
   367  ```
   368  
   369  #### BeforeEnable
   370  BeforeEnable is only applicable to Addon items, and is called before the addon
   371  changes status to "Enabled". By returning a non-nil `error` value, the addon
   372  will not become enabled.
   373  
   374  ```go
   375  func (p *Post) BeforeEnable(http.ResponseWriter, *http.Request) error {
   376      return nil
   377  }
   378  ```
   379  
   380  #### AfterEnable
   381  AfterEnable is only applicable to Addon items, and is called after the addon 
   382  changes status to "Enabled".
   383  ```go
   384  func (p *Post) AfterEnable(http.ResponseWriter, *http.Request) error {
   385      return nil
   386  }
   387  ```
   388  
   389  #### BeforeDisable
   390  BeforeDisable is only applicable to Addon items, and is called before the addon
   391  changes status to "Disabled". By returning a non-nil `error` value, the addon
   392  will not become disabled.
   393  ```go
   394  func (p *Post) BeforeDisable(http.ResponseWriter, *http.Request) error {
   395      return nil
   396  }
   397  ```
   398  
   399  #### AfterDisable
   400  AfterDisable is only applicable to Addon items, and is called after the addon 
   401  changes status to "Disabled".
   402  ```go
   403  func (p *Post) AfterDisable(http.ResponseWriter, *http.Request) error {
   404      return nil
   405  }
   406  ```
   407  
   408  Hookable is implemented by Item by default as no-ops which are expected to be overridden. 
   409  
   410  !!! note "Note" 
   411      returning an error from any of these `Hookable` methods will end the request, 
   412      causing it to halt immediately after the hook. For example, returning an `error` 
   413      from `BeforeDelete` will result in the content being kept in the database. 
   414      The same logic applies to all of these interface methods that return an error 
   415      - **the error defines the behavior**.
   416  
   417  ---
   418  
   419  ### [item.Identifiable](https://godoc.org/github.com/rpdict/ponzu/system/item#Identifiable)
   420  Identifiable enables a struct to have its ID set/get. Typically this is done to set an ID to -1 indicating it is new for DB inserts, since by default a newly initialized struct would have an ID of 0, the int zero-value, and BoltDB's starting key per bucket is 0, thus overwriting the first record.
   421  Most notable, Identifiable’s `String` method is used to set a meaningful display name for an Item. `String` is called by default in the Admin dashboard to show the Items of certain types, and in the default creation of an Item’s slug.
   422  Identifiable is implemented by Item by default.
   423  
   424  ##### Method Set
   425  ```go
   426  type Identifiable interface {
   427      ItemID() int
   428      SetItemID(int)
   429      UniqueID() uuid.UUID
   430      String() string
   431  }
   432  ```
   433  
   434  ##### Implementation
   435  `item.Identifiable` has a default implementation in the `system/item` package. 
   436  It is not advised to override these methods, with the exception of `String()`, 
   437  which is commonly used to set the display name of Content items when listed in 
   438  the CMS, and to customize slugs.
   439  
   440  ```go
   441  func (i Item) ItemID() int {
   442  	return i.ID
   443  }
   444  
   445  func (i *Item) SetItemID(id int) {
   446  	i.ID = id
   447  }
   448  
   449  func (i Item) UniqueID() uuid.UUID {
   450  	return i.UUID
   451  }
   452  
   453  func (i Item) String() string {
   454  	return fmt.Sprintf("Item ID: %s", i.UniqueID())
   455  }
   456  ```
   457  ---
   458  
   459  ### [item.Sluggable](https://godoc.org/github.com/rpdict/ponzu/system/item#Sluggable)
   460  Sluggable makes a struct locatable by URL with it's own path. As an Item implementing Sluggable, slugs may overlap. If this is an issue, make your content struct (or one which embeds Item) implement Sluggable and it will override the slug created by Item's `SetSlug` method with your own.
   461  It is not recommended to override `SetSlug`, but rather the `String` method on your content struct, which will have a similar, more predictable effect.
   462  Sluggable is implemented by Item by default.
   463  
   464  ##### Method Set
   465  ```go
   466  type Sluggable interface {
   467      SetSlug(string)
   468      ItemSlug() string
   469  }
   470  ```
   471  
   472  ##### Implementation
   473  `item.Sluggable` has a default implementation in the `system/item` package. It is
   474  possible to override these methods on your own Content types, but beware, behavior
   475  is undefined. It is tempting to override the `SetSlug()` method to customize your
   476  Content item slug, but try first to override the `String()` method found in the
   477  `item.Identifiable` interface instead. If you don't get the desired results, try
   478  `SetSlug()`.
   479  
   480  ```go
   481  func (i *Item) SetSlug(slug string) {
   482  	i.Slug = slug
   483  }
   484  
   485  func (i *Item) ItemSlug() string {
   486  	return i.Slug
   487  }
   488  ```
   489  ---
   490  
   491  
   492  ### [item.Sortable](https://godoc.org/github.com/rpdict/ponzu/system/item#Sortable)
   493  Sortable enables items to be sorted by time, as per the sort.Interface interface. Sortable is implemented by Item by default.
   494  
   495  ##### Method Set
   496  ```go
   497  type Sortable interface {
   498      Time() int64
   499      Touch() int64
   500  }
   501  ```
   502  
   503  ##### Implementation
   504  `item.Sortable` has a default implementation in the `system/item` package. It is
   505  possible to override these methods on your own Content type, but beware, behavior 
   506  is undefined.
   507  
   508  ```go
   509  func (i Item) Time() int64 {
   510  	return i.Timestamp
   511  }
   512  
   513  func (i Item) Touch() int64 {
   514  	return i.Updated
   515  }
   516  ```
   517