Removing translation directories
[project/ctools.git] / help / plugins-creating.html
CommitLineData
38b88766 1There are two primary pieces to using plugins. The first is getting the data, and the second is using the data.
4f8d821f 2
38b88766 3<h3>Getting the data</h3>
e5eeb652 4To create a plugin, a module only has to execute ctools_get_plugins with the right data:
4f8d821f 5
38b88766 6<pre>
d618b8c2 7 ctools_include('plugins');
38b88766
EM
8 ctools_get_plugins($module, $type, [$id])
9</pre>
4f8d821f 10
38b88766 11In the above example, $module should be your module's name and $type is the type of the plugin. It is typically best practice to provide some kind of wrapper function to make this easier. For example, Panels provides the following functions to implement the 'content_types' plugin:
4f8d821f 12
38b88766
EM
13<pre>
14/**
15 * Fetch metadata on a specific content_type plugin.
16 *
17 * @param $content type
18 * Name of a panel content type.
19 *
20 * @return
21 * An array with information about the requested panel content type.
22 */
23function panels_get_content_type($content_type) {
24 ctools_include('context');
25 ctools_include('plugins');
26 return ctools_get_plugins('panels', 'content_types', $content_type);
27}
28
29/**
30 * Fetch metadata for all content_type plugins.
31 *
32 * @return
33 * An array of arrays with information about all available panel content types.
34 */
35function panels_get_content_types() {
36 ctools_include('context');
37 ctools_include('plugins');
38 return ctools_get_plugins('panels', 'content_types');
39}
40</pre>
41
42As a plugin creator, your module can also implement a hook to give more information about this plugin, and to enable a few features that are not normally enabled. If you need any of these features, simply implement hook_ctools_plugin_TYPE (where TYPE is the same $type sent to ctools_get_plugins). This isn't a true hook, it will only be called for the $module that was given. This hook returns an array:
43
44<pre>
45/**
46 * Inform CTools that the layout plugin can be loaded from themes.
47 */
48function panels_ctools_plugin_layouts() {
49 return array(
50 'load themes' => TRUE,
9398d6a6 51 );
38b88766
EM
52}
53</pre>
54
55The following information can be specified:
56<dl>
57<dt>cache</dt>
aeed3fef
SB
58<dd><em>Defaults to:</em> <strong>FALSE</strong></dd>
59<dd>If set to TRUE, the results of ctools_get_plugins will be cached in the 'cache' table (by default), thus preventing .inc files from being loaded. ctools_get_plugins looking for a specific plugin will always load the appropriate .inc file.</dd>
60<dt>cache table</dt>
61<dd><em>Defaults to:</em> <strong>'cache'</strong></dd>
62<dd>If 'cache' is TRUE, then this value specifies the cache table where the cached plugin information will be stored.</dd>
38b88766 63<dt>defaults</dt>
aeed3fef
SB
64<dd><em>Defaults to:</em> <strong>array()</strong></dd>
65<dd>An array of defaults that should be added to each plugin; this can be used to ensure that every plugin has the basic data necessary. These defaults will not ovewrite data supplied by the plugin. This could also be a function name, in which case the callback will be used to provide defaults. NOTE, however, that the callback-based approach is deprecated as it is redundant with the 'process' callback, and as such will be removed in later versions. Consequently, you should only use the array form for maximum cross-version compatibility.</dd>
38b88766 66<dt>load themes</dt>
aeed3fef
SB
67<dd><em>Defaults to:</em> <strong>FALSE</strong></dd>
68<dd>If set to TRUE, then plugins of this type can be supplied by themes as well as modules. If this is the case, all themes that are currently enabled will provide a plugin: NOTE: Due to a slight UI bug in Drupal, it is possible for the default theme to be active but not enabled. If this is the case, that theme will NOT provide plugins, so if you are using this feature, be sure to document that issue. Also, themes set via $custom_theme do not necessarily need to be enabled, but the system has no way of knowing what those themes are, so the enabled flag is the only true method of identifying which themes can provide layouts.</dd>
38b88766 69<dt>hook</dt>
aeed3fef
SB
70<dd><em>Defaults to:</em> (dynamic value)</dd>
71<dd>The name of the hook used to collect data for this plugin. Normally this is <strong>$module . '_' . $type</strong> -- but this can be changed here. If you change this, you MUST be sure to document this for your plugin implementors as it will change the format of the specially named hook.
38b88766 72<dt>process</dt>
aeed3fef
SB
73<dd><em>Defaults to:</em> <strong>''</strong></dd>
74<dd>An optional function callback to use for processing a plugin. This can be used to provide automated settings that must be calculated per-plugin instance (i.e., it is not enough to simply append an array via 'defaults'). The parameters on this callback are: <strong>callback(&$plugin, $info)</strong> where $plugin is a reference to the plugin as processed and $info is the fully processed result of hook_ctools_plugin_api_info().
75<dt>extension</dt>
76<dd><em>Defaults to:</em> <strong>'inc'</strong></dd>
77<dd>Can be used to change the extension on files containing plugins of this type. By default the extension will be "inc", though it will default to "info" if "info files" is set to true. Do not include the dot in the extension if changing it, that will be added automatically.</dd>
e5eeb652 78<dt>info file</dt>
aeed3fef 79<dd><em>Defaults to:</em> <strong>FALSE</strong></dd>
e5eeb652 80<dd>If set to TRUE, then the plugin will look for a .info file instead of a .inc. Internally, this will look exactly the same, though obviously a .info file cannot contain functions. This can be good for styles that may not need to contain code.</dd>
aeed3fef
SB
81<dt>use hooks</dt>
82<dd><em>Defaults to:</em> <strong>TRUE</strong>*</dd>
83<dd>Use to enable support for plugin definition hooks instead of plugin definition files. NOTE: using a central plugin definition hook is less optimal for the plugins system, and as such this will default to FALSE in later versions.</dd>
84<dt>child plugins</dt>
85<dd><em>Defaults to:</em> <strong>FALSE</strong></dd>
86<dd>If set to TRUE, the plugin type can automatically have 'child plugins' meaning each plugin can actually provide multiple plugins. This is mostly used for plugins that store some of their information in the database, such as views, blocks or exportable custom versions of plugins.</dd>
87<dd>To implement, each plugin can have a 'get child' and 'get children' callback. Both of these should be implemented for performance reasons, since it is best to avoid getting all children if necessary, but if 'get child' is not implemented, it will fall back to 'get children' if it has to.</dd>
88<dd>Child plugins should be named parent:child, with the : being the separator, so that it knows which parent plugin to ask for teh child. The 'get children' method should at least return the parent plugin as part of the list, unless it wants the parent plugin itself to not be a choosable option, which is not unheard of. </dd>
89<dd>'get children' arguments are ($plugin, $parent) and 'get child' arguments are ($plugin, $parent, $child).
38b88766
EM
90</dl>
91
aeed3fef 92In addition, there is a 'module' and 'type' settings; these are for internal use of the plugin system and you should not change these.
38b88766
EM
93
94<h3>Using the data</h3>
95
96Each plugin returns a packet of data, which is added to with a few defaults. Each plugin is guaranteed to always have the following data:
97<dl>
98<dt>name</dt>
99<dd>The name of the plugin. This is also the key in the array, of the full list of plugins, and is placed here since that is not always available.</dd>
100<dt>module</dt>
101<dd>The module that supplied the plugin.</dd>
102<dt>file</dt>
103<dd>The actual file containing the plugin.</dd>
104<dt>path</dt>
105<dd>The path to the file containing the plugin. This is useful for using secondary files, such as templates, css files, images, etc, that may come with a plugin.</dd>
106</dl>
5a49056a 107
38b88766 108Any of the above items can be overridden by the plugin itself, though the most likely one to be modified is the 'path'.
0479b3da 109
38b88766
EM
110The most likely data (beyond simple printable data) for a plugin to provide is a callback. The plugin system provides a pair of functions to make it easy and consistent for these callbacks to be used. The first is ctools_plugin_get_function, which requires the full $plugin object.
111
112<pre>
113/**
114 * Get a function from a plugin, if it exists. If the plugin is not already
115 * loaded, try ctools_plugin_load_function() instead.
116 *
117 * @param $plugin
118 * The loaded plugin type.
119 * @param $callback_name
120 * The identifier of the function. For example, 'settings form'.
121 *
122 * @return
123 * The actual name of the function to call, or NULL if the function
124 * does not exist.
125 */
126function ctools_plugin_get_function($plugin, $callback_name)
127</pre>
128
129The second does not require the full $plugin object, and will load it:
130<pre>
131/**
132 * Load a plugin and get a function name from it, returning success only
133 * if the function exists.
134 *
135 * @param $module
136 * The module that owns the plugin type.
137 * @param $type
138 * The type of plugin.
139 * @param $id
140 * The id of the specific plugin to load.
141 * @param $callback_name
142 * The identifier of the function. For example, 'settings form'.
143 *
144 * @return
145 * The actual name of the function to call, or NULL if the function
146 * does not exist.
147 */
148function ctools_plugin_load_function($module, $type, $id, $callback_name) {
149</pre>
150
151Both of these functions will ensure any needed files are included. In fact, it allows each callback to specify alternative include files. The plugin implementation could include code like this:
152
153<pre>
154 'callback_name' => 'actual_name_of_function_here',
155</pre>
156
157Or like this:
158<pre>
159 'callback_name' => array(
5a49056a 160 'file' => 'filename',
38b88766
EM
161 'path' => 'filepath', // optional, will use plugin path if absent
162 'function' => 'actual_name_of_function_here',
5a49056a 163 ),
38b88766
EM
164</pre>
165
aeed3fef 166An example, for 'plugin_example' type
38b88766
EM
167
168<pre>
169$plugin = array(
170 'name' => 'my_plugin',
171 'module' => 'my_module',
172 'example_callback' => array(
173 'file' => 'my_plugin.extrafile.inc',
174 'function' => 'my_module_my_plugin_example_callback',
175 ),
176);
177</pre>
178
179To utilize this callback on this plugin:
180
181<pre>
182if ($function = ctools_plugin_get_function($plugin, 'example_callback')) {
183 $function($arg1, $arg2, $etc);
184}
185</pre>
5a49056a 186
38b88766
EM
187<h3>Document your plugins!</h3>
188Since the data provided by your plugin tends to be specific to your plugin type, you really need to document what the data returned in the hook in the .inc file will be or nobody will figure it out. Use advanced help and document it there. If every system that utilizes plugins does this, then plugin implementors will quickly learn to expect the documentation to be in the advanced help.
0a5d33a1 189