Completed
Push — master ( 571822...c5142e )
by Cheren
09:31
created

Plugin::hasManifestEvent()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
/**
3
 * CakeCMS Core
4
 *
5
 * This file is part of the of the simple cms based on CakePHP 3.
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 *
9
 * @package     Core
10
 * @license     MIT
11
 * @copyright   MIT License http://www.opensource.org/licenses/mit-license.php
12
 * @link        https://github.com/CakeCMS/Core".
13
 * @author      Sergey Kalistratov <[email protected]>
14
 */
15
16
namespace Core;
17
18
use Cake\Core\App;
19
use JBZoo\Utils\FS;
20
use JBZoo\Data\Data;
21
use JBZoo\Utils\Arr;
22
use Cake\Core\Configure;
23
use Cake\Core\Plugin as CakePlugin;
24
25
/**
26
 * Class Plugin
27
 *
28
 * @package Core
29
 */
30
class Plugin extends CakePlugin
31
{
32
33
    /**
34
     * Plugin bootstrap file.
35
     */
36
    const FILE_BOOTSTRAP = 'bootstrap.php';
37
38
    /**
39
     * Plugin routes file.
40
     */
41
    const FILE_ROUTES = 'routes.php';
42
43
    /**
44
     * The plugin manifest file name.
45
     */
46
    const PLUGIN_MANIFEST = 'plugin.manifest.php';
47
48
    /**
49
     * Hold plugin data.
50
     *
51
     * @var array
52
     */
53
    protected static $_data = [];
54
55
    /**
56
     * Holds a list of all plugin events from manifest file.
57
     *
58
     * @var array
59
     */
60
    protected static $_eventList = [];
61
62
    /**
63
     * Manifest callback list.
64
     *
65
     * @var array
66
     */
67
    protected static $_manifestEvents = [
68
        'Controller.initialize',
69
        'Controller.beforeRender',
70
        'Controller.beforeFilter',
71
        'Controller.beforeRedirect',
72
        'Controller.afterFilter',
73
        'View.initialize',
74
        'View.beforeRenderFile',
75
        'View.afterRenderFile',
76
        'View.beforeRender',
77
        'View.afterRender',
78
        'View.beforeLayout',
79
    ];
80
81
    /**
82
     * Get plugin manifest data.
83
     *
84
     * @param string $plugin
85
     * @param null|string $key
86
     * @return Data
87
     */
88
    public static function getData($plugin, $key = null)
89
    {
90
        $data = self::_checkData($plugin);
91
        if (empty($data) && $path = self::getManifestPath($plugin)) {
92
            if (FS::isFile($path)) {
93
                /** @noinspection PhpIncludeInspection */
94
                $plgData = include $path;
95
                $plgData = (array) $plgData;
96
                if (!empty($plgData)) {
97
                    self::$_data[$plugin] = $plgData;
98
                    $data = $plgData;
99
                }
100
            }
101
        }
102
103
        return self::_getPluginData($data, $key);
104
    }
105
106
    /**
107
     * Get plugin locale path.
108
     *
109
     * @param string $plugin
110
     * @return string
111
     */
112
    public static function getLocalePath($plugin)
113
    {
114
        return self::path($plugin) . 'src' . DS . 'Locale' . DS;
115
    }
116
117
    /**
118
     * Get absolute plugin manifest file path.
119
     *
120
     * @param string $plugin
121
     * @return null|string
122
     */
123
    public static function getManifestPath($plugin)
124
    {
125
        if (self::loaded($plugin)) {
126
            return FS::clean(self::path($plugin) . DS . self::PLUGIN_MANIFEST);
127
        }
128
129
        return null;
130
    }
131
132
    /**
133
     * Check manifest event.
134
     *
135
     * @param   string $name Plugin name.
136
     * @return  bool
137
     */
138
    public static function hasManifestEvent($name)
139
    {
140
        return Arr::in($name, self::$_manifestEvents);
141
    }
142
143
    /**
144
     * Load the plugin.
145
     *
146
     * @param array|string $plugin
147
     * @param array $config
148
     */
149
    public static function load($plugin, array $config = [])
150
    {
151
        parent::load($plugin, $config);
152
153
        $plugin = (array) $plugin;
154
        foreach ($plugin as $name) {
155
            if ((bool) self::loaded($name)) {
156
                self::_addManifestCallback($name);
157
                Cms::mergeConfig('App.paths.locales', self::getLocalePath($name));
158
            }
159
        }
160
    }
161
162
    /**
163
     * Load list plugin.
164
     *
165
     * @param array $plugins
166
     * @return void
167
     */
168
    public static function loadList(array $plugins)
169
    {
170
        foreach ($plugins as $name) {
171
            if (self::loaded($name)) {
172
                continue;
173
            }
174
175
            if ($path = self::_findPlugin($name)) {
176
                self::load($name, self::_getConfigForLoad($path));
177
            }
178
        }
179
    }
180
181
    /**
182
     * Call plugin manifest callbacks.
183
     *
184
     * @return void
185
     */
186
    public static function manifestEvent()
187
    {
188
        $args     = func_get_args();
189
        $callback = array_shift($args);
190
191
        if (Arr::key($callback, self::$_eventList)) {
192
            $callbacks = self::$_eventList[$callback];
193
            foreach ($callbacks as $method) {
194
                call_user_func_array($method, $args);
195
            }
196
        }
197
    }
198
199
    /**
200
     * Unload the plugin.
201
     *
202
     * @param null|string $plugin
203
     * @return void
204
     */
205
    public static function unload($plugin = null)
206
    {
207
        if (self::loaded($plugin)) {
208
            $locales = Configure::read('App.paths.locales');
209
            foreach ($locales as $key => $path) {
210
                if ($path == self::getLocalePath($plugin)) {
211
                    unset($locales[$key]);
212
                }
213
            }
214
215
            Configure::write('App.paths.locales', $locales);
216
        }
217
218
        parent::unload($plugin);
219
    }
220
221
    /**
222
     * Registration plugin manifest callbacks.
223
     *
224
     * @param string $plugin
225
     * @return void
226
     */
227
    protected static function _addManifestCallback($plugin)
228
    {
229
        $data = Plugin::getData($plugin);
230
        foreach ($data as $name => $callback) {
231
            if (self::_isCallablePluginData($name, $plugin, $callback) && $plugin !== 'Core') {
232
                self::$_eventList[$name][$plugin] = $callback;
233
            }
234
        }
235
    }
236
237
    /**
238
     * Check plugin data.
239
     *
240
     * @param string $plugin
241
     * @return array
242
     */
243
    protected static function _checkData($plugin)
244
    {
245
        return (Arr::in($plugin, self::$_data)) ? self::$_data[$plugin] : [];
246
    }
247
248
    /**
249
     * Find plugin dir in registered paths.
250
     *
251
     * @param string $name
252
     * @return null|string
253
     */
254
    protected static function _findPlugin($name)
255
    {
256
        $output = null;
257
        $paths  = App::path('Plugin');
258
        $plugin = Configure::read('plugins.' . $name);
259
260
        if ($plugin !== null) {
261
            return $plugin;
262
        }
263
264
        foreach ($paths as $path) {
265
            $plgPath = $path . $name . DS;
266
            if (FS::isDir($plgPath)) {
267
                $output = $plgPath;
268
                break;
269
            }
270
        }
271
272
        return $output;
273
    }
274
275
    /**
276
     * Get plugin configuration for load plugin.
277
     *
278
     * @param string $path
279
     * @return array
280
     */
281
    protected static function _getConfigForLoad($path)
282
    {
283
        $config    = ['autoload' => true];
284
        $routes    = $path . 'config' . DS . Plugin::FILE_ROUTES;
285
        $bootstrap = $path . 'config' . DS . Plugin::FILE_BOOTSTRAP;
286
287
        if (FS::isFile($bootstrap)) {
288
            $config['bootstrap'] = true;
289
        }
290
291
        if (FS::isFile($routes)) {
292
            $config['routes'] = true;
293
        }
294
295
        $config['path'] = $path;
296
297
        return $config;
298
    }
299
300
    /**
301
     * Get current plugin data.
302
     *
303
     * @param array $data
304
     * @param null|string $key
305
     * @return Data
306
     */
307
    protected static function _getPluginData(array $data, $key = null)
308
    {
309
        if (isset($data[$key])) {
310
            $data = $data[$key];
311
        }
312
313
        return new Data($data);
314
    }
315
316
    /**
317
     * Check manifest param on callable.
318
     *
319
     * @param string $name
320
     * @param string $plugin
321
     * @param mixed $callback
322
     * @return bool
323
     */
324
    protected static function _isCallablePluginData($name, $plugin, $callback)
325
    {
326
        if (Arr::in($name, self::$_manifestEvents) &&
327
            !isset(self::$_eventList[$name][$plugin]) &&
328
            is_callable($callback)
329
        ) {
330
            return true;
331
        }
332
333
        return false;
334
    }
335
}
336