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