123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431 |
- <?php
- /**
- * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
- * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
- *
- * Licensed under The MIT License
- * For full copyright and license information, please see the LICENSE.txt
- * Redistributions of files must retain the above copyright notice.
- *
- * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
- * @link https://cakephp.org CakePHP(tm) Project
- * @since 2.0.0
- * @license https://opensource.org/licenses/mit-license.php MIT License
- */
- namespace Cake\Core;
- use Cake\Core\Exception\MissingPluginException;
- use DirectoryIterator;
- /**
- * Plugin is used to load and locate plugins.
- *
- * It also can retrieve plugin paths and load their bootstrap and routes files.
- *
- * @link https://book.cakephp.org/3.0/en/plugins.html
- */
- class Plugin
- {
- /**
- * Holds a list of all loaded plugins and their configuration
- *
- * @var \Cake\Core\PluginCollection|null
- */
- protected static $plugins;
- /**
- * Class loader instance
- *
- * @var \Cake\Core\ClassLoader
- */
- protected static $_loader;
- /**
- * Loads a plugin and optionally loads bootstrapping,
- * routing files or runs an initialization function.
- *
- * Plugins only need to be loaded if you want bootstrapping/routes/cli commands to
- * be exposed. If your plugin does not expose any of these features you do not need
- * to load them.
- *
- * This method does not configure any autoloaders. That must be done separately either
- * through composer, or your own code during config/bootstrap.php.
- *
- * ### Examples:
- *
- * `Plugin::load('DebugKit')`
- *
- * Will load the DebugKit plugin and will not load any bootstrap nor route files.
- * However, the plugin will be part of the framework default routes, and have its
- * CLI tools (if any) available for use.
- *
- * `Plugin::load('DebugKit', ['bootstrap' => true, 'routes' => true])`
- *
- * Will load the bootstrap.php and routes.php files.
- *
- * `Plugin::load('DebugKit', ['bootstrap' => false, 'routes' => true])`
- *
- * Will load routes.php file but not bootstrap.php
- *
- * `Plugin::load('FOC/Authenticate')`
- *
- * Will load plugin from `plugins/FOC/Authenticate`.
- *
- * It is also possible to load multiple plugins at once. Examples:
- *
- * `Plugin::load(['DebugKit', 'ApiGenerator'])`
- *
- * Will load the DebugKit and ApiGenerator plugins.
- *
- * `Plugin::load(['DebugKit', 'ApiGenerator'], ['bootstrap' => true])`
- *
- * Will load bootstrap file for both plugins
- *
- * ```
- * Plugin::load([
- * 'DebugKit' => ['routes' => true],
- * 'ApiGenerator'
- * ],
- * ['bootstrap' => true])
- * ```
- *
- * Will only load the bootstrap for ApiGenerator and only the routes for DebugKit
- *
- * ### Configuration options
- *
- * - `bootstrap` - array - Whether or not you want the $plugin/config/bootstrap.php file loaded.
- * - `routes` - boolean - Whether or not you want to load the $plugin/config/routes.php file.
- * - `ignoreMissing` - boolean - Set to true to ignore missing bootstrap/routes files.
- * - `path` - string - The path the plugin can be found on. If empty the default plugin path (App.pluginPaths) will be used.
- * - `classBase` - The path relative to `path` which contains the folders with class files.
- * Defaults to "src".
- * - `autoload` - boolean - Whether or not you want an autoloader registered. This defaults to false. The framework
- * assumes you have configured autoloaders using composer. However, if your application source tree is made up of
- * plugins, this can be a useful option.
- *
- * @param string|array $plugin name of the plugin to be loaded in CamelCase format or array or plugins to load
- * @param array $config configuration options for the plugin
- * @throws \Cake\Core\Exception\MissingPluginException if the folder for the plugin to be loaded is not found
- * @return void
- * @deprecated 3.7.0 This method will be removed in 4.0.0. Use Application::addPlugin() instead.
- */
- public static function load($plugin, array $config = [])
- {
- deprecationWarning(
- 'Plugin::load() is deprecated. ' .
- 'Use Application::addPlugin() instead. ' .
- 'This method will be removed in 4.0.0.'
- );
- if (is_array($plugin)) {
- foreach ($plugin as $name => $conf) {
- list($name, $conf) = is_numeric($name) ? [$conf, $config] : [$name, $conf];
- static::load($name, $conf);
- }
- return;
- }
- $config += [
- 'autoload' => false,
- 'bootstrap' => false,
- 'routes' => false,
- 'console' => true,
- 'classBase' => 'src',
- 'ignoreMissing' => false,
- 'name' => $plugin
- ];
- if (!isset($config['path'])) {
- $config['path'] = static::getCollection()->findPath($plugin);
- }
- $config['classPath'] = $config['path'] . $config['classBase'] . DIRECTORY_SEPARATOR;
- if (!isset($config['configPath'])) {
- $config['configPath'] = $config['path'] . 'config' . DIRECTORY_SEPARATOR;
- }
- $pluginClass = str_replace('/', '\\', $plugin) . '\\Plugin';
- if (class_exists($pluginClass)) {
- $instance = new $pluginClass($config);
- } else {
- // Use stub plugin as this method will be removed long term.
- $instance = new BasePlugin($config);
- }
- static::getCollection()->add($instance);
- if ($config['autoload'] === true) {
- if (empty(static::$_loader)) {
- static::$_loader = new ClassLoader();
- static::$_loader->register();
- }
- static::$_loader->addNamespace(
- str_replace('/', '\\', $plugin),
- $config['path'] . $config['classBase'] . DIRECTORY_SEPARATOR
- );
- static::$_loader->addNamespace(
- str_replace('/', '\\', $plugin) . '\Test',
- $config['path'] . 'tests' . DIRECTORY_SEPARATOR
- );
- }
- if ($config['bootstrap'] === true) {
- static::bootstrap($plugin);
- }
- }
- /**
- * Will load all the plugins located in the default plugin folder.
- *
- * If passed an options array, it will be used as a common default for all plugins to be loaded
- * It is possible to set specific defaults for each plugins in the options array. Examples:
- *
- * ```
- * Plugin::loadAll([
- * ['bootstrap' => true],
- * 'DebugKit' => ['routes' => true],
- * ]);
- * ```
- *
- * The above example will load the bootstrap file for all plugins, but for DebugKit it will only load the routes file
- * and will not look for any bootstrap script.
- *
- * If a plugin has been loaded already, it will not be reloaded by loadAll().
- *
- * @param array $options Options.
- * @return void
- * @throws \Cake\Core\Exception\MissingPluginException
- * @deprecated 3.7.0 This method will be removed in 4.0.0.
- */
- public static function loadAll(array $options = [])
- {
- $plugins = [];
- foreach (App::path('Plugin') as $path) {
- if (!is_dir($path)) {
- continue;
- }
- $dir = new DirectoryIterator($path);
- foreach ($dir as $dirPath) {
- if ($dirPath->isDir() && !$dirPath->isDot()) {
- $plugins[] = $dirPath->getBasename();
- }
- }
- }
- if (Configure::check('plugins')) {
- $plugins = array_merge($plugins, array_keys(Configure::read('plugins')));
- $plugins = array_unique($plugins);
- }
- $collection = static::getCollection();
- foreach ($plugins as $p) {
- $opts = isset($options[$p]) ? $options[$p] : null;
- if ($opts === null && isset($options[0])) {
- $opts = $options[0];
- }
- if ($collection->has($p)) {
- continue;
- }
- static::load($p, (array)$opts);
- }
- }
- /**
- * Returns the filesystem path for a plugin
- *
- * @param string $name name of the plugin in CamelCase format
- * @return string path to the plugin folder
- * @throws \Cake\Core\Exception\MissingPluginException if the folder for plugin was not found or plugin has not been loaded
- */
- public static function path($name)
- {
- $plugin = static::getCollection()->get($name);
- return $plugin->getPath();
- }
- /**
- * Returns the filesystem path for plugin's folder containing class folders.
- *
- * @param string $name name of the plugin in CamelCase format.
- * @return string Path to the plugin folder container class folders.
- * @throws \Cake\Core\Exception\MissingPluginException If plugin has not been loaded.
- */
- public static function classPath($name)
- {
- $plugin = static::getCollection()->get($name);
- return $plugin->getClassPath();
- }
- /**
- * Returns the filesystem path for plugin's folder containing config files.
- *
- * @param string $name name of the plugin in CamelCase format.
- * @return string Path to the plugin folder container config files.
- * @throws \Cake\Core\Exception\MissingPluginException If plugin has not been loaded.
- */
- public static function configPath($name)
- {
- $plugin = static::getCollection()->get($name);
- return $plugin->getConfigPath();
- }
- /**
- * Loads the bootstrapping files for a plugin, or calls the initialization setup in the configuration
- *
- * @param string $name name of the plugin
- * @return mixed
- * @see \Cake\Core\Plugin::load() for examples of bootstrap configuration
- * @deprecated 3.7.0 This method will be removed in 4.0.0.
- */
- public static function bootstrap($name)
- {
- deprecationWarning(
- 'Plugin::bootstrap() is deprecated. ' .
- 'This method will be removed in 4.0.0.'
- );
- $plugin = static::getCollection()->get($name);
- if (!$plugin->isEnabled('bootstrap')) {
- return false;
- }
- // Disable bootstrapping for this plugin as it will have
- // been bootstrapped.
- $plugin->disable('bootstrap');
- return static::_includeFile(
- $plugin->getConfigPath() . 'bootstrap.php',
- true
- );
- }
- /**
- * Loads the routes file for a plugin, or all plugins configured to load their respective routes file.
- *
- * If you need fine grained control over how routes are loaded for plugins, you
- * can use {@see Cake\Routing\RouteBuilder::loadPlugin()}
- *
- * @param string|null $name name of the plugin, if null will operate on all
- * plugins having enabled the loading of routes files.
- * @return bool
- * @deprecated 3.6.5 This method is no longer needed when using HttpApplicationInterface based applications.
- * This method will be removed in 4.0.0
- */
- public static function routes($name = null)
- {
- deprecationWarning(
- 'You no longer need to call `Plugin::routes()` after upgrading to use Http\Server. ' .
- 'See https://book.cakephp.org/3.0/en/development/application.html#adding-the-new-http-stack-to-an-existing-application ' .
- 'for upgrade information.'
- );
- if ($name === null) {
- foreach (static::loaded() as $p) {
- static::routes($p);
- }
- return true;
- }
- $plugin = static::getCollection()->get($name);
- if (!$plugin->isEnabled('routes')) {
- return false;
- }
- return (bool)static::_includeFile(
- $plugin->getConfigPath() . 'routes.php',
- true
- );
- }
- /**
- * Check whether or not a plugin is loaded.
- *
- * @param string $plugin The name of the plugin to check.
- * @return bool
- * @since 3.7.0
- */
- public static function isLoaded($plugin)
- {
- return static::getCollection()->has($plugin);
- }
- /**
- * Return a list of loaded plugins.
- *
- * If a plugin name is provided, the return value will be a bool
- * indicating whether or not the named plugin is loaded. This usage
- * is deprecated. Instead you should use Plugin::isLoaded($name)
- *
- * @param string|null $plugin Plugin name.
- * @return bool|array Boolean true if $plugin is already loaded.
- * If $plugin is null, returns a list of plugins that have been loaded
- */
- public static function loaded($plugin = null)
- {
- if ($plugin !== null) {
- deprecationWarning(
- 'Checking a single plugin with Plugin::loaded() is deprecated. ' .
- 'Use Plugin::isLoaded() instead.'
- );
- return static::getCollection()->has($plugin);
- }
- $names = [];
- foreach (static::getCollection() as $plugin) {
- $names[] = $plugin->getName();
- }
- sort($names);
- return $names;
- }
- /**
- * Forgets a loaded plugin or all of them if first parameter is null
- *
- * @param string|null $plugin name of the plugin to forget
- * @deprecated 3.7.0 This method will be removed in 4.0.0. Use PluginCollection::remove() or clear() instead.
- * @return void
- */
- public static function unload($plugin = null)
- {
- deprecationWarning('Plugin::unload() will be removed in 4.0. Use PluginCollection::remove() or clear()');
- if ($plugin === null) {
- static::getCollection()->clear();
- } else {
- static::getCollection()->remove($plugin);
- }
- }
- /**
- * Include file, ignoring include error if needed if file is missing
- *
- * @param string $file File to include
- * @param bool $ignoreMissing Whether to ignore include error for missing files
- * @return mixed
- */
- protected static function _includeFile($file, $ignoreMissing = false)
- {
- if ($ignoreMissing && !is_file($file)) {
- return false;
- }
- return include $file;
- }
- /**
- * Get the shared plugin collection.
- *
- * This method should generally not be used during application
- * runtime as plugins should be set during Application startup.
- *
- * @return \Cake\Core\PluginCollection
- */
- public static function getCollection()
- {
- if (!isset(static::$plugins)) {
- static::$plugins = new PluginCollection();
- }
- return static::$plugins;
- }
- }
|