Completed
Push — master ( 43e9fe...cb024f )
by Cheren
10:21
created

Plugin::manifestEvent()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

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