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