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