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