]> git.immae.eu Git - github/shaarli/Shaarli.git/blob - doc/md/Plugin-System.md
Generate HTML documentation using MkDocs (WIP)
[github/shaarli/Shaarli.git] / doc / md / Plugin-System.md
1 [**I am a developer.** Developer API.](#developer-api)
2
3 [**I am a template designer.** Guide for template designer.](#guide-for-template-designer)
4
5 ## Developer API
6
7 ### What can I do with plugins?
8
9 The plugin system let you:
10
11 * insert content into specific places across templates.
12 * alter data before templates rendering.
13 * alter data before saving new links.
14
15 ### How can I create a plugin for Shaarli?
16
17 First, chose a plugin name, such as `demo_plugin`.
18
19 Under `plugin` folder, create a folder named with your plugin name. Then create a <plugin_name>.php file in that folder.
20
21 You should have the following tree view:
22
23 ```
24 | index.php
25 | plugins/
26 |---| demo_plugin/
27 | |---| demo_plugin.php
28 ```
29
30 ### Plugin initialization
31
32 At the beginning of Shaarli execution, all enabled plugins are loaded. At this point, the plugin system looks for an `init()` function to execute and run it if it exists. This function must be named this way, and takes the `ConfigManager` as parameter.
33
34 <plugin_name>_init($conf)
35
36 This function can be used to create initial data, load default settings, etc. But also to set *plugin errors*. If the initialization function returns an array of strings, they will be understand as errors, and displayed in the header to logged in users.
37
38 ### Understanding hooks
39
40 A plugin is a set of functions. Each function will be triggered by the plugin system at certain point in Shaarli execution.
41
42 These functions need to be named with this pattern:
43
44 ```
45 hook_<plugin_name>_<hook_name>($data, $conf)
46 ```
47
48 Parameters:
49
50 - data: see [$data section](https://github.com/shaarli/Shaarli/wiki/Plugin-System#plugins-data)
51 - conf: the `ConfigManager` instance.
52
53 For exemple, if my plugin want to add data to the header, this function is needed:
54
55 hook_demo_plugin_render_header
56
57 If this function is declared, and the plugin enabled, it will be called every time Shaarli is rendering the header.
58
59 ### Plugin's data
60
61 #### Parameters
62
63 Every hook function has a `$data` parameter. Its content differs for each hooks.
64
65 **This parameter needs to be returned every time**, otherwise data is lost.
66
67 return $data;
68
69 #### Filling templates placeholder
70
71 Template placeholders are displayed in template in specific places.
72
73 RainTPL displays every element contained in the placeholder's array. These element can be added by plugins.
74
75 For example, let's add a value in the placeholder `top_placeholder` which is displayed at the top of my page:
76
77 ```php
78 $data['top_placeholder'][] = 'My content';
79 # OR
80 array_push($data['top_placeholder'], 'My', 'content');
81
82 return $data;
83 ```
84
85 #### Data manipulation
86
87 When a page is displayed, every variable send to the template engine is passed to plugins before that in `$data`.
88
89 The data contained by this array can be altered before template rendering.
90
91 For exemple, in linklist, it is possible to alter every title:
92
93 ```php
94 // mind the reference if you want $data to be altered
95 foreach ($data['links'] as &$value) {
96 // String reverse every title.
97 $value['title'] = strrev($value['title']);
98 }
99
100 return $data;
101 ```
102
103 ### Metadata
104
105 Every plugin needs a `<plugin_name>.meta` file, which is in fact an `.ini` file (`KEY="VALUE"`), to be listed in plugin administration.
106
107 Each file contain two keys:
108
109 * `description`: plugin description
110 * `parameters`: user parameter names, separated by a `;`.
111 * `parameter.<PARAMETER_NAME>`: add a text description the specified parameter.
112
113 > Note: In PHP, `parse_ini_file()` seems to want strings to be between by quotes `"` in the ini file.
114
115 ### It's not working!
116
117 Use `demo_plugin` as a functional example. It covers most of the plugin system features.
118
119 If it's still not working, please [open an issue](https://github.com/shaarli/Shaarli/issues/new).
120
121 ### Hooks
122
123 | Hooks | Description |
124 | ------------- |:-------------:|
125 | [render_header](#render_header) | Allow plugin to add content in page headers. |
126 | [render_includes](#render_includes) | Allow plugin to include their own CSS files. |
127 | [render_footer](#render_footer) | Allow plugin to add content in page footer and include their own JS files. |
128 | [render_linklist](#render_linklist) | It allows to add content at the begining and end of the page, after every link displayed and to alter link data. |
129 | [render_editlink](#render_editlink) | Allow to add fields in the form, or display elements. |
130 | [render_tools](#render_tools) | Allow to add content at the end of the page. |
131 | [render_picwall](#render_picwall) | Allow to add content at the top and bottom of the page. |
132 | [render_tagcloud](#render_tagcloud) | Allow to add content at the top and bottom of the page, and after all tags. |
133 | [render_taglist](#render_taglist) | Allow to add content at the top and bottom of the page, and after all tags. |
134 | [render_daily](#render_daily) | Allow to add content at the top and bottom of the page, the bottom of each link and to alter data. |
135 | [render_feed](#render_feed) | Allow to do add tags in RSS and ATOM feeds. |
136 | [save_link](#save_link) | Allow to alter the link being saved in the datastore. |
137 | [delete_link](#delete_link) | Allow to do an action before a link is deleted from the datastore. |
138
139
140
141 #### render_header
142
143 Triggered on every page.
144
145 Allow plugin to add content in page headers.
146
147 ##### Data
148
149 `$data` is an array containing:
150
151 * `_PAGE_`: current target page (eg: `linklist`, `picwall`, etc.).
152 * `_LOGGEDIN_`: true if user is logged in, false otherwise.
153
154 ##### Template placeholders
155
156 Items can be displayed in templates by adding an entry in `$data['<placeholder>']` array.
157
158 List of placeholders:
159
160 * `buttons_toolbar`: after the list of buttons in the header.
161
162 ![buttons_toolbar_example](http://i.imgur.com/ssJUOrt.png)
163
164 * `fields_toolbar`: after search fields in the header.
165
166 > Note: This will only be called in linklist.
167
168 ![fields_toolbar_example](http://i.imgur.com/3GMifI2.png)
169
170 #### render_includes
171
172 Triggered on every page.
173
174 Allow plugin to include their own CSS files.
175
176 ##### Data
177
178 `$data` is an array containing:
179
180 * `_PAGE_`: current target page (eg: `linklist`, `picwall`, etc.).
181 * `_LOGGEDIN_`: true if user is logged in, false otherwise.
182
183 ##### Template placeholders
184
185 Items can be displayed in templates by adding an entry in `$data['<placeholder>']` array.
186
187 List of placeholders:
188
189 * `css_files`: called after loading default CSS.
190
191 > Note: only add the path of the CSS file. E.g: `plugins/demo_plugin/custom_demo.css`.
192
193 #### render_footer
194
195 Triggered on every page.
196
197 Allow plugin to add content in page footer and include their own JS files.
198
199 ##### Data
200
201 `$data` is an array containing:
202
203 * `_PAGE_`: current target page (eg: `linklist`, `picwall`, etc.).
204 * `_LOGGEDIN_`: true if user is logged in, false otherwise.
205
206 ##### Template placeholders
207
208 Items can be displayed in templates by adding an entry in `$data['<placeholder>']` array.
209
210 List of placeholders:
211
212 * `text`: called after the end of the footer text.
213 * `endofpage`: called at the end of the page.
214
215 ![text_example](http://i.imgur.com/L5S2YEH.png)
216
217 * `js_files`: called at the end of the page, to include custom JS scripts.
218
219 > Note: only add the path of the JS file. E.g: `plugins/demo_plugin/custom_demo.js`.
220
221 #### render_linklist
222
223 Triggered when `linklist` is displayed (list of links, permalink, search, tag filtered, etc.).
224
225 It allows to add content at the begining and end of the page, after every link displayed and to alter link data.
226
227 ##### Data
228
229 `$data` is an array containing:
230
231 * `_LOGGEDIN_`: true if user is logged in, false otherwise.
232 * All templates data, including links.
233
234 ##### Template placeholders
235
236 Items can be displayed in templates by adding an entry in `$data['<placeholder>']` array.
237
238 List of placeholders:
239
240 * `action_plugin`: next to the button "private only" at the top and bottom of the page.
241
242 ![action_plugin_example](http://i.imgur.com/Q12PWg0.png)
243
244 * `link_plugin`: for every link, between permalink and link URL.
245
246 ![link_plugin_example](http://i.imgur.com/3oDPhWx.png)
247
248 * `plugin_start_zone`: before displaying the template content.
249
250 ![plugin_start_zone_example](http://i.imgur.com/OVBkGy3.png)
251
252 * `plugin_end_zone`: after displaying the template content.
253
254 ![plugin_end_zone_example](http://i.imgur.com/6IoRuop.png)
255
256 #### render_editlink
257
258 Triggered when the link edition form is displayed.
259
260 Allow to add fields in the form, or display elements.
261
262 ##### Data
263
264 `$data` is an array containing:
265
266 * All templates data.
267
268 ##### Template placeholders
269
270 Items can be displayed in templates by adding an entry in `$data['<placeholder>']` array.
271
272 List of placeholders:
273
274 * `edit_link_plugin`: after tags field.
275
276 ![edit_link_plugin_example](http://i.imgur.com/5u17Ens.png)
277
278 #### render_tools
279
280 Triggered when the "tools" page is displayed.
281
282 Allow to add content at the end of the page.
283
284 ##### Data
285
286 `$data` is an array containing:
287
288 * All templates data.
289
290 ##### Template placeholders
291
292 Items can be displayed in templates by adding an entry in `$data['<placeholder>']` array.
293
294 List of placeholders:
295
296 * `tools_plugin`: at the end of the page.
297
298 ![tools_plugin_example](http://i.imgur.com/Bqhu9oQ.png)
299
300 #### render_picwall
301
302 Triggered when picwall is displayed.
303
304 Allow to add content at the top and bottom of the page.
305
306 ##### Data
307
308 `$data` is an array containing:
309
310 * `_LOGGEDIN_`: true if user is logged in, false otherwise.
311 * All templates data.
312
313 ##### Template placeholders
314
315 Items can be displayed in templates by adding an entry in `$data['<placeholder>']` array.
316
317 List of placeholders:
318
319 * `plugin_start_zone`: before displaying the template content.
320
321 * `plugin_end_zone`: after displaying the template content.
322
323 ![plugin_start_end_zone_example](http://i.imgur.com/tVTQFER.png)
324
325 #### render_tagcloud
326
327 Triggered when tagcloud is displayed.
328
329 Allow to add content at the top and bottom of the page.
330
331 ##### Data
332
333 `$data` is an array containing:
334
335 * `_LOGGEDIN_`: true if user is logged in, false otherwise.
336 * All templates data.
337
338 ##### Template placeholders
339
340 Items can be displayed in templates by adding an entry in `$data['<placeholder>']` array.
341
342 List of placeholders:
343
344 * `plugin_start_zone`: before displaying the template content.
345
346 * `plugin_end_zone`: after displaying the template content.
347
348 For each tag, the following placeholder can be used:
349
350 * `tag_plugin`: after each tag
351
352 ![plugin_start_end_zone_example](http://i.imgur.com/vHmyT3a.png)
353
354
355 #### render_taglist
356
357 Triggered when taglist is displayed.
358
359 Allow to add content at the top and bottom of the page.
360
361 ##### Data
362
363 `$data` is an array containing:
364
365 * `_LOGGEDIN_`: true if user is logged in, false otherwise.
366 * All templates data.
367
368 ##### Template placeholders
369
370 Items can be displayed in templates by adding an entry in `$data['<placeholder>']` array.
371
372 List of placeholders:
373
374 * `plugin_start_zone`: before displaying the template content.
375
376 * `plugin_end_zone`: after displaying the template content.
377
378 For each tag, the following placeholder can be used:
379
380 * `tag_plugin`: after each tag
381
382 #### render_daily
383
384 Triggered when tagcloud is displayed.
385
386 Allow to add content at the top and bottom of the page, the bottom of each link and to alter data.
387
388 ##### Data
389
390 `$data` is an array containing:
391
392 * `_LOGGEDIN_`: true if user is logged in, false otherwise.
393 * All templates data, including links.
394
395 ##### Template placeholders
396
397 Items can be displayed in templates by adding an entry in `$data['<placeholder>']` array.
398
399 List of placeholders:
400
401 * `link_plugin`: used at bottom of each link.
402
403 ![link_plugin_example](http://i.imgur.com/hzhMfSZ.png)
404
405 * `plugin_start_zone`: before displaying the template content.
406
407 * `plugin_end_zone`: after displaying the template content.
408
409 #### render_feed
410
411 Triggered when the ATOM or RSS feed is displayed.
412
413 Allow to add tags in the feed, either in the header or for each items. Items (links) can also be altered before being rendered.
414
415 ##### Data
416
417 `$data` is an array containing:
418
419 * `_LOGGEDIN_`: true if user is logged in, false otherwise.
420 * `_PAGE_`: containing either `rss` or `atom`.
421 * All templates data, including links.
422
423 ##### Template placeholders
424
425 Tags can be added in feeds by adding an entry in `$data['<placeholder>']` array.
426
427 List of placeholders:
428
429 * `feed_plugins_header`: used as a header tag in the feed.
430
431 For each links:
432
433 * `feed_plugins`: additional tag for every link entry.
434
435 #### save_link
436
437 Triggered when a link is save (new link or edit).
438
439 Allow to alter the link being saved in the datastore.
440
441 ##### Data
442
443 `$data` is an array containing the link being saved:
444
445 * id
446 * title
447 * url
448 * shorturl
449 * description
450 * private
451 * tags
452 * created
453 * updated
454
455
456 #### delete_link
457
458 Triggered when a link is deleted.
459
460 Allow to execute any action before the link is actually removed from the datastore
461
462 ##### Data
463
464 `$data` is an array containing the link being saved:
465
466 * id
467 * title
468 * url
469 * shorturl
470 * description
471 * private
472 * tags
473 * created
474 * updated
475
476 ## Guide for template designer
477
478 ### Plugin administration
479
480 Your theme must include a plugin administration page: `pluginsadmin.html`.
481
482 > Note: repo's template link needs to be added when the PR is merged.
483
484 Use the default one as an example.
485
486 Aside from classic RainTPL loops, plugins order is handle by JavaScript. You can just include `plugin_admin.js`, only if:
487
488 * you're using a table.
489 * you call orderUp() and orderUp() onclick on arrows.
490 * you add data-line and data-order to your rows.
491
492 Otherwise, you can use your own JS as long as this field is send by the form:
493
494 <input type="hidden" name="order_{$key}" value="{$counter}">
495
496 ### Placeholder system
497
498 In order to make plugins work with every custom themes, you need to add variable placeholder in your templates.
499
500 It's a RainTPL loop like this:
501
502 {loop="$plugin_variable"}
503 {$value}
504 {/loop}
505
506 You should enable `demo_plugin` for testing purpose, since it uses every placeholder available.
507
508 ### List of placeholders
509
510 **page.header.html**
511
512 At the end of the menu:
513
514 {loop="$plugins_header.buttons_toolbar"}
515 {$value}
516 {/loop}
517
518 At the end of file, before clearing floating blocks:
519
520 {if="!empty($plugin_errors) && isLoggedIn()"}
521 <ul class="errors">
522 {loop="plugin_errors"}
523 <li>{$value}</li>
524 {/loop}
525 </ul>
526 {/if}
527
528 **includes.html**
529
530 At the end of the file:
531
532 ```html
533 {loop="$plugins_includes.css_files"}
534 <link type="text/css" rel="stylesheet" href="{$value}#"/>
535 {/loop}
536 ```
537
538 **page.footer.html**
539
540 At the end of your footer notes:
541
542 ```html
543 {loop="$plugins_footer.text"}
544 {$value}
545 {/loop}
546 ```
547
548 At the end of file:
549
550 ```html
551 {loop="$plugins_footer.js_files"}
552 <script src="{$value}#"></script>
553 {/loop}
554 ```
555
556 **linklist.html**
557
558 After search fields:
559
560 ```html
561 {loop="$plugins_header.fields_toolbar"}
562 {$value}
563 {/loop}
564 ```
565
566 Before displaying the link list (after paging):
567
568 ```html
569 {loop="$plugin_start_zone"}
570 {$value}
571 {/loop}
572 ```
573
574 For every links (icons):
575
576 ```html
577 {loop="$value.link_plugin"}
578 <span>{$value}</span>
579 {/loop}
580 ```
581
582 Before end paging:
583
584 ```html
585 {loop="$plugin_end_zone"}
586 {$value}
587 {/loop}
588 ```
589
590 **linklist.paging.html**
591
592 After the "private only" icon:
593
594 ```html
595 {loop="$action_plugin"}
596 {$value}
597 {/loop}
598 ```
599
600 **editlink.html**
601
602 After tags field:
603
604 ```html
605 {loop="$edit_link_plugin"}
606 {$value}
607 {/loop}
608 ```
609
610 **tools.html**
611
612 After the last tool:
613
614 ```html
615 {loop="$tools_plugin"}
616 {$value}
617 {/loop}
618 ```
619
620 **picwall.html**
621
622 Top:
623
624 ```html
625 <div id="plugin_zone_start_picwall" class="plugin_zone">
626 {loop="$plugin_start_zone"}
627 {$value}
628 {/loop}
629 </div>
630 ```
631
632 Bottom:
633
634 ```html
635 <div id="plugin_zone_end_picwall" class="plugin_zone">
636 {loop="$plugin_end_zone"}
637 {$value}
638 {/loop}
639 </div>
640 ```
641
642 **tagcloud.html**
643
644 Top:
645
646 ```html
647 <div id="plugin_zone_start_tagcloud" class="plugin_zone">
648 {loop="$plugin_start_zone"}
649 {$value}
650 {/loop}
651 </div>
652 ```
653
654 Bottom:
655
656 ```html
657 <div id="plugin_zone_end_tagcloud" class="plugin_zone">
658 {loop="$plugin_end_zone"}
659 {$value}
660 {/loop}
661 </div>
662 ```
663
664 **daily.html**
665
666 Top:
667
668 ```html
669 <div id="plugin_zone_start_picwall" class="plugin_zone">
670 {loop="$plugin_start_zone"}
671 {$value}
672 {/loop}
673 </div>
674 ```
675
676 After every link:
677
678 ```html
679 <div class="dailyEntryFooter">
680 {loop="$link.link_plugin"}
681 {$value}
682 {/loop}
683 </div>
684 ```
685
686 Bottom:
687
688 ```html
689 <div id="plugin_zone_end_picwall" class="plugin_zone">
690 {loop="$plugin_end_zone"}
691 {$value}
692 {/loop}
693 </div>
694 ```
695
696 **feed.atom.xml** and **feed.rss.xml**:
697
698 In headers tags section:
699 ```xml
700 {loop="$feed_plugins_header"}
701 {$value}
702 {/loop}
703 ```
704
705 After each entry:
706 ```xml
707 {loop="$value.feed_plugins"}
708 {$value}
709 {/loop}
710 ```