diff --git a/cake/libs/controller/components/acl.php b/cake/libs/controller/components/acl.php index c41d4d8e400..2516ff6d3ab 100644 --- a/cake/libs/controller/components/acl.php +++ b/cake/libs/controller/components/acl.php @@ -44,19 +44,46 @@ class AclComponent extends Object { /** * Constructor. Will return an instance of the correct ACL class as defined in `Configure::read('Acl.classname')` * + * @throws Exception when Acl.classname could not be loaded. */ - function __construct() { + public function __construct() { $name = Inflector::camelize(strtolower(Configure::read('Acl.classname'))); if (!class_exists($name)) { if (App::import('Component', $name)) { list($plugin, $name) = pluginSplit($name); $name .= 'Component'; } else { - trigger_error(sprintf(__('Could not find %s.'), $name), E_USER_WARNING); + throw new Exception(sprintf(__('Could not find %s.'), $name)); + } + } + $this->adapter($name); + } + +/** + * Sets or gets the Adapter object currently in the AclComponent. + * + * `$this->Acl->adapter();` will get the current adapter class while + * `$this->Acl->adapter($obj);` will set the adapter class + * + * Will call the initialize method on the adapter if setting a new one. + * + * @param mixed $adapter Instance of AclBase or a string name of the class to use. (optional) + * @return mixed either null, or instance of AclBase + * @throws Exception when the given class is not an AclBase + */ + public function adapter($adapter = null) { + if ($adapter) { + if (is_string($adapter)) { + $adapter = new $adapter(); + } + if (!$adapter instanceof AclBase) { + throw new Exception(__('AclComponent adapters must extend AclBase')); } + $this->_Instance = $adapter; + $this->_Instance->initialize($this); + return; } - $this->_Instance =& new $name(); - $this->_Instance->initialize($this); + return $this->_Instance; } /** @@ -161,18 +188,7 @@ public function revoke($aro, $aco, $action = "*") { * @subpackage cake.cake.libs.controller.components * @abstract */ -class AclBase extends Object { - -/** - * This class should never be instantiated, just subclassed. - * - */ - function __construct() { - if (strcasecmp(get_class($this), "AclBase") == 0 || !is_subclass_of($this, "AclBase")) { - trigger_error(__("[acl_base] The AclBase class constructor has been called, or the class was instantiated. This class must remain abstract. Please refer to the Cake docs for ACL configuration."), E_USER_ERROR); - return NULL; - } - } +abstract class AclBase extends Object { /** * Empty method to be overridden in subclasses @@ -181,16 +197,14 @@ function __construct() { * @param string $aco ACO The controlled object identifier. * @param string $action Action (defaults to *) */ - public function check($aro, $aco, $action = "*") { - } + public abstract function check($aro, $aco, $action = "*"); /** * Empty method to be overridden in subclasses * * @param object $component Component */ - public function initialize(&$component) { - } + public abstract function initialize($component); } /** @@ -234,7 +248,7 @@ function __construct() { * @param AclComponent $component * @return void */ - public function initialize(&$component) { + public function initialize($component) { $component->Aro =& $this->Aro; $component->Aco =& $this->Aco; } @@ -494,10 +508,13 @@ class IniAcl extends AclBase { public $config = null; /** - * The constructor must be overridden, as AclBase is abstract. + * Initialize method * + * @param AclBase $component + * @return void */ - function __construct() { + public function initialize($component) { + } /** diff --git a/cake/tests/cases/libs/controller/components/acl.test.php b/cake/tests/cases/libs/controller/components/acl.test.php index af36e340aa1..e26ed7a50af 100644 --- a/cake/tests/cases/libs/controller/components/acl.test.php +++ b/cake/tests/cases/libs/controller/components/acl.test.php @@ -17,9 +17,6 @@ * @since CakePHP(tm) v 1.2.0.5435 * @license http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License */ -if (!defined('CAKEPHP_UNIT_TEST_EXECUTION')) { - define('CAKEPHP_UNIT_TEST_EXECUTION', 1); -} App::import(array('controller' .DS . 'components' . DS . 'acl', 'model' . DS . 'db_acl')); /** @@ -184,15 +181,6 @@ function __construct() { } } -/** - * IniAclTest class - * - * @package cake - * @subpackage cake.tests.cases.libs.controller.components - */ -class IniAclTest extends IniAcl { -} - /** * Short description for class. * @@ -242,6 +230,41 @@ function tearDown() { unset($this->Acl); } +/** + * test that construtor throws an exception when Acl.classname is a + * non-existant class + * + * @return void + */ + function testConstrutorException() { + $this->expectException(); + Configure::write('Acl.classname', 'AclClassNameThatDoesNotExist'); + $acl = new AclComponent(); + } + +/** + * test that adapter() allows control of the interal implementation AclComponent uses. + * + * @return void + */ + function testAdapter() { + $implementation = new IniAcl(); + $this->assertNull($this->Acl->adapter($implementation)); + + $this->assertEqual($this->Acl->adapter(), $implementation, 'Returned object is different %s'); + } + +/** + * test that adapter() whines when the class is not an AclBase + * + * @return void + */ + function testAdapterException() { + $this->expectException(); + $thing = new StdClass(); + $this->Acl->adapter($thing); + } + /** * testAclCreate method * @@ -513,11 +536,9 @@ function testStartup() { * @return void */ function testIniReadConfigFile() { - Configure::write('Acl.classname', 'IniAclTest'); - unset($this->Acl); - $this->Acl = new AclComponent(); + $Ini = new IniAcl(); $iniFile = TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'test_app' . DS . 'config'. DS . 'acl.ini.php'; - $result = $this->Acl->_Instance->readConfigFile($iniFile); + $result = $Ini->readConfigFile($iniFile); $expected = array( 'admin' => array( 'groups' => 'administrators', @@ -562,12 +583,11 @@ function testIniReadConfigFile() { * @return void */ function testIniCheck() { - Configure::write('Acl.classname', 'IniAclTest'); - unset($this->Acl); $iniFile = TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'test_app' . DS . 'config'. DS . 'acl.ini.php'; - $this->Acl = new AclComponent(); - $this->Acl->_Instance->config= $this->Acl->_Instance->readConfigFile($iniFile); + $Ini = new IniAcl(); + $Ini->config = $Ini->readConfigFile($iniFile); + $this->Acl->adapter($Ini); $this->assertFalse($this->Acl->check('admin', 'ads')); $this->assertTrue($this->Acl->check('admin', 'posts'));