diff --git a/cake/libs/object_collection.php b/cake/libs/object_collection.php index 6f4ba875137..97ff33d7a51 100644 --- a/cake/libs/object_collection.php +++ b/cake/libs/object_collection.php @@ -151,4 +151,23 @@ public function attached($name = null) { return $this->_attached; } +/** + * Normalizes an object array, creates an array that makes lazy loading + * easier + * + * @param array $objects Array of child objects to normalize. + * @return array Array of normalized objects. + */ + public static function normalizeObjectArray($objects) { + $normal = array(); + foreach ($objects as $i => $objectName) { + $options = array(); + if (!is_int($i)) { + list($options, $objectName) = array($objectName, $i); + } + list($plugin, $name) = pluginSplit($objectName); + $normal[$name] = array('class' => $objectName, 'settings' => $options); + } + return $normal; + } } \ No newline at end of file diff --git a/cake/libs/view/helper.php b/cake/libs/view/helper.php index d6a23cd05be..2f1b7564a11 100644 --- a/cake/libs/view/helper.php +++ b/cake/libs/view/helper.php @@ -38,7 +38,14 @@ class Helper extends Object { * * @var array */ - public $helpers = null; + public $helpers = array(); + +/** + * A helper lookup table used to lazy load helper objects. + * + * @var array + */ + protected $_helperMap = array(); /** * Base URL @@ -143,11 +150,11 @@ class Helper extends Object { private $__cleaned = null; /** - * undocumented class variable + * The View instance this helper is attached to * - * @var string + * @var View */ - public $View; + protected $_View; /** * Default Constructor @@ -156,8 +163,11 @@ class Helper extends Object { * @param array $settings Configuration settings for the helper. */ public function __construct(View $View, $settings = array()) { - $this->View = $View; - // Nothing to see here. + $this->_View = $View; + $this->params = $View->params; + if (!empty($this->helpers)) { + $this->_helperMap = ObjectCollection::normalizeObjectArray($this->helpers); + } } /** @@ -174,8 +184,12 @@ public function __call($method, $params) { * @return void */ public function __get($name) { - if (!empty($this->helpers) && in_array($name, $this->helpers)) { - $this->{$name} = $this->View->Helpers->load($name, array(), false); + if (isset($this->_helperMap[$name]) && !isset($this->{$name})) { + $this->{$name} = $this->_View->loadHelper( + $this->_helperMap[$name]['class'], $this->_helperMap[$name]['settings'], false + ); + } + if (isset($this->{$name})) { return $this->{$name}; } } diff --git a/cake/libs/view/helpers/js.php b/cake/libs/view/helpers/js.php index eccc7bb9580..2ddeb00a7df 100644 --- a/cake/libs/view/helpers/js.php +++ b/cake/libs/view/helpers/js.php @@ -98,7 +98,7 @@ public function __construct(View $View, $settings = array()) { $this->__engineName = $className . 'Engine'; $engineClass = $engineName . 'Engine'; $this->helpers[] = $engineClass; - parent::__construct(); + parent::__construct($View, $settings); } /** diff --git a/cake/libs/view/helpers/paginator.php b/cake/libs/view/helpers/paginator.php index dce32e8da1b..88dd3289cd4 100644 --- a/cake/libs/view/helpers/paginator.php +++ b/cake/libs/view/helpers/paginator.php @@ -90,6 +90,7 @@ class PaginatorHelper extends AppHelper { * @return void */ function __construct(View $View, $settings = array()) { + parent::__construct($View, $settings); $ajaxProvider = isset($settings['ajax']) ? $settings['ajax'] : 'Js'; $this->helpers[] = $ajaxProvider; $this->_ajaxHelperClass = $ajaxProvider; diff --git a/cake/libs/view/helpers/xml.php b/cake/libs/view/helpers/xml.php index ccc21df4277..88e61bf0de7 100644 --- a/cake/libs/view/helpers/xml.php +++ b/cake/libs/view/helpers/xml.php @@ -44,7 +44,7 @@ class XmlHelper extends AppHelper { * @return void */ function __construct(View $View, $settings = array()) { - parent::__construct(); + parent::__construct($View, $settings); $this->Xml =& new Xml(); $this->Xml->options(array('verifyNs' => false)); } diff --git a/cake/libs/view/view.php b/cake/libs/view/view.php index 721d08b5fb3..7e1fe15684c 100644 --- a/cake/libs/view/view.php +++ b/cake/libs/view/view.php @@ -736,8 +736,8 @@ protected function _render($___viewFn, $___dataForView, $loadHelpers = true, $ca * @param array $settings Settings for the helper * @return Helper a constructed helper object. */ - public function loadHelper($helperName, $settings = array()) { - return $this->Helpers->load($helperName, $settings, true); + public function loadHelper($helperName, $settings = array(), $attach = true) { + return $this->Helpers->load($helperName, $settings, $attach); } /** diff --git a/cake/tests/cases/libs/view/helper.test.php b/cake/tests/cases/libs/view/helper.test.php index a52a3b27027..039be4965e2 100644 --- a/cake/tests/cases/libs/view/helper.test.php +++ b/cake/tests/cases/libs/view/helper.test.php @@ -163,6 +163,13 @@ function schema() { } class TestHelper extends Helper { +/** + * helpers for this helper. + * + * @var string + */ + var $helpers = array('Html', 'TestPlugin.OtherHelper'); + /** * expose a method as public * @@ -790,8 +797,12 @@ function testParseAttributeCompact() { * @return void */ function testLazyLoadingHelpers() { - $this->Helper->helpers = array('Test', 'Html'); - $result = $this->Helper->Test; - $this->assertType('TestHelper', $result); + App::build(array( + 'plugins' => array(TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'test_app' . DS . 'plugins' . DS), + )); + $Helper = new TestHelper($this->View); + $this->assertType('OtherHelperHelper', $Helper->OtherHelper); + $this->assertType('HtmlHelper', $Helper->Html); + App::build(); } } diff --git a/cake/tests/cases/libs/view/helper_collection.test.php b/cake/tests/cases/libs/view/helper_collection.test.php index 0b83a4b2c69..5df3c6e82a6 100644 --- a/cake/tests/cases/libs/view/helper_collection.test.php +++ b/cake/tests/cases/libs/view/helper_collection.test.php @@ -28,8 +28,8 @@ class HelperCollectionTest extends CakeTestCase { * @return void */ function setup() { - $View = $this->getMock('View', array(), array(null)); - $this->Helpers = new HelperCollection($View); + $this->View = $this->getMock('View', array(), array(null)); + $this->Helpers = new HelperCollection($this->View); } /** @@ -38,7 +38,7 @@ function setup() { * @return void */ function teardown() { - unset($this->Helpers); + unset($this->Helpers, $this->View); } /** @@ -124,8 +124,8 @@ function testTrigger() { $this->Helpers->load('Form'); $this->Helpers->load('Html'); - $this->Helpers->Html = $this->getMock('HtmlHelper'); - $this->Helpers->Form = $this->getMock('FormHelper'); + $this->Helpers->Html = $this->getMock('HtmlHelper', array(), array($this->View)); + $this->Helpers->Form = $this->getMock('FormHelper', array(), array($this->View)); $this->Helpers->Html->expects($this->once())->method('beforeRender') ->with('one', 'two'); @@ -144,8 +144,8 @@ function testTriggerWithDisabledHelpers() { $this->Helpers->load('Form'); $this->Helpers->load('Html'); - $this->Helpers->Html = $this->getMock('HtmlHelper'); - $this->Helpers->Form = $this->getMock('FormHelper'); + $this->Helpers->Html = $this->getMock('HtmlHelper', array(), array($this->View)); + $this->Helpers->Form = $this->getMock('FormHelper', array(), array($this->View)); $this->Helpers->Html->expects($this->once())->method('beforeRender') ->with('one', 'two'); @@ -155,4 +155,26 @@ function testTriggerWithDisabledHelpers() { $this->Helpers->trigger('beforeRender', array('one', 'two')); } + +/** + * test normalizeObjectArray + * + * @return void + */ + function testnormalizeObjectArray() { + $helpers = array( + 'Html', + 'Foo.Bar' => array('one', 'two'), + 'Something', + 'Banana.Apple' => array('foo' => 'bar') + ); + $result = ObjectCollection::normalizeObjectArray($helpers); + $expected = array( + 'Html' => array('class' => 'Html', 'settings' => array()), + 'Bar' => array('class' => 'Foo.Bar', 'settings' => array('one', 'two')), + 'Something' => array('class' => 'Something', 'settings' => array()), + 'Apple' => array('class' => 'Banana.Apple', 'settings' => array('foo' => 'bar')), + ); + $this->assertEquals($expected, $result); + } } \ No newline at end of file