Completed
Push — master ( f5777b...43e9fe )
by Cheren
01:50
created

Plugin::hasMigration()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 14
rs 9.2
c 0
b 0
f 0
cc 4
eloc 8
nc 3
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 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
     * Check plugin need migration.
135
     *
136
     * @param string $plugin
137
     * @return bool
138
     */
139
    public static function hasMigration($plugin)
140
    {
141
        $manager = new Manager($plugin);
142
        $migrations = array_keys($manager->getMigrations());
143
        if (count($migrations)) {
144
            foreach ($migrations as $version) {
145
                if (!$manager->isMigrated($version)) {
146
                    return true;
147
                }
148
            }
149
        }
150
151
        return false;
152
    }
153
154
    /**
155
     * Load the plugin.
156
     *
157
     * @param array|string $plugin
158
     * @param array $config
159
     */
160
    public static function load($plugin, array $config = [])
161
    {
162
        parent::load($plugin, $config);
163
164
        $plugin = (array) $plugin;
165
        foreach ($plugin as $name) {
166
            if ((bool) self::loaded($name)) {
167
                self::_addManifestCallback($name);
168
                Cms::mergeConfig('App.paths.locales', self::getLocalePath($name));
169
            }
170
        }
171
    }
172
173
    /**
174
     * Load list plugin.
175
     *
176
     * @param array $plugins
177
     * @return void
178
     */
179
    public static function loadList(array $plugins)
180
    {
181
        foreach ($plugins as $name) {
182
            if (self::loaded($name)) {
183
                continue;
184
            }
185
186
            if ($path = self::_findPlugin($name)) {
187
                self::load($name, self::_getConfigForLoad($path));
188
            }
189
        }
190
    }
191
192
    /**
193
     * Call plugin manifest callbacks.
194
     *
195
     * @return void
196
     */
197
    public static function manifestEvent()
198
    {
199
        $args     = func_get_args();
200
        $callback = array_shift($args);
201
202
        if (Arr::key($callback, self::$_eventList)) {
203
            $callbacks = self::$_eventList[$callback];
204
            foreach ($callbacks as $method) {
205
                call_user_func_array($method, $args);
206
            }
207
        }
208
    }
209
210
    /**
211
     * Unload the plugin.
212
     *
213
     * @param null|string $plugin
214
     * @return void
215
     */
216
    public static function unload($plugin = null)
217
    {
218
        if (self::loaded($plugin)) {
219
            $locales = Configure::read('App.paths.locales');
220
            foreach ($locales as $key => $path) {
221
                if ($path == self::getLocalePath($plugin)) {
222
                    unset($locales[$key]);
223
                }
224
            }
225
226
            Configure::write('App.paths.locales', $locales);
227
        }
228
229
        parent::unload($plugin);
230
    }
231
232
    /**
233
     * Registration plugin manifest callbacks.
234
     *
235
     * @param string $plugin
236
     * @return void
237
     */
238
    protected static function _addManifestCallback($plugin)
239
    {
240
        $data = Plugin::getData($plugin);
241
        foreach ($data as $name => $callback) {
242
            if (self::_isCallablePluginData($name, $plugin, $callback)) {
243
                self::$_eventList[$name][$plugin] = $callback;
244
            }
245
        }
246
    }
247
248
    /**
249
     * Check plugin data.
250
     *
251
     * @param string $plugin
252
     * @return array
253
     */
254
    protected static function _checkData($plugin)
255
    {
256
        return (Arr::in($plugin, self::$_data)) ? self::$_data[$plugin] : [];
257
    }
258
259
    /**
260
     * Find plugin dir in registered paths.
261
     *
262
     * @param string $name
263
     * @return null|string
264
     */
265
    protected static function _findPlugin($name)
266
    {
267
        $output = null;
268
        $paths  = App::path('Plugin');
269
        $plugin = Configure::read('plugins.' . $name);
270
271
        if ($plugin !== null) {
272
            return $plugin;
273
        }
274
275
        foreach ($paths as $path) {
276
            $plgPath = $path . $name . DS;
277
            if (FS::isDir($plgPath)) {
278
                $output = $plgPath;
279
                break;
280
            }
281
        }
282
283
        return $output;
284
    }
285
286
    /**
287
     * Get plugin configuration for load plugin.
288
     *
289
     * @param string $path
290
     * @return array
291
     */
292
    protected static function _getConfigForLoad($path)
293
    {
294
        $config    = ['autoload' => true];
295
        $routes    = $path . 'config' . DS . Plugin::FILE_ROUTES;
296
        $bootstrap = $path . 'config' . DS . Plugin::FILE_BOOTSTRAP;
297
298
        if (FS::isFile($bootstrap)) {
299
            $config['bootstrap'] = true;
300
        }
301
302
        if (FS::isFile($routes)) {
303
            $config['routes'] = true;
304
        }
305
306
        $config['path'] = $path;
307
308
        return $config;
309
    }
310
311
    /**
312
     * Get current plugin data.
313
     *
314
     * @param array $data
315
     * @param null|string $key
316
     * @return Data
317
     */
318
    protected static function _getPluginData(array $data, $key = null)
319
    {
320
        if (isset($data[$key])) {
321
            $data = $data[$key];
322
        }
323
324
        return new Data($data);
325
    }
326
327
    /**
328
     * Check manifest param on callable.
329
     *
330
     * @param string $name
331
     * @param string $plugin
332
     * @param mixed $callback
333
     * @return bool
334
     */
335
    protected static function _isCallablePluginData($name, $plugin, $callback)
336
    {
337
        if (Arr::in($name, self::$_manifestEvents) &&
338
            !isset(self::$_eventList[$name][$plugin]) &&
339
            is_callable($callback)
340
        ) {
341
            return true;
342
        }
343
344
        return false;
345
    }
346
}
347