]> git.immae.eu Git - github/shaarli/Shaarli.git/blame - doc/md/Plugin-System.md
documentation: fix rendering and internal references
[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
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
b230bf20
A
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
992af0b9
V
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```
b230bf20 47hook_<plugin_name>_<hook_name>($data, $conf)
992af0b9
V
48```
49
b230bf20
A
50Parameters:
51
43ad7c8e
V
52- data: see [$data section](https://github.com/shaarli/Shaarli/wiki/Plugin-System#plugins-data)
53- conf: the `ConfigManager` instance.
b230bf20 54
992af0b9
V
55For exemple, if my plugin want to add data to the header, this function is needed:
56
b230bf20 57 hook_demo_plugin_render_header
992af0b9
V
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
53ed6d7d 80$data['top_placeholder'][] = 'My content';
992af0b9 81# OR
53ed6d7d 82array_push($data['top_placeholder'], 'My', 'content');
992af0b9
V
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
53ed6d7d 97foreach ($data['links'] as &$value) {
992af0b9 98 // String reverse every title.
53ed6d7d 99 $value['title'] = strrev($value['title']);
992af0b9
V
100}
101
102return $data;
103```
104
5409ade2
A
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
43ad7c8e
V
111- `description`: plugin description
112- `parameters`: user parameter names, separated by a `;`.
113- `parameter.<PARAMETER_NAME>`: add a text description the specified parameter.
5409ade2
A
114
115> Note: In PHP, `parse_ini_file()` seems to want strings to be between by quotes `"` in the ini file.
116
992af0b9
V
117### It's not working!
118
119Use `demo_plugin` as a functional example. It covers most of the plugin system features.
120
53ed6d7d 121If it's still not working, please [open an issue](https://github.com/shaarli/Shaarli/issues/new).
992af0b9
V
122
123### Hooks
124
125| Hooks | Description |
126| ------------- |:-------------:|
53ed6d7d 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. |
b230bf20 140
992af0b9
V
141
142
143#### render_header
144
145Triggered on every page.
146
147Allow plugin to add content in page headers.
148
149##### Data
150
151`$data` is an array containing:
152
43ad7c8e
V
153- `_PAGE_`: current target page (eg: `linklist`, `picwall`, etc.).
154- `_LOGGEDIN_`: true if user is logged in, false otherwise.
992af0b9
V
155
156##### Template placeholders
157
53ed6d7d 158Items can be displayed in templates by adding an entry in `$data['<placeholder>']` array.
992af0b9
V
159
160List of placeholders:
161
43ad7c8e 162- `buttons_toolbar`: after the list of buttons in the header.
992af0b9 163
53ed6d7d 164![buttons_toolbar_example](http://i.imgur.com/ssJUOrt.png)
992af0b9 165
43ad7c8e 166- `fields_toolbar`: after search fields in the header.
992af0b9
V
167
168> Note: This will only be called in linklist.
169
53ed6d7d 170![fields_toolbar_example](http://i.imgur.com/3GMifI2.png)
992af0b9
V
171
172#### render_includes
173
174Triggered on every page.
175
176Allow plugin to include their own CSS files.
177
178##### Data
179
180`$data` is an array containing:
181
43ad7c8e
V
182- `_PAGE_`: current target page (eg: `linklist`, `picwall`, etc.).
183- `_LOGGEDIN_`: true if user is logged in, false otherwise.
992af0b9
V
184
185##### Template placeholders
186
53ed6d7d 187Items can be displayed in templates by adding an entry in `$data['<placeholder>']` array.
992af0b9
V
188
189List of placeholders:
190
43ad7c8e 191- `css_files`: called after loading default CSS.
992af0b9
V
192
193> Note: only add the path of the CSS file. E.g: `plugins/demo_plugin/custom_demo.css`.
194
195#### render_footer
196
197Triggered on every page.
198
199Allow plugin to add content in page footer and include their own JS files.
200
201##### Data
202
203`$data` is an array containing:
204
43ad7c8e
V
205- `_PAGE_`: current target page (eg: `linklist`, `picwall`, etc.).
206- `_LOGGEDIN_`: true if user is logged in, false otherwise.
992af0b9
V
207
208##### Template placeholders
209
53ed6d7d 210Items can be displayed in templates by adding an entry in `$data['<placeholder>']` array.
992af0b9
V
211
212List of placeholders:
213
43ad7c8e
V
214- `text`: called after the end of the footer text.
215- `endofpage`: called at the end of the page.
992af0b9 216
53ed6d7d 217![text_example](http://i.imgur.com/L5S2YEH.png)
992af0b9 218
43ad7c8e 219- `js_files`: called at the end of the page, to include custom JS scripts.
992af0b9
V
220
221> Note: only add the path of the JS file. E.g: `plugins/demo_plugin/custom_demo.js`.
222
223#### render_linklist
224
225Triggered when `linklist` is displayed (list of links, permalink, search, tag filtered, etc.).
226
227It 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
43ad7c8e
V
233- `_LOGGEDIN_`: true if user is logged in, false otherwise.
234- All templates data, including links.
992af0b9
V
235
236##### Template placeholders
237
53ed6d7d 238Items can be displayed in templates by adding an entry in `$data['<placeholder>']` array.
992af0b9
V
239
240List of placeholders:
241
43ad7c8e 242- `action_plugin`: next to the button "private only" at the top and bottom of the page.
992af0b9 243
53ed6d7d 244![action_plugin_example](http://i.imgur.com/Q12PWg0.png)
992af0b9 245
43ad7c8e 246- `link_plugin`: for every link, between permalink and link URL.
992af0b9 247
53ed6d7d 248![link_plugin_example](http://i.imgur.com/3oDPhWx.png)
992af0b9 249
43ad7c8e 250- `plugin_start_zone`: before displaying the template content.
992af0b9 251
53ed6d7d 252![plugin_start_zone_example](http://i.imgur.com/OVBkGy3.png)
992af0b9 253
43ad7c8e 254- `plugin_end_zone`: after displaying the template content.
992af0b9 255
53ed6d7d 256![plugin_end_zone_example](http://i.imgur.com/6IoRuop.png)
992af0b9
V
257
258#### render_editlink
259
260Triggered when the link edition form is displayed.
261
262Allow to add fields in the form, or display elements.
263
264##### Data
265
266`$data` is an array containing:
267
43ad7c8e 268- All templates data.
992af0b9
V
269
270##### Template placeholders
271
53ed6d7d 272Items can be displayed in templates by adding an entry in `$data['<placeholder>']` array.
992af0b9
V
273
274List of placeholders:
275
43ad7c8e 276- `edit_link_plugin`: after tags field.
992af0b9 277
53ed6d7d 278![edit_link_plugin_example](http://i.imgur.com/5u17Ens.png)
992af0b9
V
279
280#### render_tools
281
282Triggered when the "tools" page is displayed.
283
284Allow to add content at the end of the page.
285
286##### Data
287
288`$data` is an array containing:
289
43ad7c8e 290- All templates data.
992af0b9
V
291
292##### Template placeholders
293
53ed6d7d 294Items can be displayed in templates by adding an entry in `$data['<placeholder>']` array.
992af0b9
V
295
296List of placeholders:
297
43ad7c8e 298- `tools_plugin`: at the end of the page.
992af0b9 299
53ed6d7d 300![tools_plugin_example](http://i.imgur.com/Bqhu9oQ.png)
992af0b9
V
301
302#### render_picwall
303
304Triggered when picwall is displayed.
305
306Allow to add content at the top and bottom of the page.
307
308##### Data
309
310`$data` is an array containing:
311
43ad7c8e
V
312- `_LOGGEDIN_`: true if user is logged in, false otherwise.
313- All templates data.
992af0b9
V
314
315##### Template placeholders
316
53ed6d7d 317Items can be displayed in templates by adding an entry in `$data['<placeholder>']` array.
992af0b9
V
318
319List of placeholders:
320
43ad7c8e
V
321- `plugin_start_zone`: before displaying the template content.
322- `plugin_end_zone`: after displaying the template content.
992af0b9 323
53ed6d7d 324![plugin_start_end_zone_example](http://i.imgur.com/tVTQFER.png)
992af0b9
V
325
326#### render_tagcloud
327
328Triggered when tagcloud is displayed.
329
330Allow to add content at the top and bottom of the page.
331
332##### Data
333
334`$data` is an array containing:
335
43ad7c8e
V
336- `_LOGGEDIN_`: true if user is logged in, false otherwise.
337- All templates data.
992af0b9
V
338
339##### Template placeholders
340
53ed6d7d 341Items can be displayed in templates by adding an entry in `$data['<placeholder>']` array.
992af0b9
V
342
343List of placeholders:
344
43ad7c8e
V
345- `plugin_start_zone`: before displaying the template content.
346- `plugin_end_zone`: after displaying the template content.
992af0b9 347
b230bf20
A
348For each tag, the following placeholder can be used:
349
43ad7c8e 350- `tag_plugin`: after each tag
b230bf20 351
53ed6d7d 352![plugin_start_end_zone_example](http://i.imgur.com/vHmyT3a.png)
992af0b9 353
b230bf20
A
354
355#### render_taglist
356
357Triggered when taglist is displayed.
358
359Allow to add content at the top and bottom of the page.
360
361##### Data
362
363`$data` is an array containing:
364
43ad7c8e
V
365- `_LOGGEDIN_`: true if user is logged in, false otherwise.
366- All templates data.
b230bf20
A
367
368##### Template placeholders
369
53ed6d7d 370Items can be displayed in templates by adding an entry in `$data['<placeholder>']` array.
b230bf20
A
371
372List of placeholders:
373
43ad7c8e
V
374- `plugin_start_zone`: before displaying the template content.
375- `plugin_end_zone`: after displaying the template content.
b230bf20
A
376
377For each tag, the following placeholder can be used:
378
43ad7c8e 379- `tag_plugin`: after each tag
b230bf20 380
992af0b9
V
381#### render_daily
382
383Triggered when tagcloud is displayed.
384
385Allow 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
43ad7c8e
V
391- `_LOGGEDIN_`: true if user is logged in, false otherwise.
392- All templates data, including links.
992af0b9
V
393
394##### Template placeholders
395
53ed6d7d 396Items can be displayed in templates by adding an entry in `$data['<placeholder>']` array.
992af0b9
V
397
398List of placeholders:
399
43ad7c8e 400- `link_plugin`: used at bottom of each link.
992af0b9 401
53ed6d7d 402![link_plugin_example](http://i.imgur.com/hzhMfSZ.png)
992af0b9 403
43ad7c8e
V
404- `plugin_start_zone`: before displaying the template content.
405- `plugin_end_zone`: after displaying the template content.
992af0b9 406
b230bf20
A
407#### render_feed
408
409Triggered when the ATOM or RSS feed is displayed.
410
411Allow 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
43ad7c8e
V
417- `_LOGGEDIN_`: true if user is logged in, false otherwise.
418- `_PAGE_`: containing either `rss` or `atom`.
419- All templates data, including links.
b230bf20
A
420
421##### Template placeholders
422
53ed6d7d 423Tags can be added in feeds by adding an entry in `$data['<placeholder>']` array.
b230bf20
A
424
425List of placeholders:
426
43ad7c8e 427- `feed_plugins_header`: used as a header tag in the feed.
b230bf20
A
428
429For each links:
430
43ad7c8e 431- `feed_plugins`: additional tag for every link entry.
b230bf20
A
432
433#### save_link
992af0b9
V
434
435Triggered when a link is save (new link or edit).
436
437Allow to alter the link being saved in the datastore.
438
439##### Data
440
441`$data` is an array containing the link being saved:
442
43ad7c8e
V
443- id
444- title
445- url
446- shorturl
447- description
448- private
449- tags
450- created
451- updated
b230bf20
A
452
453
454#### delete_link
455
456Triggered when a link is deleted.
457
458Allow 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
43ad7c8e
V
464- id
465- title
466- url
467- shorturl
468- description
469- private
470- tags
471- created
472- updated
992af0b9
V
473
474## Guide for template designer
475
5409ade2
A
476### Plugin administration
477
478Your 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
482Use the default one as an example.
483
484Aside from classic RainTPL loops, plugins order is handle by JavaScript. You can just include `plugin_admin.js`, only if:
485
43ad7c8e
V
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.
5409ade2
A
489
490Otherwise, 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
992af0b9
V
494### Placeholder system
495
496In order to make plugins work with every custom themes, you need to add variable placeholder in your templates.
497
498It's a RainTPL loop like this:
499
500 {loop="$plugin_variable"}
501 {$value}
502 {/loop}
503
504You should enable `demo_plugin` for testing purpose, since it uses every placeholder available.
505
506### List of placeholders
507
508**page.header.html**
509
510At the end of the menu:
511
512 {loop="$plugins_header.buttons_toolbar"}
513 {$value}
514 {/loop}
515
5409ade2
A
516At 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
992af0b9
V
526**includes.html**
527
528At 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
538At the end of your footer notes:
539
540```html
541{loop="$plugins_footer.text"}
542 {$value}
543{/loop}
544```
545
546At 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
556After search fields:
557
558```html
559{loop="$plugins_header.fields_toolbar"}
560 {$value}
561{/loop}
562```
563
564Before displaying the link list (after paging):
565
566```html
567{loop="$plugin_start_zone"}
568 {$value}
569{/loop}
570```
571
572For every links (icons):
573
574```html
575{loop="$value.link_plugin"}
576 <span>{$value}</span>
577{/loop}
578```
579
580Before end paging:
581
582```html
583{loop="$plugin_end_zone"}
584 {$value}
585{/loop}
586```
587
588**linklist.paging.html**
589
590After the "private only" icon:
591
592```html
593{loop="$action_plugin"}
594 {$value}
595{/loop}
596```
597
598**editlink.html**
599
600After tags field:
601
602```html
603{loop="$edit_link_plugin"}
604 {$value}
605{/loop}
606```
607
608**tools.html**
609
610After the last tool:
611
612```html
613{loop="$tools_plugin"}
614 {$value}
615{/loop}
616```
617
618**picwall.html**
619
620Top:
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
630Bottom:
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
642Top:
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
652Bottom:
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
664Top:
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
674After every link:
675
676```html
677<div class="dailyEntryFooter">
678 {loop="$link.link_plugin"}
679 {$value}
680 {/loop}
681</div>
682```
683
684Bottom:
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```
b230bf20
A
693
694**feed.atom.xml** and **feed.rss.xml**:
695
696In headers tags section:
697```xml
698{loop="$feed_plugins_header"}
699 {$value}
700{/loop}
701```
702
703After each entry:
704```xml
705{loop="$value.feed_plugins"}
706 {$value}
707{/loop}
708```