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

https://gitlab.com/vnsoftdev/amms · PHP · 294 lines · 141 code · 51 blank · 102 comment · 21 complexity · 4ee3cb7dada3ff2bf9a8fb05fc4aac41 MD5 · raw file

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