PicoDeprecated   B
last analyzed

Complexity

Total Complexity 49

Size/Duplication

Total Lines 394
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1
Metric Value
wmc 49
lcom 1
cbo 1
dl 0
loc 394
rs 8.5454

21 Methods

Rating   Name   Duplication   Size   Complexity  
C onPluginsLoaded() 0 26 7
A onConfigLoaded() 0 9 1
D defineConstants() 0 25 8
B loadRootDirConfig() 0 20 5
B enablePlugins() 0 20 5
A onRequestUrl() 0 4 1
A onRequestFile() 0 4 1
A onContentLoading() 0 4 1
A onContentLoaded() 0 4 1
A on404ContentLoading() 0 4 1
A on404ContentLoaded() 0 4 1
A onMetaHeaders() 0 4 1
A onMetaParsed() 0 4 1
A onContentParsing() 0 4 1
A onContentParsed() 0 7 1
A onSinglePageLoaded() 0 4 1
B onPagesLoaded() 0 32 5
A onTwigRegistration() 0 4 1
A onPageRendering() 0 14 2
A onPageRendered() 0 4 1
A triggerEvent() 0 8 3

How to fix   Complexity   

Complex Class

Complex classes like PicoDeprecated often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use PicoDeprecated, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * Serve features of Pico deprecated since v1.0
5
 *
6
 * This plugin exists for backward compatibility and is disabled by default.
7
 * It gets automatically enabled when a plugin which doesn't implement
8
 * {@link PicoPluginInterface} is loaded. This plugin triggers deprecated
9
 * events and automatically enables {@link PicoParsePagesContent} and
10
 * {@link PicoExcerpt}. These plugins heavily impact Pico's performance! You
11
 * can disable this plugin by calling {@link PicoDeprecated::setEnabled()}.
12
 *
13
 * The following deprecated events are triggered by this plugin:
14
 *
15
 * | Event               | ... triggers the deprecated event                         |
16
 * | ------------------- | --------------------------------------------------------- |
17
 * | onPluginsLoaded     | plugins_loaded()                                          |
18
 * | onConfigLoaded      | config_loaded($config)                                    |
19
 * | onRequestUrl        | request_url($url)                                         |
20
 * | onContentLoading    | before_load_content($file)                                |
21
 * | onContentLoaded     | after_load_content($file, $rawContent)                    |
22
 * | on404ContentLoading | before_404_load_content($file)                            |
23
 * | on404ContentLoaded  | after_404_load_content($file, $rawContent)                |
24
 * | onMetaHeaders       | before_read_file_meta($headers)                           |
25
 * | onMetaParsed        | file_meta($meta)                                          |
26
 * | onContentParsing    | before_parse_content($rawContent)                         |
27
 * | onContentParsed     | after_parse_content($content)                             |
28
 * | onContentParsed     | content_parsed($content)                                  |
29
 * | onSinglePageLoaded  | get_page_data($pages, $meta)                              |
30
 * | onPagesLoaded       | get_pages($pages, $currentPage, $previousPage, $nextPage) |
31
 * | onTwigRegistration  | before_twig_register()                                    |
32
 * | onPageRendering     | before_render($twigVariables, $twig, $templateName)       |
33
 * | onPageRendered      | after_render($output)                                     |
34
 *
35
 * Since Pico 1.0 the config is stored in {@path "config/config.php"}. This
36
 * plugin tries to read {@path "config.php"} in Pico's root dir and overwrites
37
 * all settings previously specified in {@path "config/config.php"}.
38
 *
39
 * @author  Daniel Rudolf
40
 * @link    http://picocms.org
41
 * @license http://opensource.org/licenses/MIT
42
 * @version 1.0
43
 */
44
class PicoDeprecated extends AbstractPicoPlugin
45
{
46
    /**
47
     * This plugin is disabled by default
48
     *
49
     * @see AbstractPicoPlugin::$enabled
50
     */
51
    protected $enabled = false;
52
53
    /**
54
     * The requested file
55
     *
56
     * @see PicoDeprecated::getRequestFile()
57
     * @var string|null
58
     */
59
    protected $requestFile;
60
61
    /**
62
     * Enables this plugin on demand and triggers the deprecated event
63
     * plugins_loaded()
64
     *
65
     * @see DummyPlugin::onPluginsLoaded()
66
     */
67
    public function onPluginsLoaded(array &$plugins)
68
    {
69
        if (!empty($plugins)) {
70
            foreach ($plugins as $plugin) {
71
                if (!is_a($plugin, 'PicoPluginInterface')) {
72
                    // the plugin doesn't implement PicoPluginInterface; it uses deprecated events
73
                    // enable PicoDeprecated if it hasn't be explicitly enabled/disabled yet
74
                    if (!$this->isStatusChanged()) {
75
                        $this->setEnabled(true, true, true);
76
                    }
77
                    break;
78
                }
79
            }
80
        } else {
81
            // no plugins were found, so it actually isn't necessary to call deprecated events
82
            // anyway, this plugin also ensures compatibility apart from events used by old plugins,
83
            // so enable PicoDeprecated if it hasn't be explicitly enabled/disabled yet
84
            if (!$this->isStatusChanged()) {
85
                $this->setEnabled(true, true, true);
86
            }
87
        }
88
89
        if ($this->isEnabled()) {
90
            $this->triggerEvent('plugins_loaded');
91
        }
92
    }
93
94
    /**
95
     * Triggers the deprecated event config_loaded($config)
96
     *
97
     * This method also defines deprecated constants, reads the `config.php`
98
     * in Pico's root dir, enables the plugins {@link PicoParsePagesContent}
99
     * and {@link PicoExcerpt} and makes `$config` globally accessible (the
100
     * latter was removed with Pico 0.9 and was added again as deprecated
101
     * feature with Pico 1.0)
102
     *
103
     * @see    PicoDeprecated::defineConstants()
104
     * @see    PicoDeprecated::loadRootDirConfig()
105
     * @see    PicoDeprecated::enablePlugins()
106
     * @see    DummyPlugin::onConfigLoaded()
107
     * @param  array &$config array of config variables
108
     * @return void
109
     */
110
    public function onConfigLoaded(array &$config)
111
    {
112
        $this->defineConstants();
113
        $this->loadRootDirConfig($config);
114
        $this->enablePlugins();
115
        $GLOBALS['config'] = &$config;
116
117
        $this->triggerEvent('config_loaded', array(&$config));
118
    }
119
120
    /**
121
     * Defines deprecated constants
122
     *
123
     * `ROOT_DIR`, `LIB_DIR`, `PLUGINS_DIR`, `THEMES_DIR` and `CONTENT_EXT`
124
     * are deprecated since v1.0, `CONTENT_DIR` existed just in v0.9,
125
     * `CONFIG_DIR` just for a short time between v0.9 and v1.0 and
126
     * `CACHE_DIR` was dropped with v1.0 without a replacement.
127
     *
128
     * @see    PicoDeprecated::onConfigLoaded()
129
     * @return void
130
     */
131
    protected function defineConstants()
132
    {
133
        if (!defined('ROOT_DIR')) {
134
            define('ROOT_DIR', $this->getRootDir());
135
        }
136
        if (!defined('CONFIG_DIR')) {
137
            define('CONFIG_DIR', $this->getConfigDir());
138
        }
139
        if (!defined('LIB_DIR')) {
140
            $picoReflector = new ReflectionClass('Pico');
141
            define('LIB_DIR', dirname($picoReflector->getFileName()) . '/');
142
        }
143
        if (!defined('PLUGINS_DIR')) {
144
            define('PLUGINS_DIR', $this->getPluginsDir());
145
        }
146
        if (!defined('THEMES_DIR')) {
147
            define('THEMES_DIR', $this->getThemesDir());
148
        }
149
        if (!defined('CONTENT_DIR')) {
150
            define('CONTENT_DIR', $this->getConfig('content_dir'));
151
        }
152
        if (!defined('CONTENT_EXT')) {
153
            define('CONTENT_EXT', $this->getConfig('content_ext'));
154
        }
155
    }
156
157
    /**
158
     * Read config.php in Pico's root dir
159
     *
160
     * @see    PicoDeprecated::onConfigLoaded()
161
     * @see    Pico::loadConfig()
162
     * @param  array &$realConfig array of config variables
163
     * @return void
164
     */
165
    protected function loadRootDirConfig(array &$realConfig)
166
    {
167
        if (file_exists($this->getRootDir() . 'config.php')) {
168
            // config.php in Pico::$rootDir is deprecated
169
            // use config.php in Pico::$configDir instead
170
            $config = null;
171
            require($this->getRootDir() . 'config.php');
172
173
            if (is_array($config)) {
174
                if (isset($config['base_url'])) {
175
                    $config['base_url'] = rtrim($config['base_url'], '/') . '/';
176
                }
177
                if (isset($config['content_dir'])) {
178
                    $config['content_dir'] = rtrim($config['content_dir'], '/\\') . '/';
179
                }
180
181
                $realConfig = $config + $realConfig;
182
            }
183
        }
184
    }
185
186
    /**
187
     * Enables the plugins PicoParsePagesContent and PicoExcerpt
188
     *
189
     * @see    PicoParsePagesContent
190
     * @see    PicoExcerpt
191
     * @return void
192
     */
193
    protected function enablePlugins()
194
    {
195
        // enable PicoParsePagesContent and PicoExcerpt
196
        // we can't enable them during onPluginsLoaded because we can't know
197
        // if the user disabled us (PicoDeprecated) manually in the config
198
        $plugins = $this->getPlugins();
199
        if (isset($plugins['PicoParsePagesContent'])) {
200
            // parse all pages content if this plugin hasn't
201
            // be explicitly enabled/disabled yet
202
            if (!$plugins['PicoParsePagesContent']->isStatusChanged()) {
203
                $plugins['PicoParsePagesContent']->setEnabled(true, true, true);
204
            }
205
        }
206
        if (isset($plugins['PicoExcerpt'])) {
207
            // enable excerpt plugin if it hasn't be explicitly enabled/disabled yet
208
            if (!$plugins['PicoExcerpt']->isStatusChanged()) {
209
                $plugins['PicoExcerpt']->setEnabled(true, true, true);
210
            }
211
        }
212
    }
213
214
    /**
215
     * Triggers the deprecated event request_url($url)
216
     *
217
     * @see DummyPlugin::onRequestUrl()
218
     */
219
    public function onRequestUrl(&$url)
220
    {
221
        $this->triggerEvent('request_url', array(&$url));
222
    }
223
224
    /**
225
     * Sets PicoDeprecated::$requestFile to trigger the deprecated
226
     * events after_load_content() and after_404_load_content()
227
     *
228
     * @see PicoDeprecated::onContentLoaded()
229
     * @see PicoDeprecated::on404ContentLoaded()
230
     * @see DummyPlugin::onRequestFile()
231
     */
232
    public function onRequestFile(&$file)
233
    {
234
        $this->requestFile = &$file;
235
    }
236
237
    /**
238
     * Triggers the deprecated before_load_content($file)
239
     *
240
     * @see DummyPlugin::onContentLoading()
241
     */
242
    public function onContentLoading(&$file)
243
    {
244
        $this->triggerEvent('before_load_content', array(&$file));
245
    }
246
247
    /**
248
     * Triggers the deprecated event after_load_content($file, $rawContent)
249
     *
250
     * @see DummyPlugin::onContentLoaded()
251
     */
252
    public function onContentLoaded(&$rawContent)
253
    {
254
        $this->triggerEvent('after_load_content', array(&$this->requestFile, &$rawContent));
255
    }
256
257
    /**
258
     * Triggers the deprecated before_404_load_content($file)
259
     *
260
     * @see DummyPlugin::on404ContentLoading()
261
     */
262
    public function on404ContentLoading(&$file)
263
    {
264
        $this->triggerEvent('before_404_load_content', array(&$file));
265
    }
266
267
    /**
268
     * Triggers the deprecated event after_404_load_content($file, $rawContent)
269
     *
270
     * @see DummyPlugin::on404ContentLoaded()
271
     */
272
    public function on404ContentLoaded(&$rawContent)
273
    {
274
        $this->triggerEvent('after_404_load_content', array(&$this->requestFile, &$rawContent));
275
    }
276
277
    /**
278
     * Triggers the deprecated event before_read_file_meta($headers)
279
     *
280
     * @see DummyPlugin::onMetaHeaders()
281
     */
282
    public function onMetaHeaders(array &$headers)
283
    {
284
        $this->triggerEvent('before_read_file_meta', array(&$headers));
285
    }
286
287
    /**
288
     * Triggers the deprecated event file_meta($meta)
289
     *
290
     * @see DummyPlugin::onMetaParsed()
291
     */
292
    public function onMetaParsed(array &$meta)
293
    {
294
        $this->triggerEvent('file_meta', array(&$meta));
295
    }
296
297
    /**
298
     * Triggers the deprecated event before_parse_content($rawContent)
299
     *
300
     * @see DummyPlugin::onContentParsing()
301
     */
302
    public function onContentParsing(&$rawContent)
303
    {
304
        $this->triggerEvent('before_parse_content', array(&$rawContent));
305
    }
306
307
    /**
308
     * Triggers the deprecated events after_parse_content($content) and
309
     * content_parsed($content)
310
     *
311
     * @see DummyPlugin::onContentParsed()
312
     */
313
    public function onContentParsed(&$content)
314
    {
315
        $this->triggerEvent('after_parse_content', array(&$content));
316
317
        // deprecated since v0.8
318
        $this->triggerEvent('content_parsed', array(&$content));
319
    }
320
321
    /**
322
     * Triggers the deprecated event get_page_data($pages, $meta)
323
     *
324
     * @see DummyPlugin::onSinglePageLoaded()
325
     */
326
    public function onSinglePageLoaded(array &$pageData)
327
    {
328
        $this->triggerEvent('get_page_data', array(&$pageData, $pageData['meta']));
329
    }
330
331
    /**
332
     * Triggers the deprecated event
333
     * get_pages($pages, $currentPage, $previousPage, $nextPage)
334
     *
335
     * Please note that the `get_pages()` event gets `$pages` passed without a
336
     * array index. The index is rebuild later using either the `id` array key
337
     * or is derived from the `url` array key. Duplicates are prevented by
338
     * adding `~dup` when necessary.
339
     *
340
     * @see DummyPlugin::onPagesLoaded()
341
     */
342
    public function onPagesLoaded(
343
        array &$pages,
344
        array &$currentPage = null,
345
        array &$previousPage = null,
346
        array &$nextPage = null
347
    ) {
348
        // remove keys of pages array
349
        $plainPages = array();
350
        foreach ($pages as &$pageData) {
351
            $plainPages[] = &$pageData;
352
        }
353
        unset($pageData);
354
355
        $this->triggerEvent('get_pages', array(&$plainPages, &$currentPage, &$previousPage, &$nextPage));
356
357
        // re-index pages array
358
        $pages = array();
359
        foreach ($plainPages as &$pageData) {
360
            if (!isset($pageData['id'])) {
361
                $urlPrefixLength = strlen($this->getBaseUrl()) + intval(!$this->isUrlRewritingEnabled());
362
                $pageData['id'] = substr($pageData['url'], $urlPrefixLength);
363
            }
364
365
            // prevent duplicates
366
            $id = $pageData['id'];
367
            for ($i = 1; isset($pages[$id]); $i++) {
368
                $id = $pageData['id'] . '~dup' . $i;
369
            }
370
371
            $pages[$id] = &$pageData;
372
        }
373
    }
374
375
    /**
376
     * Triggers the deprecated event before_twig_register()
377
     *
378
     * @see DummyPlugin::onTwigRegistration()
379
     */
380
    public function onTwigRegistration()
381
    {
382
        $this->triggerEvent('before_twig_register');
383
    }
384
385
    /**
386
     * Triggers the deprecated event before_render($twigVariables, $twig, $templateName)
387
     *
388
     * Please note that the `before_render()` event gets `$templateName` passed
389
     * without its file extension. The file extension is later added again.
390
     *
391
     * @see DummyPlugin::onPageRendering()
392
     */
393
    public function onPageRendering(Twig_Environment &$twig, array &$twigVariables, &$templateName)
394
    {
395
        // template name contains file extension since Pico 1.0
396
        $fileExtension = '';
397
        if (($fileExtensionPos = strrpos($templateName, '.')) !== false) {
398
            $fileExtension = substr($templateName, $fileExtensionPos);
399
            $templateName = substr($templateName, 0, $fileExtensionPos);
400
        }
401
402
        $this->triggerEvent('before_render', array(&$twigVariables, &$twig, &$templateName));
403
404
        // add original file extension
405
        $templateName = $templateName . $fileExtension;
406
    }
407
408
    /**
409
     * Triggers the deprecated event after_render($output)
410
     *
411
     * @see DummyPlugin::onPageRendered()
412
     */
413
    public function onPageRendered(&$output)
414
    {
415
        $this->triggerEvent('after_render', array(&$output));
416
    }
417
418
    /**
419
     * Triggers a deprecated event on all plugins
420
     *
421
     * Deprecated events are also triggered on plugins which implement
422
     * {@link PicoPluginInterface}. Please note that the methods are called
423
     * directly and not through {@link PicoPluginInterface::handleEvent()}.
424
     *
425
     * @param  string $eventName event to trigger
426
     * @param  array  $params    parameters to pass
427
     * @return void
428
     */
429
    protected function triggerEvent($eventName, array $params = array())
430
    {
431
        foreach ($this->getPlugins() as $plugin) {
432
            if (method_exists($plugin, $eventName)) {
433
                call_user_func_array(array($plugin, $eventName), $params);
434
            }
435
        }
436
    }
437
}
438