123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330 |
- <?php
- /**
- * @package Grav\Common
- *
- * @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
- * @license MIT License; see LICENSE file for details.
- */
- namespace Grav\Common;
- use Exception;
- use Grav\Common\Config\Config;
- use Grav\Common\Data\Blueprints;
- use Grav\Common\Data\Data;
- use Grav\Common\File\CompiledYamlFile;
- use Grav\Events\PluginsLoadedEvent;
- use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
- use RuntimeException;
- use SplFileInfo;
- use Symfony\Component\EventDispatcher\EventDispatcher;
- use function get_class;
- use function is_object;
- /**
- * Class Plugins
- * @package Grav\Common
- */
- class Plugins extends Iterator
- {
- /** @var array|null */
- public $formFieldTypes;
- /** @var bool */
- private $plugins_initialized = false;
- /**
- * Plugins constructor.
- */
- public function __construct()
- {
- parent::__construct();
- /** @var UniformResourceLocator $locator */
- $locator = Grav::instance()['locator'];
- $iterator = $locator->getIterator('plugins://');
- $plugins = [];
- /** @var SplFileInfo $directory */
- foreach ($iterator as $directory) {
- if (!$directory->isDir()) {
- continue;
- }
- $plugins[] = $directory->getFilename();
- }
- sort($plugins, SORT_NATURAL | SORT_FLAG_CASE);
- foreach ($plugins as $plugin) {
- $object = $this->loadPlugin($plugin);
- if ($object) {
- $this->add($object);
- }
- }
- }
- /**
- * @return $this
- */
- public function setup()
- {
- $blueprints = [];
- $formFields = [];
- $grav = Grav::instance();
- /** @var Config $config */
- $config = $grav['config'];
- /** @var Plugin $plugin */
- foreach ($this->items as $plugin) {
- // Setup only enabled plugins.
- if ($config["plugins.{$plugin->name}.enabled"] && $plugin instanceof Plugin) {
- if (isset($plugin->features['blueprints'])) {
- $blueprints["plugin://{$plugin->name}/blueprints"] = $plugin->features['blueprints'];
- }
- if (method_exists($plugin, 'getFormFieldTypes')) {
- $formFields[get_class($plugin)] = $plugin->features['formfields'] ?? 0;
- }
- }
- }
- if ($blueprints) {
- // Order by priority.
- arsort($blueprints, SORT_NUMERIC);
- /** @var UniformResourceLocator $locator */
- $locator = $grav['locator'];
- $locator->addPath('blueprints', '', array_keys($blueprints), ['system', 'blueprints']);
- }
- if ($formFields) {
- // Order by priority.
- arsort($formFields, SORT_NUMERIC);
- $list = [];
- foreach ($formFields as $className => $priority) {
- $plugin = $this->items[$className];
- $list += $plugin->getFormFieldTypes();
- }
- $this->formFieldTypes = $list;
- }
- return $this;
- }
- /**
- * Registers all plugins.
- *
- * @return Plugin[] array of Plugin objects
- * @throws RuntimeException
- */
- public function init()
- {
- if ($this->plugins_initialized) {
- return $this->items;
- }
- $grav = Grav::instance();
- /** @var Config $config */
- $config = $grav['config'];
- /** @var EventDispatcher $events */
- $events = $grav['events'];
- foreach ($this->items as $instance) {
- // Register only enabled plugins.
- if ($config["plugins.{$instance->name}.enabled"] && $instance instanceof Plugin) {
- // Set plugin configuration.
- $instance->setConfig($config);
- // Register autoloader.
- if (method_exists($instance, 'autoload')) {
- $instance->setAutoloader($instance->autoload());
- }
- // Register event listeners.
- $events->addSubscriber($instance);
- }
- }
- // Plugins Loaded Event
- $event = new PluginsLoadedEvent($grav, $this);
- $grav->dispatchEvent($event);
- $this->plugins_initialized = true;
- return $this->items;
- }
- /**
- * Add a plugin
- *
- * @param Plugin $plugin
- * @return void
- */
- public function add($plugin)
- {
- if (is_object($plugin)) {
- $this->items[get_class($plugin)] = $plugin;
- }
- }
- /**
- * @return array
- */
- public function __debugInfo(): array
- {
- $array = (array)$this;
- unset($array["\0Grav\Common\Iterator\0iteratorUnset"]);
- return $array;
- }
- /**
- * @return Plugin[] Index of all plugins by plugin name.
- */
- public static function getPlugins(): array
- {
- /** @var Plugins $plugins */
- $plugins = Grav::instance()['plugins'];
- $list = [];
- foreach ($plugins as $instance) {
- $list[$instance->name] = $instance;
- }
- return $list;
- }
- /**
- * @param string $name Plugin name
- * @return Plugin|null Plugin object or null if plugin cannot be found.
- */
- public static function getPlugin(string $name)
- {
- $list = static::getPlugins();
- return $list[$name] ?? null;
- }
- /**
- * Return list of all plugin data with their blueprints.
- *
- * @return Data[]
- */
- public static function all()
- {
- $grav = Grav::instance();
- /** @var Plugins $plugins */
- $plugins = $grav['plugins'];
- $list = [];
- foreach ($plugins as $instance) {
- $name = $instance->name;
- try {
- $result = self::get($name);
- } catch (Exception $e) {
- $exception = new RuntimeException(sprintf('Plugin %s: %s', $name, $e->getMessage()), $e->getCode(), $e);
- /** @var Debugger $debugger */
- $debugger = $grav['debugger'];
- $debugger->addMessage("Plugin {$name} cannot be loaded, please check Exceptions tab", 'error');
- $debugger->addException($exception);
- continue;
- }
- if ($result) {
- $list[$name] = $result;
- }
- }
- return $list;
- }
- /**
- * Get a plugin by name
- *
- * @param string $name
- * @return Data|null
- */
- public static function get($name)
- {
- $blueprints = new Blueprints('plugins://');
- $blueprint = $blueprints->get("{$name}/blueprints");
- // Load default configuration.
- $file = CompiledYamlFile::instance("plugins://{$name}/{$name}" . YAML_EXT);
- // ensure this is a valid plugin
- if (!$file->exists()) {
- return null;
- }
- $obj = new Data((array)$file->content(), $blueprint);
- // Override with user configuration.
- $obj->merge(Grav::instance()['config']->get('plugins.' . $name) ?: []);
- // Save configuration always to user/config.
- $file = CompiledYamlFile::instance("config://plugins/{$name}.yaml");
- $obj->file($file);
- return $obj;
- }
- /**
- * @param string $name
- * @return Plugin|null
- */
- protected function loadPlugin($name)
- {
- // NOTE: ALL THE LOCAL VARIABLES ARE USED INSIDE INCLUDED FILE, DO NOT REMOVE THEM!
- $grav = Grav::instance();
- /** @var UniformResourceLocator $locator */
- $locator = $grav['locator'];
- $class = null;
- // Start by attempting to load the plugin_name.php file.
- $file = $locator->findResource('plugins://' . $name . DS . $name . PLUGIN_EXT);
- if (is_file($file)) {
- // Local variables available in the file: $grav, $name, $file
- $class = include_once $file;
- if (!is_object($class) || !is_subclass_of($class, Plugin::class, true)) {
- $class = null;
- }
- }
- // If the class hasn't been initialized yet, guess the class name and create a new instance.
- if (null === $class) {
- $className = Inflector::camelize($name);
- $pluginClassFormat = [
- 'Grav\\Plugin\\' . ucfirst($name). 'Plugin',
- 'Grav\\Plugin\\' . $className . 'Plugin',
- 'Grav\\Plugin\\' . $className
- ];
- foreach ($pluginClassFormat as $pluginClass) {
- if (is_subclass_of($pluginClass, Plugin::class, true)) {
- $class = new $pluginClass($name, $grav);
- break;
- }
- }
- }
- // Log a warning if plugin cannot be found.
- if (null === $class) {
- $grav['log']->addWarning(
- sprintf("Plugin '%s' enabled but not found! Try clearing cache with `bin/grav clearcache`", $name)
- );
- }
- return $class;
- }
- }
|