DokuWiki

It's better when it's simple

User Tools

Site Tools


devel:plugin_programming_tips

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
devel:plugin_programming_tips [2013-02-26 02:35] – made link internal achdevel:plugin_programming_tips [2023-09-20 23:34] (current) Klap-in
Line 1: Line 1:
 ====== Tips for programming plugins ====== ====== Tips for programming plugins ======
-Please write down tips you've discovered making it easier for others to make plugins.+Please write down tips you've discovered making it easier for others to [[plugins|make plugins]].
 I actually had to sit down and fgrep myself to this info, and I hope that it will help others ;-) I actually had to sit down and fgrep myself to this info, and I hope that it will help others ;-)
  
 On this page are some tips (see ToC right). Useful resources elsewhere in the wiki are: On this page are some tips (see ToC right). Useful resources elsewhere in the wiki are:
   * [[common plugin functions#Configuration]]   * [[common plugin functions#Configuration]]
-  * [[common plugin functions#Localisation]]+  * [[common plugin functions#Localization]]
   * Plugin [[plugin file structure|file structure]] and [[plugin file structure|name conventions]]   * Plugin [[plugin file structure|file structure]] and [[plugin file structure|name conventions]]
-  * Using a customized [[section editor]] in your plugin+  * [[devel:badextensions|Conflicting Versions and Basenames]]
  
 +
 +=====Customized Section editing=====
 +When you like to change only small pieces of the wiki text via your plugin, it is recommended to look for section editing. This let you provide your interface elements that can edit a specific marked piece of wiki text.
 +
 +Please refer to [[section editor]] for details on the implementation in your plugin.
  
  
Line 15: Line 20:
  
 <code php> <code php>
-    global $auth; +global $auth; 
-    if($auth->canDo('getUsers')) {  // is this feature available? +if ($auth->canDo('getUsers')) {  // is this feature available? 
-        $auth->retrieveUsers(0,0,$filter); +    $auth->retrieveUsers(0, 0, $filter); 
-    }+}
 </code> </code>
  
 Where ''$filter'' is an array with one or more of the following keys ''user'', ''name'', ''mail'', or ''grps''. Where ''$filter'' is an array with one or more of the following keys ''user'', ''name'', ''mail'', or ''grps''.
-Several values in each using '|' as a separator.\\+Several values in each using ''|'' as a separator. 
 For example, to retrieve all users in the group 'admin', one would use: For example, to retrieve all users in the group 'admin', one would use:
 <code php> <code php>
-    $filter['grps']="admin"+$filter['grps'] = 'admin'
-    $array_of_matches = retrieveUsers(0,0,$filter);+$array_of_matches = $auth->retrieveUsers(0, 0, $filter);
 </code> </code>
  
-Be aware that the user backend needs to implement this function. Otherwise it returns always an empty array.+Be aware that the authentication plugin needs to implement this function. Otherwise it returns always an empty array.
  
-See also [[devel:authentication_backends#optional_methods|authentication backend]] mention of ''retrieveUsers()'' and other auth functions.+See also [[devel:auth_plugins#retrieveusers|authentication plugins]] mention of ''retrieveUsers()'' and other functions.
  
 ===== DokuWiki Global Variables ===== ===== DokuWiki Global Variables =====
Line 48: Line 54:
  
 ===Protect forms and action urls=== ===Protect forms and action urls===
-If you use forms in your plugins or urls that initiate actions, you should include a hidden form field with the session-based security token. In the current version of DokuWiki you can generate this field by calling the function ''formSecurityToken()''. Before you process the form input, call ''checkSecurityToken()''. This function checks if the sent security token is correct. +If you use forms in your plugins or urls that initiate actions, you should include a hidden form field with the session-based security token. In the current version of DokuWiki you can generate this field by calling the function [[xref>formSecurityToken()]]. Before you process the form input, call [[xref>checkSecurityToken()]]. This function checks if the sent security token is correct. 
  
 //Scenario// If you wonder, why this will make your plugins more secure, consider the following scenario: //Scenario// If you wonder, why this will make your plugins more secure, consider the following scenario:
Line 56: Line 62:
  
 Other security tips are listed and explained [[devel:security|on the dedicated page.]] Other security tips are listed and explained [[devel:security|on the dedicated page.]]
 +
 +===== Use correct regular expressions =====
 +
 +Use correct regular expressions for syntax search patterns. If the search pattern is incorrect, it can produce unwanted effects in combination with other plugins.
 +
 +Use reasonable tag names to avoid conflicts with other plugins. For example don't use a name like ''test'' but ''pluginname_test'' instead. Maybe check existing search patterns here [[devel:plugin_survey:syntax]], but don't use them as example because many of them are incorrect regular expressions.
 +
 +==== Correct regular expression ====
 +
 +<code>
 +<tag\b.*?>.*?</tag>
 +
 +<tag\b[^>\r\n]*?>.*?</tag>
 +<tag\b[^>\r\n]*?>[^\r\n]*?</tag>
 +
 +<tag\b.*?>(?:.*?</tag>)
 +
 +<tag\b(?:\s+(?:par1|par2)="[^">\r\n]*")*\s*>(?:.*?</tag>)
 +</code>
 +
 +<code>
 +~~tag\b.*?~~
 +~~tag>.+?~~
 +~~tag>[^\r\n]+?~~
 +</code>
 + 
 +
 +
 +==== False regular expression ====
 +
 +Example 1:
 +
 +<code>
 +<tag.*>.*?</tag>
 +<tag ?.*>.*?</tag>
 +<tag *.*>.*?</tag>
 +</code>
 +
 +Start tag is not a word, the end-of-word marker ''\b'' is missing, any pattern for example tagmore or taged is found too.
 +
 +This produces a wrong result in this case:
 +
 +<code>
 +<tagmore>
 +Text
 +</tagmore>
 +
 +<tag>
 +Text
 +</tag>
 +</code>
 +
 +Example 2:
 +
 +<code>
 +<tag\b.*>.*?</tag>
 +<tag\b.*?>.*</tag>
 +</code>
 +
 +The search pattern is "greedy", the not-greedy marker ''?'' is missing, to long pieces are included in one search match.
 +
 +This produces a wrong result in this case:
 +
 +<code>
 +<tag>
 +Text
 +</tag>
 +
 +<tag>
 +Text
 +</tag>
 +</code>
 +
 +===== Spam prevention =====
 +When you offer a form in your plugin and this can be also used by public users of a wiki, it's recommended to use CAPTCHA to defeat spambots. There is already a [[plugin:CAPTCHA]] plugin available, which provides different formats, visible and invisible CAPTCHAs. 
 +
 +See the plugin page for description of the [[plugin:captcha#helper_methods|integration]] and the [[plugin:captcha#configuration]] options.
 +
 +===Example implementation=== 
 +The [[plugin:Bureaucracy]] plugin supports this plugin. The CAPTCHA is integrated in the submit button, see [[https://github.com/splitbrain/dokuwiki-plugin-bureaucracy/blob/master/fields/submit.php|submit.php]].
 +
 +
  
 ===== Adding JavaScript ===== ===== Adding JavaScript =====
Line 65: Line 153:
  
 ===Distribute JavaScript and CSS files by pseudo plugins=== ===Distribute JavaScript and CSS files by pseudo plugins===
-If you want to add some JavaScript and CSS at the same time and make it easier to distribute, you can create a //'pseudo'// plugin. Create a new folder and add a ''script.js'' and/or a ''style.css'' file to it. Add this folder to ''lib/plugins/''.+If you want to add some JavaScript and CSS at the same time and make it easier to distribute, you can create a //'pseudo'// plugin. Create a new folder and add a ''script.js'' and/or a ''style.css'' file to it. Add this folder to ''lib/plugins/'' and complete it by adding the ''[[plugin_info|plugin.info.txt]]''.
  
 Examples pseudo plugins: [[plugin:searchjump]] or [[plugin:ipa]] Examples pseudo plugins: [[plugin:searchjump]] or [[plugin:ipa]]
Line 71: Line 159:
 More about [[plugin file structure#JavaScript]] and [[plugin file structure#CSS styles]] in plugins. More about [[plugin file structure#JavaScript]] and [[plugin file structure#CSS styles]] in plugins.
  
 +
 +=====Using cookies=====
 +When you like to store some preferences, you can add to and retrieve of DokuWikis preferences cookie by: 
 +  * in PHP: 
 +    * set a value ''[[xref>set_doku_pref|set_doku_pref($pref, $value)]]'' 
 +    * delete an entry ''[[xref>set_doku_pref|set_doku_pref($pref, false)]]''
 +    * and retrieve its value with ''[[xref>get_doku_pref|get_doku_pref($pref, $default)]]''
 +  * and in javascript: 
 +    * set a value ''[[xref>lib/scripts/cookie.js|DokuCookie.setValue(pref, value)]]'' 
 +    * and retrieve value ''[[xref>lib/scripts/cookie.js|DokuCookie.getValue(pref)]]''
 +
 +For other usages you use a separated cookie. Next snippet shows how you set cookies with the correct path in DokuWiki.
 +
 +In PHP:
 +<code php>
 +global $conf;
 +$cookieDir = empty($conf['cookiedir']) ? DOKU_REL : $conf['cookiedir'];
 +setCookie("yourCookieName", $value, $expire, $cookieDir, '', ($conf['securecookie'] && is_ssl()));
 +</code>
 +and in javascript:
 +<code javascript>
 +jQuery.cookie("yourCookieName", value, { 
 +    expires: 7, //days
 +    path: DOKU_COOKIE_PARAM.path,
 +    secure: DOKU_COOKIE_PARAM.secure 
 +});
 +</code>
 +
 +
 +More general info about cookies: [[faq:cookies|DokuWiki's cookies]], [[config:cookiedir]] config, [[config:securecookie]] config.
  
 ===== Handle JSON ajax request ===== ===== Handle JSON ajax request =====
-An action plugin that register the [[devel:event:ajax_call_unknown]] event, you can handle your own ajax requests. Here a sample how you can return JSON to your javascript. Plugin name is  ''example''.+An action plugin that register the [[devel:event:ajax_call_unknown|AJAX_CALL_UNKNOWN]] event, you can handle your own ajax requests. Here a sample how you can return JSON to your javascript. Plugin name is  ''example''.
  
 Create an [[Action Plugin]] which should contain: Create an [[Action Plugin]] which should contain:
 <code php lib/plugin/example/action.php> <code php lib/plugin/example/action.php>
-/* +use dokuwiki\Extension\ActionPlugin
- * plugin should use this method to register its handlers  +use dokuwiki\Extension\EventHandler
- * with the dokuwiki's event controller +use dokuwiki\Extension\Event;
- */ +
-function register(&$controller) { +
-    $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this,'_ajax_call')+
-+
-     +
-/** +
- * handle ajax requests +
- */ +
-function _ajax_call(&$event, $param) { +
-    if ($event->data !== 'example') { +
-        return+
-    } +
-    //no other ajax call handlers needed +
-    $event->stopPropagation(); +
-    $event->preventDefault();+
  
-    //e.g. access additional request variables +class action_plugin_example extends ActionPlugin { 
-    global $INPUT; //available since release 2012-10-13 "Adora Belle" + 
-    $name = $INPUT->str('name')) {+    /** 
 +     * plugin should use this method to register its handlers  
 +     * with the dokuwiki's event controller 
 +     *
 +    public function register(EventHandler $controller) { 
 +        $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'ajaxCall')
 +    }
          
-    //data +    /** 
-    $data = array();+     * handle ajax requests 
 +     *
 +    public function ajaxCall(Event $event) { 
 +        if ($event->data !== 'plugin_example') { 
 +            return; 
 +        } 
 +        //no other ajax call handlers needed 
 +        $event->stopPropagation(); 
 +        $event->preventDefault();
  
-    //json library of DokuWiki +        //e.gaccess additional request variables 
-    require_once DOKU_INC 'inc/JSON.php'+        global $INPUT
-    $json new JSON();+        $name $INPUT->str('name');
          
-    //set content type +        //data 
-    header('Content-Type: application/json'); +        $data = []; 
-    echo $json->encode($data);+ 
 +        //set content type 
 +        header('Content-Type: application/json'); 
 +        echo json_encode($data); 
 +    }
 } }
 </code> </code>
Line 118: Line 239:
 jQuery.post( jQuery.post(
     DOKU_BASE + 'lib/exe/ajax.php',     DOKU_BASE + 'lib/exe/ajax.php',
-    {call: 'example', name: 'local'},+    { 
 +        call: 'plugin_example',  
 +        name: 'local' 
 +    },
     function(data) {     function(data) {
         alert('Received response');         alert('Received response');
Line 156: Line 280:
 Example: Example:
 <code php> <code php>
 +global $INPUT;
 +
 // we are parsing a submitted comment... // we are parsing a submitted comment...
-if (isset($_REQUEST['comment']))+if ($INPUT->has('comment')) {
     return false;     return false;
 +}
 </code> </code>
 +
 +===== Sending popularity data =====
 +Since release 2015-08-10 "Detritus"
 +
 +:!: As a plugin developer, beware: since popularity data is public, you must not send sensitive information with this feature.
 +
 +The [[plugin:popularity]] plugin already gather the number of time a plugin is installed on an instance of Dokuwiki.
 +
 +It also let the possibility to developers, to send more data about usage. It can be used by plugins developers to know if a given obsolete feature is still used. To do it, you need to subscribe to the [[devel:event:PLUGIN_POPULARITY_DATA_SETUP]] event. This event contains a key-value array. You should add a key which is the name of your plugin. The value should be either a string, or a key-value array itself (in this latter case, the data will be sent with the key ''<plugin-name>_<key>'')
 +
 +Example:
 +
 +<code php action.php>
 +use dokuwiki\Extension\ActionPlugin;
 +use dokuwiki\Extension\EventHandler;
 +use dokuwiki\Extension\Event;
 +
 +class action_plugin_example extends ActionPlugin {
 +    public function register(EventHandler $controller) {
 +        $controller->register_hook('PLUGIN_POPULARITY_DATA_SETUP', 'AFTER', $this, 'usageData');
 +    }
 +    
 +    public function usageData(Event $event){
 +        $event->data['my_plugin_name'] = 'my usage data';
 + 
 +    /* or: 
 +        $event->data['my_plugin_name'] = [
 +            'k1' => 'v1', 
 +            'k2' => 'v2'
 +        ];
 +    */
 +    }
 +}
 +</code>
 +
 +A plugin which uses this feature is the [[plugin:nspages]] Plugin.
devel/plugin_programming_tips.1361842553.txt.gz · Last modified: 2013-02-26 02:35 by ach

Except where otherwise noted, content on this wiki is licensed under the following license: CC Attribution-Share Alike 4.0 International
CC Attribution-Share Alike 4.0 International Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki