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