Failed Conditions
Push — psr2 ( ccc4c7...2140e7 )
by Andreas
26s queued 20s
created

Doku_Plugin_Controller::load()   C

Complexity

Conditions 11
Paths 8

Size

Total Lines 53

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 11
nc 8
nop 4
dl 0
loc 53
rs 6.8787
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Class to encapsulate access to dokuwiki plugins
4
 *
5
 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
6
 * @author     Christopher Smith <[email protected]>
7
 */
8
9
// plugin related constants
10
if(!defined('DOKU_PLUGIN'))  define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
11
12
class Doku_Plugin_Controller {
13
14
    protected $list_bytype = array();
15
    protected $tmp_plugins = array();
16
    protected $plugin_cascade = array('default'=>array(),'local'=>array(),'protected'=>array());
17
    protected $last_local_config_file = '';
18
19
    /**
20
     * Populates the master list of plugins
21
     */
22
    public function __construct() {
23
        $this->loadConfig();
24
        $this->_populateMasterList();
25
    }
26
27
    /**
28
     * Returns a list of available plugins of given type
29
     *
30
     * @param $type  string, plugin_type name;
31
     *               the type of plugin to return,
32
     *               use empty string for all types
33
     * @param $all   bool;
34
     *               false to only return enabled plugins,
35
     *               true to return both enabled and disabled plugins
36
     *
37
     * @return       array of
38
     *                  - plugin names when $type = ''
39
     *                  - or plugin component names when a $type is given
40
     *
41
     * @author Andreas Gohr <[email protected]>
42
     */
43
    public function getList($type='',$all=false){
44
45
        // request the complete list
46
        if (!$type) {
47
            return $all ? array_keys($this->tmp_plugins) : array_keys(array_filter($this->tmp_plugins));
48
        }
49
50
        if (!isset($this->list_bytype[$type]['enabled'])) {
51
            $this->list_bytype[$type]['enabled'] = $this->_getListByType($type,true);
52
        }
53
        if ($all && !isset($this->list_bytype[$type]['disabled'])) {
54
            $this->list_bytype[$type]['disabled'] = $this->_getListByType($type,false);
55
        }
56
57
        return $all
58
            ? array_merge($this->list_bytype[$type]['enabled'], $this->list_bytype[$type]['disabled'])
59
            : $this->list_bytype[$type]['enabled'];
60
    }
61
62
    /**
63
     * Loads the given plugin and creates an object of it
64
     *
65
     * @author Andreas Gohr <[email protected]>
66
     *
67
     * @param  $type     string type of plugin to load
68
     * @param  $name     string name of the plugin to load
69
     * @param  $new      bool   true to return a new instance of the plugin, false to use an already loaded instance
70
     * @param  $disabled bool   true to load even disabled plugins
71
     * @return DokuWiki_PluginInterface|null  the plugin object or null on failure
72
     */
73
    public function load($type,$name,$new=false,$disabled=false){
74
75
        //we keep all loaded plugins available in global scope for reuse
76
        global $DOKU_PLUGINS;
77
78
        list($plugin, /* $component */) = $this->_splitName($name);
79
80
        // check if disabled
81
        if(!$disabled && $this->isdisabled($plugin)){
82
            return null;
83
        }
84
85
        $class = $type.'_plugin_'.$name;
86
87
        //plugin already loaded?
88
        if(!empty($DOKU_PLUGINS[$type][$name])){
89
            if ($new || !$DOKU_PLUGINS[$type][$name]->isSingleton()) {
90
                return class_exists($class, true) ? new $class : null;
91
            } else {
92
                return $DOKU_PLUGINS[$type][$name];
93
            }
94
        }
95
96
        //construct class and instantiate
97
        if (!class_exists($class, true)) {
98
99
            # the plugin might be in the wrong directory
100
            $dir = $this->get_directory($plugin);
101
            $inf = confToHash(DOKU_PLUGIN."$dir/plugin.info.txt");
102
            if($inf['base'] && $inf['base'] != $plugin){
103
                msg(
104
                    sprintf(
105
                        "Plugin installed incorrectly. Rename plugin directory '%s' to '%s'.",
106
                        hsc($plugin),
107
                        hsc(
108
                            $inf['base']
109
                        )
110
                    ), -1
111
                );
112
            } elseif (preg_match('/^'.DOKU_PLUGIN_NAME_REGEX.'$/', $plugin) !== 1) {
113
                msg(
114
                    sprintf(
115
                        "Plugin name '%s' is not a valid plugin name, only the characters a-z and 0-9 are allowed. " .
116
                        'Maybe the plugin has been installed in the wrong directory?', hsc($plugin)
117
                    ), -1
118
                );
119
            }
120
            return null;
121
        }
122
123
        $DOKU_PLUGINS[$type][$name] = new $class;
124
        return $DOKU_PLUGINS[$type][$name];
125
    }
126
127
    /**
128
     * Whether plugin is disabled
129
     *
130
     * @param string $plugin name of plugin
131
     * @return bool  true disabled, false enabled
132
     */
133
    public function isdisabled($plugin) {
134
        return empty($this->tmp_plugins[$plugin]);
135
    }
136
137
    /**
138
     * Disable the plugin
139
     *
140
     * @param string $plugin name of plugin
141
     * @return bool  true saving succeed, false saving failed
142
     */
143
    public function disable($plugin) {
144
        if(array_key_exists($plugin,$this->plugin_cascade['protected'])) return false;
145
        $this->tmp_plugins[$plugin] = 0;
146
        return $this->saveList();
147
    }
148
149
    /**
150
     * Enable the plugin
151
     *
152
     * @param string $plugin name of plugin
153
     * @return bool  true saving succeed, false saving failed
154
     */
155
    public function enable($plugin) {
156
        if(array_key_exists($plugin,$this->plugin_cascade['protected'])) return false;
157
        $this->tmp_plugins[$plugin] = 1;
158
        return $this->saveList();
159
    }
160
161
    /**
162
     * Returns directory name of plugin
163
     *
164
     * @param string $plugin name of plugin
165
     * @return string name of directory
166
     */
167
    public function get_directory($plugin) {
168
        return $plugin;
169
    }
170
171
    /**
172
     * Returns cascade of the config files
173
     *
174
     * @return array with arrays of plugin configs
175
     */
176
    public function getCascade() {
177
        return $this->plugin_cascade;
178
    }
179
180
    protected function _populateMasterList() {
181
        global $conf;
182
183
        if ($dh = @opendir(DOKU_PLUGIN)) {
184
            $all_plugins = array();
185
            while (false !== ($plugin = readdir($dh))) {
186
                if ($plugin[0] == '.') continue;               // skip hidden entries
187
                if (is_file(DOKU_PLUGIN.$plugin)) continue;    // skip files, we're only interested in directories
188
189
                if (array_key_exists($plugin,$this->tmp_plugins) && $this->tmp_plugins[$plugin] == 0){
190
                    $all_plugins[$plugin] = 0;
191
192
                } elseif ((array_key_exists($plugin,$this->tmp_plugins) && $this->tmp_plugins[$plugin] == 1)) {
193
                    $all_plugins[$plugin] = 1;
194
                } else {
195
                    $all_plugins[$plugin] = 1;
196
                }
197
            }
198
            $this->tmp_plugins = $all_plugins;
199
            if (!file_exists($this->last_local_config_file)) {
200
                $this->saveList(true);
201
            }
202
        }
203
    }
204
205
    /**
206
     * Includes the plugin config $files
207
     * and returns the entries of the $plugins array set in these files
208
     *
209
     * @param array $files list of files to include, latter overrides previous
210
     * @return array with entries of the $plugins arrays of the included files
211
     */
212
    protected function checkRequire($files) {
213
        $plugins = array();
214
        foreach($files as $file) {
215
            if(file_exists($file)) {
216
                include_once($file);
217
            }
218
        }
219
        return $plugins;
220
    }
221
222
    /**
223
     * Save the current list of plugins
224
     *
225
     * @param bool $forceSave;
0 ignored issues
show
Documentation introduced by
There is no parameter named $forceSave;. Did you maybe mean $forceSave?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
226
     *              false to save only when config changed
227
     *              true to always save
228
     * @return bool  true saving succeed, false saving failed
229
     */
230
    protected function saveList($forceSave = false) {
231
        global $conf;
232
233
        if (empty($this->tmp_plugins)) return false;
234
235
        // Rebuild list of local settings
236
        $local_plugins = $this->rebuildLocal();
237
        if($local_plugins != $this->plugin_cascade['local'] || $forceSave) {
238
            $file = $this->last_local_config_file;
239
            $out = "<?php\n/*\n * Local plugin enable/disable settings\n".
240
                   " * Auto-generated through plugin/extension manager\n *\n".
241
                   " * NOTE: Plugins will not be added to this file unless there ".
242
                   "is a need to override a default setting. Plugins are\n".
243
                   " *       enabled by default.\n */\n";
244
            foreach ($local_plugins as $plugin => $value) {
245
                $out .= "\$plugins['$plugin'] = $value;\n";
246
            }
247
            // backup current file (remove any existing backup)
248
            if (file_exists($file)) {
249
                $backup = $file.'.bak';
250
                if (file_exists($backup)) @unlink($backup);
251
                if (!@copy($file,$backup)) return false;
252
                if (!empty($conf['fperm'])) chmod($backup, $conf['fperm']);
253
            }
254
            //check if can open for writing, else restore
255
            return io_saveFile($file,$out);
256
        }
257
        return false;
258
    }
259
260
    /**
261
     * Rebuild the set of local plugins
262
     *
263
     * @return array array of plugins to be saved in end($config_cascade['plugins']['local'])
264
     */
265
    protected function rebuildLocal() {
266
        //assign to local variable to avoid overwriting
267
        $backup = $this->tmp_plugins;
268
        //Can't do anything about protected one so rule them out completely
269
        $local_default = array_diff_key($backup,$this->plugin_cascade['protected']);
270
        //Diff between local+default and default
271
        //gives us the ones we need to check and save
272
        $diffed_ones = array_diff_key($local_default,$this->plugin_cascade['default']);
273
        //The ones which we are sure of (list of 0s not in default)
274
        $sure_plugins = array_filter($diffed_ones,array($this,'negate'));
275
        //the ones in need of diff
276
        $conflicts = array_diff_key($local_default,$diffed_ones);
277
        //The final list
278
        return array_merge($sure_plugins,array_diff_assoc($conflicts,$this->plugin_cascade['default']));
279
    }
280
281
    /**
282
     * Build the list of plugins and cascade
283
     *
284
     */
285
    protected function loadConfig() {
286
        global $config_cascade;
287
        foreach(array('default','protected') as $type) {
288
            if(array_key_exists($type,$config_cascade['plugins']))
289
                $this->plugin_cascade[$type] = $this->checkRequire($config_cascade['plugins'][$type]);
290
        }
291
        $local = $config_cascade['plugins']['local'];
292
        $this->last_local_config_file = array_pop($local);
293
        $this->plugin_cascade['local'] = $this->checkRequire(array($this->last_local_config_file));
294
        if(is_array($local)) {
295
            $this->plugin_cascade['default'] = array_merge(
296
                $this->plugin_cascade['default'],
297
                $this->checkRequire($local)
298
            );
299
        }
300
        $this->tmp_plugins = array_merge(
301
            $this->plugin_cascade['default'],
302
            $this->plugin_cascade['local'],
303
            $this->plugin_cascade['protected']
304
        );
305
    }
306
307
    /**
308
     * Returns a list of available plugin components of given type
309
     *
310
     * @param string $type      plugin_type name; the type of plugin to return,
311
     * @param bool   $enabled   true to return enabled plugins,
312
     *                          false to return disabled plugins
313
     * @return array of plugin components of requested type
314
     */
315
    protected function _getListByType($type, $enabled) {
316
        $master_list = $enabled
317
            ? array_keys(array_filter($this->tmp_plugins))
318
            : array_keys(array_filter($this->tmp_plugins,array($this,'negate')));
319
        $plugins = array();
320
321
        foreach ($master_list as $plugin) {
322
323
            $basedir = $this->get_directory($plugin);
324
            if (file_exists(DOKU_PLUGIN."$basedir/$type.php")){
325
                $plugins[] = $plugin;
326
                continue;
327
            }
328
329
            $typedir = DOKU_PLUGIN."$basedir/$type/";
330
            if (is_dir($typedir)) {
331
                if ($dp = opendir($typedir)) {
332
                    while (false !== ($component = readdir($dp))) {
333
                        if (substr($component,0,1) == '.' || strtolower(substr($component, -4)) != ".php") continue;
334
                        if (is_file($typedir.$component)) {
335
                            $plugins[] = $plugin.'_'.substr($component, 0, -4);
336
                        }
337
                    }
338
                    closedir($dp);
339
                }
340
            }
341
342
        }//foreach
343
344
        return $plugins;
345
    }
346
347
    /**
348
     * Split name in a plugin name and a component name
349
     *
350
     * @param string $name
351
     * @return array with
352
     *              - plugin name
353
     *              - and component name when available, otherwise empty string
354
     */
355
    protected function _splitName($name) {
356
        if (array_search($name, array_keys($this->tmp_plugins)) === false) {
357
            return explode('_',$name,2);
358
        }
359
360
        return array($name,'');
361
    }
362
363
    /**
364
     * Returns inverse boolean value of the input
365
     *
366
     * @param mixed $input
367
     * @return bool inversed boolean value of input
368
     */
369
    protected function negate($input) {
370
        return !(bool) $input;
371
    }
372
}
373