1Plugin coding guidelines
2========================
3
4In addition to the Elgg Coding Standards, these are guidelines for creating plugins.
5Core plugins are being updated to this format and all plugin authors should follow
6these guidelines in their own plugins.
7
8.. seealso::
9
10   Be sure to follow the :doc:`plugins/plugin-skeleton` for your plugin's layout.
11
12.. warning::
13
14  :doc:`dont-modify-core`
15
16.. contents:: Contents
17   :local:
18   :depth: 1
19
20Use standardized routing with page handlers
21-------------------------------------------
22
23- Example: Bookmarks plugin
24- Page handlers should accept the following standard URLs:
25   +---------------+-----------------------------------+
26   | Purpose       | URL                               |
27   +===============+===================================+
28   | All           | page_handler/all                  |
29   +---------------+-----------------------------------+
30   | User          | page_handler/owner/<username>     |
31   +---------------+-----------------------------------+
32   | User friends’ | page_handler/friends/<username>   |
33   +---------------+-----------------------------------+
34   | Single entity | page_handler/view/<guid>/<title>  |
35   +---------------+-----------------------------------+
36   | Add           | page_handler/add/<container_guid> |
37   +---------------+-----------------------------------+
38   | Edit          | page_handler/edit/<guid>          |
39   +---------------+-----------------------------------+
40   | Group list    | page_handler/group/<guid>/owner   |
41   +---------------+-----------------------------------+
42- Include page handler scripts from the page handler. Almost every page handler should have a page handler script. (Example: ``bookmarks/all`` => ``mod/bookmarks/views/default/resources/bookmarks/all.php``)
43- Pass arguments like entity guids to the resource view via ``$vars`` in ``elgg_view_resource()``.
44- Call ``elgg_gatekeeper()`` and ``elgg_admin_gatekeeper()`` in the page handler function if required.
45- The group URL should use views like ``resources/groups/*.php`` to render pages.
46- Page handlers should not contain HTML.
47
48Use standardized page handlers and scripts
49------------------------------------------
50
51- Example: Bookmarks plugin
52- Store page functionality in ``mod/<plugin>/views/default/resources/<page_handler>/<page_name>.php``
53- Use ``elgg_view_resource('<page_handler>/<page_name>')`` to render that.
54- Use the default page layout in page handler scripts: ``$content = elgg_view_layout('default', $options);``
55- Page handler scripts should not contain HTML
56- Call ``elgg_push_breadcrumb()`` in the page handler scripts.
57- No need to worry about setting the page owner if the URLs are in the standardized format
58- For group content, check the ``container_guid`` by using ``elgg_get_page_owner_entity()``
59
60The object/<subtype> view
61-------------------------
62
63- Example: Bookmarks plugin
64- Make sure there are views for ``$vars['full_view'] == true`` and ``$vars['full_view'] == false``
65- Check for the object in ``$vars['entity']`` . Use ``elgg_instance_of()`` to make sure it’s the type entity you want. Return ``true`` to short circuit the view if the entity is missing or wrong.
66- Use the new list body and list metadata views to help format. You should use almost no markup in these views.
67- Update action structure - Example: Bookmarks plugin.
68- Namespace action files and action names (example: ``mod/blog/actions/blog/save.php`` => ``action/blog/save``)
69- Use the following action URLs:
70   +---------+----------------------+
71   | Purpose | URL                  |
72   +=========+======================+
73   | Add     | action/plugin/save   |
74   +---------+----------------------+
75   | Edit    | action/plugin/save   |
76   +---------+----------------------+
77   | Delete  | action/plugin/delete |
78   +---------+----------------------+
79- Make the delete action accept ``action/<handler>/delete?guid=<guid>`` so the metadata entity menu has the correct URL by default
80
81Actions
82-------
83
84Actions are transient states to perform an action such as updating the database or sending a notification to a user. Used correctly, actions provide a level of access control and prevent against CSRF attacks.
85
86Actions require action (CSRF) tokens to be submitted via GET/POST, but these are added automatically by elgg_view_form() and by using the ``is_action`` argument of the ``output/url`` view.
87
88Action best practices
89^^^^^^^^^^^^^^^^^^^^^
90
91Action files are included within Elgg's action system; like views, they are *not* regular scripts executable by users. Do not boot the Elgg core in your file and direct users to load it directly.
92
93Because actions are time-sensitive they are not suitable for links in emails or other delayed notifications. An example of this would be invitations to join a group. The clean way to create an invitation link is to create a page handler for invitations and email that link to the user. It is then the page handler's responsibility to create the action links for a user to join or ignore the invitation request.
94
95Consider that actions may be submitted via XHR requests, not just links or form submissions.
96
97Directly calling a file
98-----------------------
99
100This is an easy one: **Don't do it**. With the exception of 3rd party application integration, there is not a reason to directly call a file in mods directory.
101
102Recommended
103-----------
104
105These points are good ideas, but are not yet in the official guidelines. Following these suggestions will help to keep your plugin consistent with Elgg core.
106
107- Update the widget views (see the blog or file widgets)
108- Update the group profile “widget” using blog or file plugins as example
109- Update the forms
110   - Move form bodies to ``/forms/<handler>/<action>`` to use Evan’s new ``elgg_view_form()``
111   - Use input views in form bodies rather than html
112   - Add a function that prepares the form (see ``mod/file/lib/file.php`` for example)
113   - Integrate sticky forms (see the file plugin’s upload action and form prepare function)
114- Clean up CSS/HTML
115   - Should be able to remove almost all CSS (look for patterns that can be moved into core if you need CSS)
116- Use hyphens rather than underscores in classes/ids
117- Do not use the ``bundled`` category with your plugins. That is for plugins distributed with Elgg
118- Don't use ``register_shutdown_function`` as you may not have access to certain Elgg parts anymore (eg database). Instead use the ``shutdown`` ``system`` event
119