diff --git a/lib/Cake/Console/TaskRegistry.php b/lib/Cake/Console/TaskRegistry.php index ce2d4fcfb22..3351923780f 100644 --- a/lib/Cake/Console/TaskRegistry.php +++ b/lib/Cake/Console/TaskRegistry.php @@ -41,48 +41,48 @@ public function __construct(Shell $Shell) { } /** - * Loads/constructs a task. Will return the instance in the registry if it already exists. + * Resolve a task classname. * - * You can alias your task as an existing task by setting the 'className' key, i.e., - * {{{ - * public $tasks = array( - * 'DbConfig' => array( - * 'className' => 'Bakeplus.DbConfigure' - * ); - * ); - * }}} - * All calls to the `DbConfig` task would use `DbConfigure` found in the `Bakeplus` plugin instead. + * Part of the template method for Cake\Utility\ObjectRegistry::load() * - * @param string $task Task name to load - * @param array $settings Settings for the task. - * @return Task A task object, Either the existing loaded task or a new one. - * @throws Cake\Error\MissingTaskException when the task could not be found + * @param string $class Partial classname to resolve. + * @return string|false Either the correct classname or false. */ - public function load($task, $settings = array()) { - if (is_array($settings) && isset($settings['className'])) { - $alias = $task; - $task = $settings['className']; - } - list($plugin, $name) = pluginSplit($task, true); - if (!isset($alias)) { - $alias = $name; - } - - if (isset($this->_loaded[$alias])) { - return $this->_loaded[$alias]; - } + protected function _resolveClassName($class) { + return App::classname($class, 'Console/Command/Task', 'Task'); + } - $taskClass = App::classname($task, 'Console/Command/Task', 'Task'); - if (!$taskClass) { - throw new Error\MissingTaskException(array( - 'class' => $name - )); - } +/** + * Throws an exception when a task is missing. + * + * Part of the template method for Cake\Utility\ObjectRegistry::load() + * + * @param string $class The classname that is missing. + * @param string $plugin The plugin the task is missing in. + * @throws Cake\Error\MissingTaskException + */ + protected function _throwMissingClassError($class, $plugin) { + throw new Error\MissingTaskException([ + 'class' => $class, + 'plugin' => $plugin + ]); + } - $this->_loaded[$alias] = new $taskClass( - $this->_Shell->stdout, $this->_Shell->stderr, $this->_Shell->stdin +/** + * Create the task instance. + * + * Part of the template method for Cake\Utility\ObjectRegistry::load() + * + * @param string $class The classname that is missing. + * @param array $settings An array of settings to use for the task. + * @return Component The constructed task class. + */ + protected function _create($class, $settings) { + return new $class( + $this->_Shell->stdout, + $this->_Shell->stderr, + $this->_Shell->stdin ); - return $this->_loaded[$alias]; } } diff --git a/lib/Cake/Controller/ComponentRegistry.php b/lib/Cake/Controller/ComponentRegistry.php index 3cff456e285..27435fb2760 100644 --- a/lib/Cake/Controller/ComponentRegistry.php +++ b/lib/Cake/Controller/ComponentRegistry.php @@ -65,51 +65,50 @@ public function getController() { } /** - * Loads/constructs a component. Will return the instance in the registry if it already exists. - * You can use `$settings['enabled'] = false` to disable callbacks on a component when loading it. - * Callbacks default to on. Disabled component methods work as normal, only callbacks are disabled. + * Resolve a component classname. * - * You can alias your component as an existing component by setting the 'className' key, i.e., - * {{{ - * public $components = array( - * 'Email' => array( - * 'className' => '\App\Controller\Component\AliasedEmailComponent' - * ); - * ); - * }}} - * All calls to the `Email` component would use `AliasedEmail` instead. + * Part of the template method for Cake\Utility\ObjectRegistry::load() * - * @param string $component Component name to load - * @param array $settings Settings for the component. - * @return Component A component object, Either the existing loaded component or a new one. - * @throws Cake\Error\MissingComponentException when the component could not be found + * @param string $class Partial classname to resolve. + * @return string|false Either the correct classname or false. */ - public function load($component, $settings = array()) { - if (is_array($settings) && isset($settings['className'])) { - $alias = $component; - $component = $settings['className']; - } - list($plugin, $name) = pluginSplit($component, true); - if (!isset($alias)) { - $alias = $name; - } - if (isset($this->_loaded[$alias])) { - return $this->_loaded[$alias]; - } - $componentClass = App::classname($plugin . $name, 'Controller/Component', 'Component'); - if (!$componentClass) { - throw new Error\MissingComponentException(array( - 'class' => $component, - 'plugin' => substr($plugin, 0, -1) - )); - } - $component = new $componentClass($this, $settings); + protected function _resolveClassName($class) { + return App::classname($class, 'Controller/Component', 'Component'); + } + +/** + * Throws an exception when a component is missing. + * + * Part of the template method for Cake\Utility\ObjectRegistry::load() + * + * @param string $class The classname that is missing. + * @param string $plugin The plugin the component is missing in. + * @throws Cake\Error\MissingComponentException + */ + protected function _throwMissingClassError($class, $plugin) { + throw new Error\MissingComponentException([ + 'class' => $class, + 'plugin' => $plugin + ]); + } + +/** + * Create the component instance. + * + * Part of the template method for Cake\Utility\ObjectRegistry::load() + * Enabled components will be registered with the event manager. + * + * @param string $class The classname that is missing. + * @param array $settings An array of settings to use for the component. + * @return Component The constructed component class. + */ + protected function _create($class, $settings) { + $instance = new $class($this, $settings); $enable = isset($settings['enabled']) ? $settings['enabled'] : true; if ($enable) { - $this->_eventManager->attach($component); + $this->_eventManager->attach($instance); } - $this->_loaded[$alias] = $component; - return $this->_loaded[$alias]; + return $instance; } } diff --git a/lib/Cake/Utility/ObjectRegistry.php b/lib/Cake/Utility/ObjectRegistry.php index e7bb54aad1f..7f1ac694f30 100644 --- a/lib/Cake/Utility/ObjectRegistry.php +++ b/lib/Cake/Utility/ObjectRegistry.php @@ -37,15 +37,74 @@ abstract class ObjectRegistry { protected $_loaded = []; /** - * Load instances for this registry. + * Loads/constructs a object instance. * - * Overridden in subclasses. + * Will return the instance in the registry if it already exists. + * You can use `$settings['enabled'] = false` to disable events on an object when loading it. + * Not all registry subclasses support events. + * + * You can alias an object by setting the 'className' key, i.e., + * {{{ + * public $components = [ + * 'Email' => [ + * 'className' => '\App\Controller\Component\AliasedEmailComponent' + * ]; + * ]; + * }}} + * + * All calls to the `Email` component would use `AliasedEmail` instead. * * @param string $name The name/class of the object to load. * @param array $settings Additional settings to use when loading the object. - * @return mixed. + * @return mixed + */ + public function load($objectName, $settings = []) { + list($plugin, $name) = pluginSplit($objectName); + if (isset($this->_loaded[$name])) { + return $this->_loaded[$name]; + } + if (is_array($settings) && isset($settings['className'])) { + $className = $this->_resolveClassName($settings['className']); + } + if (!isset($className)) { + $className = $this->_resolveClassName($objectName); + } + if (!$className) { + $this->_throwMissingClassError($objectName, substr($plugin, 0, -1)); + } + $instance = $this->_create($className, $settings); + $this->_loaded[$name] = $instance; + return $instance; + } + +/** + * Should resolve the classname for a given object type. + * + * @param string $class The class to resolve. + * @return string|false The resolved name or false for failure. + */ + abstract protected function _resolveClassName($class); + +/** + * Throw an exception when the requested object name is missing. + * + * @param string $class The class that is missing. + * @param string $plugin The plugin $class is missing from. + * @throw Cake\Exception + */ + abstract protected function _throwMissingClassError($class, $plugin); + +/** + * Create an instance of a given classname. + * + * This method should construct and do any other initialization logic + * required. + * + * @param string $class The class to build. + * @param array $settings The settings for construction + * @return mixed */ - abstract public function load($name, $settings = []); + abstract protected function _create($class, $settings); /** * Get the loaded object list, or get the object instance at a given name. diff --git a/lib/Cake/View/HelperRegistry.php b/lib/Cake/View/HelperRegistry.php index 385e39b2ded..9f27f662ba1 100644 --- a/lib/Cake/View/HelperRegistry.php +++ b/lib/Cake/View/HelperRegistry.php @@ -100,57 +100,54 @@ public function __get($name) { } /** - * Loads/constructs a helper. Will return the instance in the registry if it already exists. - * By setting `$enable` to false you can disable callbacks for a helper. Alternatively you - * can set `$settings['enabled'] = false` to disable callbacks. This alias is provided so that when - * declaring $helpers arrays you can disable callbacks on helpers. + * Resolve a helper classname. * - * You can alias your helper as an existing helper by setting the 'className' key, i.e., - * {{{ - * public $helpers = array( - * 'Html' => array( - * 'className' => '\App\View\Helper\AliasedHtmlHelper' - * ); - * ); - * }}} - * All calls to the `Html` helper would use `AliasedHtml` instead. + * Part of the template method for Cake\Utility\ObjectRegistry::load() * - * @param string $helper Helper name to load - * @param array $settings Settings for the helper. - * @return Helper A helper object, Either the existing loaded helper or a new one. - * @throws Cake\Error\MissingHelperException when the helper could not be found + * @param string $class Partial classname to resolve. + * @return string|false Either the correct classname or false. */ - public function load($helper, $settings = array()) { - list($plugin, $name) = pluginSplit($helper); - if (isset($this->_loaded[$name])) { - return $this->_loaded[$name]; - } - if (is_array($settings) && isset($settings['className'])) { - $helperClass = App::classname($settings['className'], 'View/Helper', 'Helper'); - } - if (!isset($helperClass)) { - $helperClass = App::classname($helper, 'View/Helper', 'Helper'); - } - if (!$helperClass) { - throw new Error\MissingHelperException(array( - 'class' => $helper, - 'plugin' => substr($plugin, 0, -1) - )); - } - $helperObject = new $helperClass($this->_View, $settings); + protected function _resolveClassName($class) { + return App::classname($class, 'View/Helper', 'Helper'); + } +/** + * Throws an exception when a helper is missing. + * + * Part of the template method for Cake\Utility\ObjectRegistry::load() + * + * @param string $class The classname that is missing. + * @param string $plugin The plugin the helper is missing in. + * @throws Cake\Error\MissingHelperException + */ + protected function _throwMissingClassError($class, $plugin) { + throw new Error\MissingHelperException([ + 'class' => $class, + 'plugin' => $plugin + ]); + } + +/** + * Create the helper instance. + * + * Part of the template method for Cake\Utility\ObjectRegistry::load() + * Enabled helpers will be registered with the event manager. + * + * @param string $class The classname that is missing. + * @param array $settings An array of settings to use for the helper. + * @return Component The constructed helper class. + */ + protected function _create($class, $settings) { + $instance = new $class($this->_View, $settings); $vars = array('request', 'theme', 'plugin'); foreach ($vars as $var) { - $helperObject->{$var} = $this->_View->{$var}; + $instance->{$var} = $this->_View->{$var}; } - - $this->_loaded[$name] = $helperObject; - $enable = isset($settings['enabled']) ? $settings['enabled'] : true; if ($enable) { - $this->_eventManager->attach($helperObject); + $this->_eventManager->attach($instance); } - return $helperObject; + return $instance; } }