Plugins.php 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. <?php
  2. /**
  3. * @package Grav\Common
  4. *
  5. * @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
  6. * @license MIT License; see LICENSE file for details.
  7. */
  8. namespace Grav\Common;
  9. use Grav\Common\Config\Config;
  10. use Grav\Common\Data\Blueprints;
  11. use Grav\Common\Data\Data;
  12. use Grav\Common\File\CompiledYamlFile;
  13. use RocketTheme\Toolbox\Event\EventDispatcher;
  14. use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
  15. class Plugins extends Iterator
  16. {
  17. public $formFieldTypes;
  18. public function __construct()
  19. {
  20. parent::__construct();
  21. /** @var UniformResourceLocator $locator */
  22. $locator = Grav::instance()['locator'];
  23. $iterator = $locator->getIterator('plugins://');
  24. $plugins = [];
  25. foreach($iterator as $directory) {
  26. if (!$directory->isDir()) {
  27. continue;
  28. }
  29. $plugins[] = $directory->getFilename();
  30. }
  31. natsort($plugins);
  32. foreach ($plugins as $plugin) {
  33. $this->add($this->loadPlugin($plugin));
  34. }
  35. }
  36. /**
  37. * @return $this
  38. */
  39. public function setup()
  40. {
  41. $blueprints = [];
  42. $formFields = [];
  43. /** @var Plugin $plugin */
  44. foreach ($this->items as $plugin) {
  45. if (isset($plugin->features['blueprints'])) {
  46. $blueprints["plugin://{$plugin->name}/blueprints"] = $plugin->features['blueprints'];
  47. }
  48. if (method_exists($plugin, 'getFormFieldTypes')) {
  49. $formFields[get_class($plugin)] = isset($plugin->features['formfields']) ? $plugin->features['formfields'] : 0;
  50. }
  51. }
  52. if ($blueprints) {
  53. // Order by priority.
  54. arsort($blueprints);
  55. /** @var UniformResourceLocator $locator */
  56. $locator = Grav::instance()['locator'];
  57. $locator->addPath('blueprints', '', array_keys($blueprints), 'system/blueprints');
  58. }
  59. if ($formFields) {
  60. // Order by priority.
  61. arsort($formFields);
  62. $list = [];
  63. foreach ($formFields as $className => $priority) {
  64. $plugin = $this->items[$className];
  65. $list += $plugin->getFormFieldTypes();
  66. }
  67. $this->formFieldTypes = $list;
  68. }
  69. return $this;
  70. }
  71. /**
  72. * Registers all plugins.
  73. *
  74. * @return Plugin[] array of Plugin objects
  75. * @throws \RuntimeException
  76. */
  77. public function init()
  78. {
  79. $grav = Grav::instance();
  80. /** @var Config $config */
  81. $config = $grav['config'];
  82. /** @var EventDispatcher $events */
  83. $events = $grav['events'];
  84. foreach ($this->items as $instance) {
  85. // Register only enabled plugins.
  86. if ($config["plugins.{$instance->name}.enabled"] && $instance instanceof Plugin) {
  87. $instance->setConfig($config);
  88. $events->addSubscriber($instance);
  89. }
  90. }
  91. return $this->items;
  92. }
  93. /**
  94. * Add a plugin
  95. *
  96. * @param Plugin $plugin
  97. */
  98. public function add($plugin)
  99. {
  100. if (is_object($plugin)) {
  101. $this->items[get_class($plugin)] = $plugin;
  102. }
  103. }
  104. /**
  105. * Return list of all plugin data with their blueprints.
  106. *
  107. * @return array
  108. */
  109. public static function all()
  110. {
  111. $grav = Grav::instance();
  112. $plugins = $grav['plugins'];
  113. $list = [];
  114. foreach ($plugins as $instance) {
  115. $name = $instance->name;
  116. try {
  117. $result = self::get($name);
  118. } catch (\Exception $e) {
  119. $exception = new \RuntimeException(sprintf('Plugin %s: %s', $name, $e->getMessage()), $e->getCode(), $e);
  120. /** @var Debugger $debugger */
  121. $debugger = $grav['debugger'];
  122. $debugger->addMessage("Plugin {$name} cannot be loaded, please check Exceptions tab", 'error');
  123. $debugger->addException($exception);
  124. continue;
  125. }
  126. if ($result) {
  127. $list[$name] = $result;
  128. }
  129. }
  130. return $list;
  131. }
  132. /**
  133. * Get a plugin by name
  134. *
  135. * @param string $name
  136. *
  137. * @return Data|null
  138. */
  139. public static function get($name)
  140. {
  141. $blueprints = new Blueprints('plugins://');
  142. $blueprint = $blueprints->get("{$name}/blueprints");
  143. // Load default configuration.
  144. $file = CompiledYamlFile::instance("plugins://{$name}/{$name}" . YAML_EXT);
  145. // ensure this is a valid plugin
  146. if (!$file->exists()) {
  147. return null;
  148. }
  149. $obj = new Data((array)$file->content(), $blueprint);
  150. // Override with user configuration.
  151. $obj->merge(Grav::instance()['config']->get('plugins.' . $name) ?: []);
  152. // Save configuration always to user/config.
  153. $file = CompiledYamlFile::instance("config://plugins/{$name}.yaml");
  154. $obj->file($file);
  155. return $obj;
  156. }
  157. protected function loadPlugin($name)
  158. {
  159. $grav = Grav::instance();
  160. $locator = $grav['locator'];
  161. $file = $locator->findResource('plugins://' . $name . DS . $name . PLUGIN_EXT);
  162. if (is_file($file)) {
  163. // Local variables available in the file: $grav, $config, $name, $file
  164. $class = include_once $file;
  165. $pluginClassFormat = [
  166. 'Grav\\Plugin\\' . ucfirst($name). 'Plugin',
  167. 'Grav\\Plugin\\' . Inflector::camelize($name) . 'Plugin'
  168. ];
  169. foreach ($pluginClassFormat as $pluginClass) {
  170. if (class_exists($pluginClass)) {
  171. $class = new $pluginClass($name, $grav);
  172. break;
  173. }
  174. }
  175. } else {
  176. $grav['log']->addWarning(
  177. sprintf("Plugin '%s' enabled but not found! Try clearing cache with `bin/grav clear-cache`", $name)
  178. );
  179. return null;
  180. }
  181. return $class;
  182. }
  183. }