Completed
Push — master ( a400a4...020752 )
by David
07:41 queued 04:43
created

lib/Dwoo/Loader.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * Copyright (c) 2013-2016
4
 *
5
 * @category  Library
6
 * @package   Dwoo
7
 * @author    Jordi Boggiano <[email protected]>
8
 * @author    David Sanchez <[email protected]>
9
 * @copyright 2008-2013 Jordi Boggiano
10
 * @copyright 2013-2016 David Sanchez
11
 * @license   http://dwoo.org/LICENSE Modified BSD License
12
 * @version   1.3.0
13
 * @date      2016-09-23
14
 * @link      http://dwoo.org/
15
 */
16
17
namespace Dwoo;
18
19
/**
20
 * Handles plugin loading and caching of plugins names/paths relationships.
21
 * This software is provided 'as-is', without any express or implied warranty.
22
 * In no event will the authors be held liable for any damages arising from the use of this software.
23
 */
24
class Loader implements ILoader
25
{
26
    /**
27
     * Stores the plugin directories.
28
     *
29
     * @see addDirectory
30
     * @var array
31
     */
32
    protected $paths = array();
33
34
    /**
35
     * Stores the plugins names/paths relationships
36
     * don't edit this on your own, use addDirectory.
37
     *
38
     * @see addDirectory
39
     * @var array
40
     */
41
    protected $classPath = array();
42
43
    /**
44
     * Path where class paths cache files are written.
45
     *
46
     * @var string
47
     */
48
    protected $cacheDir;
49
50
    /**
51
     * Path where builtin plugins are stored.
52
     *
53
     * @var string
54
     */
55
    protected $corePluginDir;
56
57
    /**
58
     * Loader constructor.
59
     *
60
     * @param $cacheDir
61
     */
62
    public function __construct($cacheDir)
63
    {
64
        $this->corePluginDir = __DIR__ . DIRECTORY_SEPARATOR . 'Plugins';
65
        $this->cacheDir      = rtrim($cacheDir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
66
67
        // include class paths or rebuild paths if the cache file isn't there
68
        $cacheFile = $this->cacheDir . 'classpath.cache.d' . Core::RELEASE_TAG . '.php';
69 View Code Duplication
        if (file_exists($cacheFile)) {
70
            $classpath       = file_get_contents($cacheFile);
71
            $this->classPath = unserialize($classpath) + $this->classPath;
72
        } else {
73
            $this->rebuildClassPathCache($this->corePluginDir, $cacheFile);
74
        }
75
    }
76
77
    /**
78
     * Rebuilds class paths, scans the given directory recursively and saves all paths in the given file.
79
     *
80
     * @param string $path      the plugin path to scan
81
     * @param string $cacheFile the file where to store the plugin paths cache, it will be overwritten
82
     *
83
     * @throws Exception
84
     */
85
    protected function rebuildClassPathCache($path, $cacheFile)
86
    {
87
        if ($cacheFile !== false) {
88
            $tmp             = $this->classPath;
89
            $this->classPath = array();
90
        }
91
92
        // iterates over all files/folders
93
        $list = glob(rtrim($path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . '*');
94
        if (is_array($list)) {
95
            foreach ($list as $f) {
96
                if (is_dir($f)) {
97
                    $this->rebuildClassPathCache($f, false);
0 ignored issues
show
false is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
98
                } else {
99
                    // TODO: is it still valid now?
100
                    $this->classPath[str_replace(array(
101
                        'function.',
102
                        'block.',
103
                        'modifier.',
104
                        'outputfilter.',
105
                        'filter.',
106
                        'prefilter.',
107
                        'postfilter.',
108
                        'pre.',
109
                        'post.',
110
                        'output.',
111
                        'shared.',
112
                        'helper.'
113
                    ), '', basename($f, '.php'))] = $f;
114
                }
115
            }
116
        }
117
118
        // save in file if it's the first call (not recursed)
119
        if ($cacheFile !== false) {
120
            if (!file_put_contents($cacheFile, serialize($this->classPath))) {
121
                throw new Exception('Could not write into ' . $cacheFile .
122
                    ', either because the folder is not there (create it) or because of the chmod configuration (please ensure this directory is writable by php), alternatively you can change the directory used with $dwoo->setCompileDir() or provide a custom loader object with $dwoo->setLoader()');
123
            }
124
            $this->classPath += $tmp;
0 ignored issues
show
The variable $tmp does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
125
        }
126
    }
127
128
    /**
129
     * Loads a plugin file.
130
     *
131
     * @param string $class       the plugin name, without the `Plugin` prefix
132
     * @param bool   $forceRehash if true, the class path caches will be rebuilt if the plugin is not found, in case it
133
     *                            has just been added, defaults to true
134
     *
135
     * @throws Exception
136
     */
137
    public function loadPlugin($class, $forceRehash = true)
138
    {
139
        /**
140
         * An unknown class was requested (maybe newly added) or the
141
         * include failed so we rebuild the cache. include() will fail
142
         * with an uncatchable error if the file doesn't exist, which
143
         * usually means that the cache is stale and must be rebuilt,
144
         * so we check for that before trying to include() the plugin.
145
         */
146
        if ((!isset($this->classPath[$class]) || !is_readable($this->classPath[$class])) || (!isset
147
                ($this->classPath[$class . 'Compile']) || !is_readable($this->classPath[$class . 'Compile']))) {
148
            if ($forceRehash) {
149
                $this->rebuildClassPathCache($this->corePluginDir, $this->cacheDir . 'classpath.cache.d' .
150
                    Core::RELEASE_TAG . '.php');
151
                foreach ($this->paths as $path => $file) {
152
                    $this->rebuildClassPathCache($path, $file);
153
                }
154
                if (isset($this->classPath[$class])) {
155
                    include_once $this->classPath[$class];
156
                } elseif (isset($this->classPath[$class . 'Compile'])) {
157
                    include_once $this->classPath[$class . 'Compile'];
158
                } else {
159
                    throw new Exception('Plugin "' . $class .
160
                        '" can not be found, maybe you forgot to bind it if it\'s a custom plugin ?', E_USER_NOTICE);
161
                }
162
            } else {
163
                throw new Exception('Plugin "' . $class .
164
                    '" can not be found, maybe you forgot to bind it if it\'s a custom plugin ?', E_USER_NOTICE);
165
            }
166
        }
167
    }
168
169
    /**
170
     * Adds a plugin directory, the plugins found in the new plugin directory
171
     * will take precedence over the other directories (including the default
172
     * dwoo plugin directory), you can use this for example to override plugins
173
     * in a specific directory for a specific application while keeping all your
174
     * usual plugins in the same place for all applications.
175
     * TOCOM don't forget that php functions overrides are not rehashed so you
176
     * need to clear the classpath caches by hand when adding those.
177
     *
178
     * @param string $pluginDirectory the plugin path to scan
179
     *
180
     * @throws Exception
181
     */
182
    public function addDirectory($pluginDirectory)
183
    {
184
        $pluginDir = realpath($pluginDirectory);
185
        if (!$pluginDir) {
186
            throw new Exception('Plugin directory does not exist or can not be read : ' . $pluginDirectory);
187
        }
188
        $cacheFile = $this->cacheDir . 'classpath-' . substr(strtr($pluginDir, '/\\:' . PATH_SEPARATOR, '----'),
189
                strlen($pluginDir) > 80 ? - 80 : 0) . '.d' . Core::RELEASE_TAG . '.php';
190
        $this->paths[$pluginDir] = $cacheFile;
191 View Code Duplication
        if (file_exists($cacheFile)) {
192
            $classpath       = file_get_contents($cacheFile);
193
            $this->classPath = unserialize($classpath) + $this->classPath;
194
        } else {
195
            $this->rebuildClassPathCache($pluginDir, $cacheFile);
196
        }
197
    }
198
}
199