]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - plugins/doc/Plugin_development.md
Merge remote-tracking branch 'upstream/master' into social-master
[quix0rs-gnu-social.git] / plugins / doc / Plugin_development.md
1 Plugin Development
2 =======================
3
4 SamplePlugin.php
5 -----------------------
6
7 Each plugin requires a main class to interact with the GNU social system.
8
9 The main class usually extends the Plugin class that comes with GNU social.
10
11 The class has standard-named methods that will be called when certain events
12 happen in the code base. These methods have names like 'onX' where X is an
13 event name (see EVENTS.txt for the list of available events). Event handlers
14 have pre-defined arguments, based on which event they're handling. A typical
15 event handler:
16
17 ```php
18 function onSomeEvent($paramA, &$paramB)
19 {
20     if ($paramA == 'jed') {
21         throw new Exception(sprintf(_m("Invalid parameter %s"), $paramA));
22     }
23     $paramB = 'spock';
24     return true;
25 }
26 ```
27
28 Event Handlers
29 -----------------------
30
31 Event handlers must return a Boolean value.
32
33 If they return false, all other event handlers for this event (in other plug-in)
34 will be skipped, and in some cases the default processing for that event would
35 be skipped. This is great for replacing the default action of an event.
36
37 If the handler returns true, processing of other event handlers and the default
38 processing will continue. This is great for extending existing functionality.
39
40 If the handler throws an exception, processing will stop, and the exception's
41 error will be shown to the user.
42
43 Installation
44 ------------------
45
46 To install a plugin (like this one), site admins add the following code to their
47 config.php file:
48
49 ```php
50 addPlugin('Sample');
51 ```
52
53 Plugins must be installed in one of the following directories:
54
55 * local/plugins/{$pluginclass}.php
56 * local/plugins/{$name}/{$pluginclass}.php
57 * local/{$pluginclass}.php
58 * local/{$name}/{$pluginclass}.php
59 * plugins/{$pluginclass}.php
60 * plugins/{$name}/{$pluginclass}.php
61
62 Here, `{$name}` is the name of the plugin, like 'Sample', and `{$pluginclass}`
63 is the name of the main class, like 'SamplePlugin'. Plugins that are part of
64 the main GNU social distribution go in 'plugins' and third-party or local ones
65 go in 'local'.
66
67 Simple plugins can be implemented as a single module. Others are more complex
68 and require additional modules; these should use their own directory, like
69 'local/plugins/{$name}/'. All files related to the plugin, including images,
70 JavaScript, CSS, external libraries or PHP modules should go in the plugin
71 directory.
72
73 Plugin Configuration
74 ------------------
75
76 Plugins are configured using public instance attributes. To set their values,
77 site administrators use this syntax:
78
79 ```php
80 addPlugin('Sample', array('attr1' => 'foo', 'attr2' => 'bar'));
81 ```
82
83 The same plugin class can be initialized multiple times with different arguments:
84
85 ```php
86 addPlugin('EmailNotify', array('sendTo' => 'evan@status.net'));
87 addPlugin('EmailNotify', array('sendTo' => 'brionv@status.net'));
88 ```
89
90 ```php
91 class SamplePlugin extends Plugin
92 {
93     public $attr1 = null;
94     public $attr2 = null;
95 }
96 ```
97
98 Initialization
99 ------------------
100
101 Plugins overload this method to do any initialization they need, like connecting
102 to remote servers or creating paths or so on. @return boolean hook value; true
103 means continue processing, false means stop.
104
105 ```php
106 function initialize()
107 {
108     return true;
109 }
110 ```
111
112 Clean Up
113 ------------------
114
115 Plugins overload this method to do any cleanup they need, like disconnecting from
116 remote servers or deleting temp files or so on.
117
118 ```php
119 function cleanup()
120 {
121     return true;
122 }
123 ```
124
125 Database schema setup
126 ------------------
127
128 Plugins can add their own tables to the GNU social database. Plugins should use
129 GNU social's schema interface to add or delete tables. The ensureTable() method
130 provides an easy way to ensure a table's structure and availability.
131
132 By default, the schema is checked every time GNU social is run (say, when a Web
133 page is hit). Admins can configure their systems to only check the schema when
134 the checkschema.php script is run, greatly improving performance. However, they
135 need to remember to run that script after installing or upgrading a plugin!
136
137 ```php
138 function onCheckSchema()
139 {
140     $schema = Schema::get();
141
142     // '''For storing user-submitted flags on profiles'''
143
144     $schema->ensureTable('user_greeting_count',
145                           array(new ColumnDef('user_id', 'integer', null,
146                                               true, 'PRI'),
147                                 new ColumnDef('greeting_count', 'integer')));
148
149     return true;
150 }
151 ```
152
153 Load related modules when needed
154 ------------------
155
156 Most non-trivial plugins will require extra modules to do their work. Typically
157 these include data classes, action classes, widget classes, or external libraries.
158
159 This method receives a class name and loads the PHP file related to that class.
160 By tradition, action classes typically have files named for the action, all
161 lower-case. Data classes are in files with the data class name, initial letter
162 capitalized.
163
164 Note that this method will be called for *all* overloaded classes, not just ones
165 in this plugin! So, make sure to return true by default to let other plugins,
166 and the core code, get a chance.
167
168 ```php
169 function onAutoload($cls)
170 {
171     $dir = dirname(__FILE__);
172
173     switch ($cls)
174     {
175     case 'HelloAction':
176         include_once $dir . '/' . strtolower(mb_substr($cls, 0, -6)) . '.php';
177         return false;
178     case 'User_greeting_count':
179         include_once $dir . '/'.$cls.'.php';
180         return false;
181     default:
182         return true;
183     }
184 }
185 ```
186
187 Map URLs to actions
188 ------------------
189
190 This event handler lets the plugin map URLs on the site to actions (and thus an
191 action handler class). Note that the action handler class for an action will be
192 named 'FoobarAction', where action = 'foobar'. The class must be loaded in the
193 onAutoload() method.
194
195 ```php
196 function onRouterInitialized($m)
197 {
198     $m->connect('main/hello',
199                 array('action' => 'hello'));
200     return true;
201 }
202 ```
203
204 Modify the default menu to link to our custom action
205 ------------------
206
207 Using event handlers, it's possible to modify the default UI for pages almost
208 without limit. In this method, we add a menu item to the default primary menu
209 for the interface to link to our action.
210
211 Action Class
212 ------------------
213
214 The Action class provides a rich set of events to hook, as well as output methods.
215
216 ```php
217 function onEndPrimaryNav($action)
218 {
219     // '''common_local_url()''' gets the correct URL for the action name we provide
220
221     $action->menuItem(common_local_url('hello'),
222                       _m('Hello'), _m('A warm greeting'), false, 'nav_hello');
223     return true;
224 }
225
226 function onPluginVersion(&$versions)
227 {
228     $versions[] = array('name' => 'Sample',
229                         'version' => STATUSNET_VERSION,
230                         'author' => 'Brion Vibber, Evan Prodromou',
231                         'homepage' => 'http://example.org/plugin',
232                         'rawdescription' =>
233                         _m('A sample plugin to show basics of development for new hackers.'));
234     return true;
235 }
236 ```
237
238 hello.php
239 ------------------
240
241 This section is taken directly from the 'hello.php'. ( plugins/Sample/hello.php )
242
243 Give a warm greeting to our friendly user.
244
245 This sample action shows some basic ways of doing output in an action class.
246
247 Action classes have several output methods that they override from the parent class.
248
249 ```php
250 class HelloAction extends Action
251 {
252     var $user = null;
253     var $gc   = null;
254 }
255 ```
256
257 Take arguments for running
258 ------------------
259
260 This method is called first, and it lets the action class get all its arguments
261 and validate them. It's also the time to fetch any relevant data from the database.
262
263 Action classes should run parent::prepare($args) as the first line of this
264 method to make sure the default argument-processing happens.
265
266 ```php     
267 function prepare($args)
268 {
269     parent::prepare($args);
270
271     $this->user = common_current_user();
272
273     if (!empty($this->user)) {
274         $this->gc = User_greeting_count::inc($this->user->id);
275     }
276
277     return true;
278 }
279 ```
280
281 Handle request
282 ------------------
283
284 This is the main method for handling a request. Note that most preparation
285 should be done in the prepare() method; by the time handle() is called the
286 action should be more or less ready to go.
287
288 ```php
289 function handle($args)
290 {
291     parent::handle($args);
292
293     $this->showPage();
294 }
295 ```
296
297 Title of this page
298 ------------------
299
300 Override this method to show a custom title.
301
302 ```php
303 function title()
304 {
305     if (empty($this->user)) {
306         return _m('Hello');
307     } else {
308         return sprintf(_m('Hello, %s'), $this->user->nickname);
309     }
310 }
311 ```
312
313 Show content in the content area
314 ------------------
315
316 The default GNU social page has a lot of decorations: menus, logos, tabs, all
317 that jazz. This method is used to show content in the content area of the
318 page; it's the main thing you want to overload. This method also demonstrates
319 use of a plural localized string.
320
321 ```php
322 function showContent()
323 {
324     if (empty($this->user)) {
325         $this->element('p', array('class' => 'greeting'),
326                        _m('Hello, stranger!'));
327     } else {
328         $this->element('p', array('class' => 'greeting'),
329                        sprintf(_m('Hello, %s'), $this->user->nickname));
330         $this->element('p', array('class' => 'greeting_count'),
331                        sprintf(_m('I have greeted you %d time.',
332                                   'I have greeted you %d times.',
333                                   $this->gc->greeting_count),
334                                   $this->gc->greeting_count));
335     }
336 }
337 ```
338
339 Return true if read only.
340 ------------------
341
342 Some actions only read from the database; others read and write. The simple
343 database load-balancer built into GNU social will direct read-only actions to
344 database mirrors (if they are configured) and read-write actions to the master database.
345
346 This defaults to false to avoid data integrity issues, but you should make sure
347 to overload it for performance gains.
348
349 ```php
350 function isReadOnly($args)
351 {
352     return false;
353 }
354 ```
355