PageRenderTime 22ms CodeModel.GetById 12ms app.highlight 6ms RepoModel.GetById 1ms app.codeStats 0ms

/administrator/components/com_widgetkit/vendor/yootheme/framework/src/Plugin/PluginManager.php

https://gitlab.com/vnsoftdev/amms
PHP | 294 lines | 166 code | 42 blank | 86 comment | 15 complexity | 4ee3cb7dada3ff2bf9a8fb05fc4aac41 MD5 | raw file
  1<?php
  2
  3namespace YOOtheme\Framework\Plugin;
  4
  5use YOOtheme\Framework\Application;
  6use YOOtheme\Framework\ApplicationAware;
  7use YOOtheme\Framework\Plugin\Loader\LoaderInterface;
  8
  9class PluginManager implements \ArrayAccess, \IteratorAggregate
 10{
 11    /**
 12     * @var Application
 13     */
 14    protected $app;
 15
 16    /**
 17     * @var LoaderInterface[]
 18     */
 19    protected $loaders = array();
 20
 21    /**
 22     * @var array
 23     */
 24    protected $paths = array();
 25
 26    /**
 27     * @var array
 28     */
 29    protected $plugins = array();
 30
 31    /**
 32     * @var array
 33     */
 34    protected $registered = array();
 35
 36    /**
 37     * Constructor.
 38     *
 39     * @param Application $app
 40     */
 41    public function __construct(Application $app)
 42    {
 43        $this->app = $app;
 44    }
 45
 46    /**
 47     * Gets a plugin by name.
 48     *
 49     * @param  string $name
 50     * @return PluginInterface|null
 51     */
 52    public function get($name)
 53    {
 54        return isset($this->plugins[$name]) ? $this->plugins[$name] : null;
 55    }
 56
 57    /**
 58     * Gets all plugins.
 59     *
 60     * @return array
 61     */
 62    public function all()
 63    {
 64        return $this->plugins;
 65    }
 66
 67    /**
 68     * Loads plugins by name.
 69     *
 70     * @param string|array $plugins
 71     */
 72    public function load($plugins = array())
 73    {
 74        $resolved = array();
 75
 76        if (is_string($plugins)) {
 77            $plugins = (array) $plugins;
 78        }
 79
 80        $this->registerPlugins();
 81
 82        if (!$plugins) {
 83            $plugins = array_keys($this->registered);
 84        }
 85
 86        foreach ($plugins as $name) {
 87            $this->resolvePlugins($this->registered[$name], $resolved);
 88        }
 89
 90        $resolved = array_diff_key($resolved, $this->plugins);
 91
 92        foreach ($resolved as $name => $plugin) {
 93
 94            $plugin = $this->loadPlugin($name, $plugin);
 95
 96            if ($plugin instanceof ApplicationAware) {
 97                $plugin->setApplication($this->app);
 98            }
 99
100            $plugin->main($this->app);
101        }
102    }
103
104    /**
105     * Adds a plugin config loader.
106     *
107     * @param  LoaderInterface $loader
108     * @return self
109     */
110    public function addLoader(LoaderInterface $loader)
111    {
112        $this->loaders[] = $loader;
113
114        return $this;
115    }
116
117    /**
118     * Adds a plugin path(s).
119     *
120     * @param  string|array $paths
121     * @return self
122     */
123    public function addPath($paths)
124    {
125        $this->paths = array_merge($this->paths, (array) $paths);
126
127        return $this;
128    }
129
130    /**
131     * Checks if a plugin exists.
132     *
133     * @param  string $name
134     * @return bool
135     */
136    public function offsetExists($name)
137    {
138        return isset($this->plugins[$name]);
139    }
140
141    /**
142     * Gets a plugin by name.
143     *
144     * @param  string $name
145     * @return bool
146     */
147    public function offsetGet($name)
148    {
149        return $this->get($name);
150    }
151
152    /**
153     * Sets a plugin.
154     *
155     * @param string $name
156     * @param string $plugin
157     */
158    public function offsetSet($name, $plugin)
159    {
160        $this->plugins[$name] = $plugin;
161    }
162
163    /**
164     * Unset a plugin.
165     *
166     * @param string $name
167     */
168    public function offsetUnset($name)
169    {
170        unset($this->plugins[$name]);
171    }
172
173    /**
174     * Implements the IteratorAggregate.
175     *
176     * @return \ArrayIterator
177     */
178    public function getIterator()
179    {
180        return new \ArrayIterator($this->plugins);
181    }
182
183    /**
184     * Loads a plugin.
185     *
186     * @param  string $name
187     * @param  array  $plugin
188     * @return array
189     */
190    protected function loadPlugin($name, $plugin)
191    {
192        foreach ($this->loaders as $loader) {
193            $plugin = $loader->load($name, $plugin);
194        }
195
196        if (isset($plugin['autoload'])) {
197            foreach ($plugin['autoload'] as $namespace => $path) {
198                $this->app['autoloader']->addPsr4($namespace, $this->resolvePath($plugin, $path));
199            }
200        }
201
202        $class = is_string($plugin['main']) ? $plugin['main'] : 'YOOtheme\\Framework\\Plugin\\Plugin';
203
204        return $this->plugins[$name] = new $class($plugin);
205    }
206
207    /**
208     * Register plugins from paths.
209     */
210    protected function registerPlugins()
211    {
212        $includes = array();
213
214        foreach ($this->paths as $path) {
215
216            $paths = glob($path, GLOB_NOSORT) ?: array();
217
218            foreach ($paths as $p) {
219
220                if (!is_array($plugin = include $p) || !isset($plugin['name'])) {
221                    continue;
222                }
223
224                if (!isset($plugin['main'])) {
225                    $plugin['main'] = null;
226                }
227
228                $plugin['path'] = strtr(dirname($p), '\\', '/');
229
230                if (isset($plugin['include'])) {
231                    foreach ((array) $plugin['include'] as $include) {
232                        $includes[] = $this->resolvePath($plugin, $include);
233                    }
234                }
235
236                $this->registered[$plugin['name']] = $plugin;
237            }
238        }
239
240        if ($this->paths = $includes) {
241            $this->registerPlugins();
242        }
243    }
244
245    /**
246     * Resolves plugin requirements.
247     *
248     * @param array $plugin
249     * @param array $resolved
250     * @param array $unresolved
251     *
252     * @throws \RuntimeException
253     */
254    protected function resolvePlugins($plugin, &$resolved = array(), &$unresolved = array())
255    {
256        $unresolved[$plugin['name']] = $plugin;
257
258        if (isset($plugin['require'])) {
259            foreach ((array) $plugin['require'] as $required) {
260                if (!isset($resolved[$required])) {
261
262                    if (isset($unresolved[$required])) {
263                        throw new \RuntimeException(sprintf('Circular requirement "%s > %s" detected.', $plugin['name'], $required));
264                    }
265
266                    if (isset($this->registered[$required])) {
267                        $this->resolvePlugins($this->registered[$required], $resolved, $unresolved);
268                    }
269                }
270            }
271        }
272
273        $resolved[$plugin['name']] = $plugin;
274        unset($unresolved[$plugin['name']]);
275    }
276
277    /**
278     * Resolves a path to a absolute plugin path.
279     *
280     * @param  array  $plugin
281     * @param  string $path
282     * @return string
283     */
284    protected function resolvePath($plugin, $path)
285    {
286        $path = strtr($path, '\\', '/');
287
288        if (!($path[0] == '/' || (strlen($path) > 3 && ctype_alpha($path[0]) && $path[1] == ':' && $path[2] == '/'))) {
289            $path = $plugin['path']."/$path";
290        }
291
292        return $path;
293    }
294}