mirror of
https://github.com/kamilwylegala/cakephp2-php8.git
synced 2025-09-04 18:42:40 +00:00
Starting to update Component into a base class instead of a loader class.
This commit is contained in:
parent
3666643b84
commit
bf75ab5737
2 changed files with 112 additions and 234 deletions
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
/**
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
* PHP 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
|
@ -16,65 +16,78 @@
|
|||
* @since CakePHP(tm) v 1.2
|
||||
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
||||
*/
|
||||
App::import('Controller', 'ComponentCollection', false);
|
||||
|
||||
/**
|
||||
* Handler for Controller::$components
|
||||
* Base class for an individual Component. Components provide resuable bits of
|
||||
* controller logic that can be composed into a controller. Components also
|
||||
* provide request life-cycle callbacks for injecting logic at specific points.
|
||||
*
|
||||
* @package cake
|
||||
* @subpackage cake.cake.libs.controller
|
||||
* @link http://book.cakephp.org/view/993/Components
|
||||
* @see Controller::$components
|
||||
*/
|
||||
class Component extends Object {
|
||||
|
||||
/**
|
||||
* Contains various controller variable information (plugin, name, base).
|
||||
* Component collection class used to lazy load components.
|
||||
*
|
||||
* @var object
|
||||
* @access private
|
||||
* @var ComponentCollection
|
||||
*/
|
||||
private $__controllerVars = array('plugin' => null, 'name' => null, 'base' => null);
|
||||
protected $_Collection;
|
||||
|
||||
/**
|
||||
* List of loaded components.
|
||||
*
|
||||
* @var object
|
||||
* @access protected
|
||||
*/
|
||||
protected $_loaded = array();
|
||||
|
||||
/**
|
||||
* List of components attached directly to the controller, which callbacks
|
||||
* should be executed on.
|
||||
*
|
||||
* @var object
|
||||
* @access protected
|
||||
*/
|
||||
protected $_primary = array();
|
||||
|
||||
/**
|
||||
* Settings for loaded components.
|
||||
* Settings for this Component
|
||||
*
|
||||
* @var array
|
||||
* @access private
|
||||
*/
|
||||
private $__settings = array();
|
||||
public $settings = array();
|
||||
|
||||
/**
|
||||
* Used to initialize the components for current controller.
|
||||
* Other Components this component uses.
|
||||
*
|
||||
* @param object $controller Controller with components to load
|
||||
* @return void
|
||||
* @var array
|
||||
*/
|
||||
public function init(&$controller) {
|
||||
if (!is_array($controller->components)) {
|
||||
return;
|
||||
}
|
||||
$this->__controllerVars = array(
|
||||
'plugin' => $controller->plugin, 'name' => $controller->name,
|
||||
'base' => $controller->base
|
||||
);
|
||||
public $components = array();
|
||||
|
||||
$this->_loadComponents($controller);
|
||||
/**
|
||||
* A component lookup table used to lazy load component objects.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_componentMap = array();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param ComponentCollection $collection A ComponentCollection this component can use to lazy load its components
|
||||
* @param array $settings Array of configuration settings.
|
||||
*/
|
||||
public function __construct(ComponentCollection $collection, $settings = array()) {
|
||||
$this->_Collection = $collection;
|
||||
$this->settings = $settings;
|
||||
|
||||
if (!empty($this->components)) {
|
||||
$this->_componentMap = ComponentCollection::normalizeObjectArray($this->components);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic method for lazy loading $components.
|
||||
*
|
||||
* @param sting $name Name of component to get.
|
||||
* @return mixed A Component object or null.
|
||||
*/
|
||||
public function __get($name) {
|
||||
if (isset($this->_componentMap[$name]) && !isset($this->{$name})) {
|
||||
$this->{$name} = $this->_Collection->load(
|
||||
$this->_componentMap[$name]['class'], $this->_componentMap[$name]['settings'], false
|
||||
);
|
||||
}
|
||||
if (isset($this->{$name})) {
|
||||
return $this->{$name};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -85,19 +98,7 @@ class Component extends Object {
|
|||
* @access public
|
||||
* @link http://book.cakephp.org/view/998/MVC-Class-Access-Within-Components
|
||||
*/
|
||||
function initialize(&$controller) {
|
||||
foreach (array_keys($this->_loaded) as $name) {
|
||||
$component =& $this->_loaded[$name];
|
||||
|
||||
if (method_exists($component,'initialize') && $component->enabled === true) {
|
||||
$settings = array();
|
||||
if (isset($this->__settings[$name])) {
|
||||
$settings = $this->__settings[$name];
|
||||
}
|
||||
$component->initialize($controller, $settings);
|
||||
}
|
||||
}
|
||||
}
|
||||
public function initialize(&$controller) { }
|
||||
|
||||
/**
|
||||
* Called after the Controller::beforeFilter() and before the controller action
|
||||
|
@ -106,11 +107,8 @@ class Component extends Object {
|
|||
* @return void
|
||||
* @access public
|
||||
* @link http://book.cakephp.org/view/998/MVC-Class-Access-Within-Components
|
||||
* @deprecated See Component::triggerCallback()
|
||||
*/
|
||||
function startup(&$controller) {
|
||||
$this->triggerCallback('startup', $controller);
|
||||
}
|
||||
public function startup(&$controller) { }
|
||||
|
||||
/**
|
||||
* Called after the Controller::beforeRender(), after the view class is loaded, and before the
|
||||
|
@ -119,11 +117,17 @@ class Component extends Object {
|
|||
* @param object $controller Controller with components to beforeRender
|
||||
* @return void
|
||||
* @access public
|
||||
* @deprecated See Component::triggerCallback()
|
||||
*/
|
||||
function beforeRender(&$controller) {
|
||||
$this->triggerCallback('beforeRender', $controller);
|
||||
}
|
||||
public function beforeRender(&$controller) { }
|
||||
|
||||
/**
|
||||
* Called after Controller::render() and before the output is printed to the browser.
|
||||
*
|
||||
* @param object $controller Controller with components to shutdown
|
||||
* @return void
|
||||
* @access public
|
||||
*/
|
||||
function shutdown(&$controller) { }
|
||||
|
||||
/**
|
||||
* Called before Controller::redirect().
|
||||
|
@ -148,112 +152,5 @@ class Component extends Object {
|
|||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after Controller::render() and before the output is printed to the browser.
|
||||
*
|
||||
* @param object $controller Controller with components to shutdown
|
||||
* @return void
|
||||
* @access public
|
||||
* @deprecated See Component::triggerCallback()
|
||||
*/
|
||||
function shutdown(&$controller) {
|
||||
$this->triggerCallback('shutdown', $controller);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger a callback on all primary components. Will fire $callback on all components
|
||||
* that have such a method. You can implement and fire custom callbacks in addition to the
|
||||
* standard ones.
|
||||
*
|
||||
* example use, from inside a controller:
|
||||
*
|
||||
* `$this->Component->triggerCallback('beforeFilter', $this);`
|
||||
*
|
||||
* will trigger the beforeFilter callback on all components that have implemented one. You
|
||||
* can trigger any method in this fashion.
|
||||
*
|
||||
* @param Controller $controller Controller instance
|
||||
* @param string $callback Callback to trigger.
|
||||
* @return void
|
||||
*/
|
||||
public function triggerCallback($callback, &$controller) {
|
||||
foreach ($this->_primary as $name) {
|
||||
$component =& $this->_loaded[$name];
|
||||
if (method_exists($component, $callback) && $component->enabled === true) {
|
||||
$component->{$callback}($controller);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads components used by this component.
|
||||
*
|
||||
* @param object $object Object with a Components array
|
||||
* @param object $parent the parent of the current object
|
||||
* @return void
|
||||
*/
|
||||
protected function _loadComponents(&$object, $parent = null) {
|
||||
$base = $this->__controllerVars['base'];
|
||||
$normal = Set::normalize($object->components);
|
||||
foreach ((array)$normal as $component => $config) {
|
||||
$plugin = isset($this->__controllerVars['plugin']) ? $this->__controllerVars['plugin'] . '.' : null;
|
||||
list($plugin, $component) = pluginSplit($component, true, $plugin);
|
||||
$componentCn = $component . 'Component';
|
||||
|
||||
if (!class_exists($componentCn)) {
|
||||
if (is_null($plugin) || !App::import('Component', $plugin . $component)) {
|
||||
if (!App::import('Component', $component)) {
|
||||
$this->cakeError('missingComponentFile', array(array(
|
||||
'className' => $this->__controllerVars['name'],
|
||||
'component' => $component,
|
||||
'file' => Inflector::underscore($component) . '.php',
|
||||
'base' => $base,
|
||||
'code' => 500
|
||||
)));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!class_exists($componentCn)) {
|
||||
$this->cakeError('missingComponentClass', array(array(
|
||||
'className' => $this->__controllerVars['name'],
|
||||
'component' => $component,
|
||||
'file' => Inflector::underscore($component) . '.php',
|
||||
'base' => $base,
|
||||
'code' => 500
|
||||
)));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($parent === null) {
|
||||
$this->_primary[] = $component;
|
||||
}
|
||||
|
||||
if (isset($this->_loaded[$component])) {
|
||||
$object->{$component} =& $this->_loaded[$component];
|
||||
|
||||
if (!empty($config) && isset($this->__settings[$component])) {
|
||||
$this->__settings[$component] = array_merge($this->__settings[$component], $config);
|
||||
} elseif (!empty($config)) {
|
||||
$this->__settings[$component] = $config;
|
||||
}
|
||||
} else {
|
||||
if ($componentCn === 'SessionComponent') {
|
||||
$object->{$component} =& new $componentCn($base);
|
||||
} else {
|
||||
$object->{$component} =& new $componentCn();
|
||||
}
|
||||
$object->{$component}->enabled = true;
|
||||
$this->_loaded[$component] =& $object->{$component};
|
||||
if (!empty($config)) {
|
||||
$this->__settings[$component] = $config;
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($object->{$component}->components) && is_array($object->{$component}->components) && (!isset($object->{$component}->{$parent}))) {
|
||||
$this->_loadComponents($object->{$component}, $component);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ if (!class_exists('AppController')) {
|
|||
* @package cake
|
||||
* @subpackage cake.tests.cases.libs.controller
|
||||
*/
|
||||
class ParamTestComponent extends Object {
|
||||
class ParamTestComponent extends Component {
|
||||
|
||||
/**
|
||||
* name property
|
||||
|
@ -140,7 +140,7 @@ class ComponentTestController extends AppController {
|
|||
* @package cake
|
||||
* @subpackage cake.tests.cases.libs.controller
|
||||
*/
|
||||
class AppleComponent extends Object {
|
||||
class AppleComponent extends Component {
|
||||
|
||||
/**
|
||||
* components property
|
||||
|
@ -176,7 +176,7 @@ class AppleComponent extends Object {
|
|||
* @package cake
|
||||
* @subpackage cake.tests.cases.libs.controller
|
||||
*/
|
||||
class OrangeComponent extends Object {
|
||||
class OrangeComponent extends Component {
|
||||
|
||||
/**
|
||||
* components property
|
||||
|
@ -216,7 +216,7 @@ class OrangeComponent extends Object {
|
|||
* @package cake
|
||||
* @subpackage cake.tests.cases.libs.controller
|
||||
*/
|
||||
class BananaComponent extends Object {
|
||||
class BananaComponent extends Component {
|
||||
|
||||
/**
|
||||
* testField property
|
||||
|
@ -243,7 +243,7 @@ class BananaComponent extends Object {
|
|||
* @package cake
|
||||
* @subpackage cake.tests.cases.libs.controller
|
||||
*/
|
||||
class MutuallyReferencingOneComponent extends Object {
|
||||
class MutuallyReferencingOneComponent extends Component {
|
||||
|
||||
/**
|
||||
* components property
|
||||
|
@ -260,7 +260,7 @@ class MutuallyReferencingOneComponent extends Object {
|
|||
* @package cake
|
||||
* @subpackage cake.tests.cases.libs.controller
|
||||
*/
|
||||
class MutuallyReferencingTwoComponent extends Object {
|
||||
class MutuallyReferencingTwoComponent extends Component {
|
||||
|
||||
/**
|
||||
* components property
|
||||
|
@ -277,7 +277,7 @@ class MutuallyReferencingTwoComponent extends Object {
|
|||
* @package cake
|
||||
* @subpackage cake.tests.cases.libs.controller
|
||||
*/
|
||||
class SomethingWithEmailComponent extends Object {
|
||||
class SomethingWithEmailComponent extends Component {
|
||||
|
||||
/**
|
||||
* components property
|
||||
|
@ -321,6 +321,18 @@ class ComponentTest extends CakeTestCase {
|
|||
ClassRegistry::flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* test accessing inner components.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function testInnerComponentConstruction() {
|
||||
$Collection = new ComponentCollection();
|
||||
$Component = new AppleComponent($Collection);
|
||||
|
||||
$this->assertType('OrangeComponent', $Component->Orange, 'class is wrong');
|
||||
}
|
||||
|
||||
/**
|
||||
* testLoadComponents method
|
||||
*
|
||||
|
@ -328,6 +340,8 @@ class ComponentTest extends CakeTestCase {
|
|||
* @return void
|
||||
*/
|
||||
function testLoadComponents() {
|
||||
$this->markTestSkipped('init() will be removed from Component');
|
||||
|
||||
$Controller =& new ComponentTestController();
|
||||
$Controller->components = array('RequestHandler');
|
||||
|
||||
|
@ -378,67 +392,27 @@ class ComponentTest extends CakeTestCase {
|
|||
* @return void
|
||||
*/
|
||||
function testNestedComponentLoading() {
|
||||
$Controller =& new ComponentTestController();
|
||||
$Controller->components = array('Apple');
|
||||
$Controller->uses = false;
|
||||
$Controller->constructClasses();
|
||||
$Controller->Component->initialize($Controller);
|
||||
$Collection = new ComponentCollection();
|
||||
$Apple = new AppleComponent($Collection);
|
||||
|
||||
$this->assertTrue(is_a($Controller->Apple, 'AppleComponent'));
|
||||
$this->assertTrue(is_a($Controller->Apple->Orange, 'OrangeComponent'));
|
||||
$this->assertTrue(is_a($Controller->Apple->Orange->Banana, 'BananaComponent'));
|
||||
$this->assertTrue(is_a($Controller->Apple->Orange->Controller, 'ComponentTestController'));
|
||||
$this->assertTrue(empty($Controller->Apple->Session));
|
||||
$this->assertTrue(empty($Controller->Apple->Orange->Session));
|
||||
$this->assertType('OrangeComponent', $Apple->Orange, 'class is wrong');
|
||||
$this->assertType('BananaComponent', $Apple->Orange->Banana, 'class is wrong');
|
||||
$this->assertTrue(empty($Apple->Session));
|
||||
$this->assertTrue(empty($Apple->Orange->Session));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests Component::startup() and only running callbacks for components directly attached to
|
||||
* the controller.
|
||||
* test that component components are not enabled in the collection.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function testComponentStartup() {
|
||||
$Controller =& new ComponentTestController();
|
||||
$Controller->components = array('Apple');
|
||||
$Controller->uses = false;
|
||||
$Controller->constructClasses();
|
||||
$Controller->Component->initialize($Controller);
|
||||
$Controller->beforeFilter();
|
||||
$Controller->Component->startup($Controller);
|
||||
function testInnerComponentsAreNotEnabled() {
|
||||
$Collection = new ComponentCollection();
|
||||
$Apple = $Collection->load('Apple');
|
||||
|
||||
$this->assertTrue(is_a($Controller->Apple, 'AppleComponent'));
|
||||
$this->assertEqual($Controller->Apple->testName, 'ComponentTest');
|
||||
|
||||
$expected = !(defined('APP_CONTROLLER_EXISTS') && APP_CONTROLLER_EXISTS);
|
||||
$this->assertEqual(isset($Controller->foo), $expected);
|
||||
$this->assertFalse(isset($Controller->bar));
|
||||
}
|
||||
|
||||
/**
|
||||
* test that triggerCallbacks fires methods on all the components, and can trigger any method.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function testTriggerCallback() {
|
||||
$mock = $this->getMock(
|
||||
'Object',
|
||||
array('startup', 'beforeFilter', 'beforeRender', 'other'),
|
||||
array(),
|
||||
'ComponentMockComponent'
|
||||
);
|
||||
$Controller =& new ComponentTestController();
|
||||
$Controller->components = array('ComponentMock');
|
||||
$Controller->uses = null;
|
||||
$Controller->constructClasses();
|
||||
|
||||
$Controller->ComponentMock->expects($this->once())->method('beforeRender');
|
||||
$Controller->ComponentMock->expects($this->never())->method('beforeFilter');
|
||||
|
||||
$Controller->Component->triggerCallback('beforeRender', $Controller);
|
||||
|
||||
$Controller->ComponentMock->enabled = false;
|
||||
$Controller->Component->triggerCallback('beforeFilter', $Controller);
|
||||
$this->assertType('OrangeComponent', $Apple->Orange, 'class is wrong');
|
||||
$result = $Collection->enabled();
|
||||
$this->assertEquals(array('Apple'), $result, 'Too many components enabled.');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -447,14 +421,14 @@ class ComponentTest extends CakeTestCase {
|
|||
* @return void
|
||||
*/
|
||||
function testMultipleComponentInitialize() {
|
||||
$Controller =& new ComponentTestController();
|
||||
$Controller->uses = false;
|
||||
$Controller->components = array('Orange', 'Banana');
|
||||
$Controller->constructClasses();
|
||||
$Controller->Component->initialize($Controller);
|
||||
|
||||
$this->assertEqual($Controller->Banana->testField, 'OrangeField');
|
||||
$this->assertEqual($Controller->Orange->Banana->testField, 'OrangeField');
|
||||
$Collection = new ComponentCollection();
|
||||
$Banana = $Collection->load('Banana');
|
||||
$Orange = $Collection->load('Orange');
|
||||
|
||||
$this->assertSame($Banana, $Orange->Banana, 'Should be references');
|
||||
$Banana->testField = 'OrangeField';
|
||||
|
||||
$this->assertSame($Banana->testField, $Orange->Banana->testField, 'References are broken');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -467,6 +441,7 @@ class ComponentTest extends CakeTestCase {
|
|||
if ($this->skipIf(defined('APP_CONTROLLER_EXISTS'), '%s Need a non-existent AppController')) {
|
||||
return;
|
||||
}
|
||||
$this->markTestSkipped('MergeVars test covers this.');
|
||||
|
||||
$Controller =& new ComponentTestController();
|
||||
$Controller->components = array('ParamTest' => array('test' => 'value', 'flag'), 'Apple');
|
||||
|
@ -505,6 +480,8 @@ class ComponentTest extends CakeTestCase {
|
|||
if ($this->skipIf(defined('APP_CONTROLLER_EXISTS'), '%s Need a non-existent AppController')) {
|
||||
return;
|
||||
}
|
||||
$this->markTestSkipped('MergeVars test covers this.');
|
||||
|
||||
$Controller =& new ComponentTestController();
|
||||
$Controller->components = array('Orange' => array('setting' => array('itemx')));
|
||||
$Controller->uses = false;
|
||||
|
@ -521,6 +498,8 @@ class ComponentTest extends CakeTestCase {
|
|||
* @return void
|
||||
*/
|
||||
function testMutuallyReferencingComponents() {
|
||||
$this->markTestSkipped('ComponentCollection handles this');
|
||||
|
||||
$Controller =& new ComponentTestController();
|
||||
$Controller->components = array('MutuallyReferencingOne');
|
||||
$Controller->uses = false;
|
||||
|
@ -547,6 +526,8 @@ class ComponentTest extends CakeTestCase {
|
|||
* @return void
|
||||
*/
|
||||
function testSomethingReferencingEmailComponent() {
|
||||
$this->markTestIncomplete('Will need to be updated');
|
||||
|
||||
$Controller =& new ComponentTestController();
|
||||
$Controller->components = array('SomethingWithEmail');
|
||||
$Controller->uses = false;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue