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