From f1f586480c620939c6bba9a5bb2da572392bd5dc Mon Sep 17 00:00:00 2001 From: Ceeram Date: Sun, 27 Feb 2011 16:08:52 +0100 Subject: [PATCH] Implementing Aclbehavior to be set as both requester as controlled, tests updated, fixes #346 --- cake/libs/model/behaviors/acl.php | 82 ++++++++++++------- .../cases/libs/model/behaviors/acl.test.php | 69 +++++++++++++--- 2 files changed, 110 insertions(+), 41 deletions(-) diff --git a/cake/libs/model/behaviors/acl.php b/cake/libs/model/behaviors/acl.php index 63b85a6f0..08f66acce 100644 --- a/cake/libs/model/behaviors/acl.php +++ b/cake/libs/model/behaviors/acl.php @@ -35,7 +35,7 @@ class AclBehavior extends ModelBehavior { * @var array * @access protected */ - var $__typeMaps = array('requester' => 'Aro', 'controlled' => 'Aco'); + var $__typeMaps = array('requester' => 'Aro', 'controlled' => 'Aco', 'both' => array('Aro', 'Aco')); /** * Sets up the configuation for the model, and loads ACL models if they haven't been already @@ -48,17 +48,22 @@ class AclBehavior extends ModelBehavior { if (is_string($config)) { $config = array('type' => $config); } - $this->settings[$model->name] = array_merge(array('type' => 'requester'), (array)$config); - $this->settings[$model->name]['type'] = strtolower($this->settings[$model->name]['type']); + $this->settings[$model->alias] = array_merge(array('type' => 'controlled'), (array)$config); + $this->settings[$model->alias]['type'] = strtolower($this->settings[$model->alias]['type']); - $type = $this->__typeMaps[$this->settings[$model->name]['type']]; + $types = $this->__typeMaps[$this->settings[$model->alias]['type']]; if (!class_exists('AclNode')) { require LIBS . 'model' . DS . 'db_acl.php'; } - if (PHP5) { - $model->{$type} = ClassRegistry::init($type); - } else { - $model->{$type} =& ClassRegistry::init($type); + if (!is_array($types)) { + $types = array($types); + } + foreach($types as $type) { + if (PHP5) { + $model->{$type} = ClassRegistry::init($type); + } else { + $model->{$type} =& ClassRegistry::init($type); + } } if (!method_exists($model, 'parentNode')) { trigger_error(sprintf(__('Callback parentNode() not defined in %s', true), $model->alias), E_USER_WARNING); @@ -69,14 +74,21 @@ class AclBehavior extends ModelBehavior { * Retrieves the Aro/Aco node for this model * * @param mixed $ref + * @param string $type Only needed when Acl is set up as 'both', specify 'Aro' or 'Aco' to get the correct node * @return array * @access public * @link http://book.cakephp.org/view/1322/node */ - function node(&$model, $ref = null) { - $type = $this->__typeMaps[$this->settings[$model->name]['type']]; + function node(&$model, $ref = null, $type = null) { + if (empty($type)) { + $type = $this->__typeMaps[$this->settings[$model->alias]['type']]; + if (is_array($type)) { + trigger_error(__('AclBehavior is setup with more then one type, please specify type parameter for node()', true), E_USER_WARNING); + return null; + } + } if (empty($ref)) { - $ref = array('model' => $model->name, 'foreign_key' => $model->id); + $ref = array('model' => $model->alias, 'foreign_key' => $model->id); } return $model->{$type}->node($ref); } @@ -89,22 +101,27 @@ class AclBehavior extends ModelBehavior { * @access public */ function afterSave(&$model, $created) { - $type = $this->__typeMaps[$this->settings[$model->name]['type']]; - $parent = $model->parentNode(); - if (!empty($parent)) { - $parent = $this->node($model, $parent); + $types = $this->__typeMaps[$this->settings[$model->alias]['type']]; + if (!is_array($types)) { + $types = array($types); } - $data = array( - 'parent_id' => isset($parent[0][$type]['id']) ? $parent[0][$type]['id'] : null, - 'model' => $model->alias, - 'foreign_key' => $model->id - ); - if (!$created) { - $node = $this->node($model); - $data['id'] = isset($node[0][$type]['id']) ? $node[0][$type]['id'] : null; + foreach ($types as $type) { + $parent = $model->parentNode(); + if (!empty($parent)) { + $parent = $this->node($model, $parent, $type); + } + $data = array( + 'parent_id' => isset($parent[0][$type]['id']) ? $parent[0][$type]['id'] : null, + 'model' => $model->alias, + 'foreign_key' => $model->id + ); + if (!$created) { + $node = $this->node($model, null, $type); + $data['id'] = isset($node[0][$type]['id']) ? $node[0][$type]['id'] : null; + } + $model->{$type}->create(); + $model->{$type}->save($data); } - $model->{$type}->create(); - $model->{$type}->save($data); } /** @@ -114,10 +131,15 @@ class AclBehavior extends ModelBehavior { * @access public */ function afterDelete(&$model) { - $type = $this->__typeMaps[$this->settings[$model->name]['type']]; - $node = Set::extract($this->node($model), "0.{$type}.id"); - if (!empty($node)) { - $model->{$type}->delete($node); + $types = $this->__typeMaps[$this->settings[$model->alias]['type']]; + if (!is_array($types)) { + $types = array($types); + } + foreach ($types as $type) { + $node = Set::extract($this->node($model, null, $type), "0.{$type}.id"); + if (!empty($node)) { + $model->{$type}->delete($node); + } } } -} +} \ No newline at end of file diff --git a/cake/tests/cases/libs/model/behaviors/acl.test.php b/cake/tests/cases/libs/model/behaviors/acl.test.php index a2469b051..8f42e577c 100644 --- a/cake/tests/cases/libs/model/behaviors/acl.test.php +++ b/cake/tests/cases/libs/model/behaviors/acl.test.php @@ -52,7 +52,7 @@ class AclPerson extends CakeTestModel { * @var array * @access public */ - var $actsAs = array('Acl' => 'requester'); + var $actsAs = array('Acl' => 'both'); /** * belongsTo property @@ -133,7 +133,7 @@ class AclUser extends CakeTestModel { * @var array * @access public */ - var $actsAs = array('Acl'); + var $actsAs = array('Acl' => 'requester'); /** * parentNode @@ -261,6 +261,20 @@ class AclBehaviorTestCase extends CakeTestCase { $this->assertTrue(is_object($Post->Aco)); } +/** + * Test Setup of AclBehavior as both requester and controlled + * + * @return void + * @access public + */ + function testSetupMulti() { + $User =& new AclPerson(); + $this->assertTrue(isset($User->Behaviors->Acl->settings['AclPerson'])); + $this->assertEqual($User->Behaviors->Acl->settings['AclPerson']['type'], 'both'); + $this->assertTrue(is_object($User->Aro)); + $this->assertTrue(is_object($User->Aco)); + } + /** * test After Save * @@ -294,6 +308,15 @@ class AclBehaviorTestCase extends CakeTestCase { ); $this->Aro->save($aroData); + $acoData = array( + 'Aco' => array( + 'model' => 'AclPerson', + 'foreign_key' => 2, + 'parent_id' => null + ) + ); + $this->Aco->save($acoData); + $Person =& new AclPerson(); $data = array( 'AclPerson' => array( @@ -309,7 +332,7 @@ class AclBehaviorTestCase extends CakeTestCase { $this->assertTrue(is_array($result)); $this->assertEqual($result['Aro']['parent_id'], 5); - $node = $Person->node(array('model' => 'AclPerson', 'foreign_key' => 8)); + $node = $Person->node(array('model' => 'AclPerson', 'foreign_key' => 8), 'Aro'); $this->assertEqual(count($node), 2); $this->assertEqual($node[0]['Aro']['parent_id'], 5); $this->assertEqual($node[1]['Aro']['parent_id'], null); @@ -323,17 +346,24 @@ class AclBehaviorTestCase extends CakeTestCase { ); $this->Aro->create(); $this->Aro->save($aroData); - + $acoData = array( + 'Aco' => array( + 'model' => 'AclPerson', + 'foreign_key' => 1, + 'parent_id' => null + )); + $this->Aco->create(); + $this->Aco->save($acoData); $Person->read(null, 8); $Person->set('mother_id', 1); $Person->save(); $result = $this->Aro->find('first', array( 'conditions' => array('Aro.model' => 'AclPerson', 'Aro.foreign_key' => $Person->id) )); - $this->assertTrue(is_array($result)); - $this->assertEqual($result['Aro']['parent_id'], 7); - - $node = $Person->node(array('model' => 'AclPerson', 'foreign_key' => 8)); + $this->assertTrue(is_array($result)); + $this->assertEqual($result['Aro']['parent_id'], 7); + + $node = $Person->node(array('model' => 'AclPerson', 'foreign_key' => 8), 'Aro'); $this->assertEqual(sizeof($node), 2); $this->assertEqual($node[0]['Aro']['parent_id'], 7); $this->assertEqual($node[1]['Aro']['parent_id'], null); @@ -354,6 +384,15 @@ class AclBehaviorTestCase extends CakeTestCase { ); $this->Aro->save($aroData); + $acoData = array( + 'Aco' => array( + 'model' => 'AclPerson', + 'foreign_key' => 2, + 'parent_id' => null + ) + ); + $this->Aco->save($acoData); + $Person =& new AclPerson(); $data = array( 'AclPerson' => array( @@ -391,6 +430,14 @@ class AclBehaviorTestCase extends CakeTestCase { ) ); $this->Aro->save($aroData); + $acoData = array( + 'Aco' => array( + 'model' => 'AclPerson', + 'foreign_key' => 2, + 'parent_id' => null + ) + ); + $this->Aco->save($acoData); $Person =& new AclPerson(); $data = array( 'AclPerson' => array( @@ -401,7 +448,7 @@ class AclBehaviorTestCase extends CakeTestCase { ); $Person->save($data); $id = $Person->id; - $node = $Person->node(); + $node = $Person->node(null, 'Aro'); $this->assertEqual(count($node), 2); $this->assertEqual($node[0]['Aro']['parent_id'], 5); $this->assertEqual($node[1]['Aro']['parent_id'], null); @@ -455,8 +502,8 @@ class AclBehaviorTestCase extends CakeTestCase { $this->Aro->save($aroData); $Person->id = 2; - $result = $Person->node(); + $result = $Person->node(null, 'Aro'); $this->assertTrue(is_array($result)); $this->assertEqual(count($result), 1); } -} +} \ No newline at end of file