├── .gitignore
├── .travis.yml
├── Console
└── Command
│ └── AclExtrasShell.php
├── Lib
└── AclExtras.php
├── README.md
├── Test
├── Case
│ ├── AllTestsTest.php
│ └── Lib
│ │ └── AclExtrasTest.php
└── test_controllers.php
└── composer.json
/.gitignore:
--------------------------------------------------------------------------------
1 | tags
2 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 |
3 | php:
4 | - 5.4
5 | - 5.5
6 | - 5.6
7 | - 7.0
8 |
9 | env:
10 | - CAKE_VERSION=2.x
11 |
12 | install:
13 | - git clone git://github.com/cakephp/cakephp ../cakephp && cd ../cakephp && git checkout $CAKE_VERSION
14 | - cp -R ../acl_extras plugins/AclExtras
15 | - chmod -R 777 ../cakephp/app/tmp
16 | - sh -c "composer require 'phpunit/phpunit=3.7.33'"
17 | - sh -c "ln -s ./vendor/phpunit/phpunit/PHPUnit ../cakephp/vendors/PHPUnit"
18 |
19 | before_script:
20 | - sh -c "mysql -e 'CREATE DATABASE cakephp_test;'"
21 | - echo " 'Database/Mysql',
25 | 'database' => 'cakephp_test',
26 | 'host' => '0.0.0.0',
27 | 'login' => 'travis',
28 | 'persistent' => false,
29 | );
30 | }" > ../cakephp/app/Config/database.php
31 |
32 | script:
33 | - ./lib/Cake/Console/cake test AclExtras AllTests --stderr
34 |
35 | notifications:
36 | email: false
37 |
--------------------------------------------------------------------------------
/Console/Command/AclExtrasShell.php:
--------------------------------------------------------------------------------
1 |
13 | * @license http://www.opensource.org/licenses/mit-license.php The MIT License
14 | */
15 | App::uses('AppShell', 'Console/Command');
16 | App::uses('AclExtras', 'AclExtras.Lib');
17 |
18 | /**
19 | * Shell for ACO extras
20 | *
21 | * @package acl_extras
22 | * @subpackage acl_extras.Console.Command
23 | */
24 | class AclExtrasShell extends AppShell {
25 |
26 | /**
27 | * Contains arguments parsed from the command line.
28 | *
29 | * @var array
30 | * @access public
31 | */
32 | public $args;
33 |
34 | /**
35 | * AclExtras instance
36 | */
37 | public $AclExtras;
38 |
39 | /**
40 | * Constructor
41 | */
42 | public function __construct($stdout = null, $stderr = null, $stdin = null) {
43 | parent::__construct($stdout, $stderr, $stdin);
44 | $this->AclExtras = new AclExtras();
45 | }
46 |
47 | /**
48 | * Start up And load Acl Component / Aco model
49 | *
50 | * @return void
51 | **/
52 | public function startup() {
53 | parent::startup();
54 | $this->AclExtras->startup();
55 | $this->AclExtras->Shell = $this;
56 | }
57 |
58 | /**
59 | * Sync the ACO table
60 | *
61 | * @return void
62 | **/
63 | public function aco_sync() {
64 | $this->AclExtras->aco_sync($this->params);
65 | }
66 |
67 | /**
68 | * Updates the Aco Tree with new controller actions.
69 | *
70 | * @return void
71 | **/
72 | public function aco_update() {
73 | $this->AclExtras->aco_update($this->params);
74 | return true;
75 | }
76 |
77 | public function getOptionParser() {
78 | $plugin = array(
79 | 'short' => 'p',
80 | 'help' => __('Plugin to process'),
81 | );
82 | return parent::getOptionParser()
83 | ->description(__("Better manage, and easily synchronize you application's ACO tree"))
84 | ->addSubcommand('aco_update', array(
85 | 'parser' => array(
86 | 'options' => compact('plugin'),
87 | ),
88 | 'help' => __('Add new ACOs for new controllers and actions. Does not remove nodes from the ACO table.')
89 | ))->addSubcommand('aco_sync', array(
90 | 'parser' => array(
91 | 'options' => compact('plugin'),
92 | ),
93 | 'help' => __('Perform a full sync on the ACO table.' .
94 | 'Will create new ACOs or missing controllers and actions.' .
95 | 'Will also remove orphaned entries that no longer have a matching controller/action')
96 | ))->addSubcommand('verify', array(
97 | 'help' => __('Verify the tree structure of either your Aco or Aro Trees'),
98 | 'parser' => array(
99 | 'arguments' => array(
100 | 'type' => array(
101 | 'required' => true,
102 | 'help' => __('The type of tree to verify'),
103 | 'choices' => array('aco', 'aro')
104 | )
105 | )
106 | )
107 | ))->addSubcommand('recover', array(
108 | 'help' => __('Recover a corrupted Tree'),
109 | 'parser' => array(
110 | 'arguments' => array(
111 | 'type' => array(
112 | 'required' => true,
113 | 'help' => __('The type of tree to recover'),
114 | 'choices' => array('aco', 'aro')
115 | )
116 | )
117 | )
118 | ));
119 | }
120 |
121 | /**
122 | * Verify a Acl Tree
123 | *
124 | * @param string $type The type of Acl Node to verify
125 | * @access public
126 | * @return void
127 | */
128 | public function verify() {
129 | $this->AclExtras->args = $this->args;
130 | return $this->AclExtras->verify();
131 | }
132 | /**
133 | * Recover an Acl Tree
134 | *
135 | * @param string $type The Type of Acl Node to recover
136 | * @access public
137 | * @return void
138 | */
139 | public function recover() {
140 | $this->AclExtras->args = $this->args;
141 | $this->AclExtras->recover();
142 | }
143 | }
144 |
--------------------------------------------------------------------------------
/Lib/AclExtras.php:
--------------------------------------------------------------------------------
1 |
11 | * @license http://www.opensource.org/licenses/mit-license.php The MIT License
12 | */
13 |
14 | App::uses('Controller', 'Controller');
15 | App::uses('ComponentCollection', 'Controller');
16 | App::uses('AclComponent', 'Controller/Component');
17 | App::uses('DbAcl', 'Model');
18 | App::uses('Shell', 'Console');
19 | App::uses('CakeObject', 'Core');
20 |
21 | /**
22 | * Shell for ACO extras
23 | *
24 | * @package acl_extras
25 | * @subpackage acl_extras.Console.Command
26 | */
27 | class AclExtras extends CakeObject {
28 |
29 | /**
30 | * Contains instance of AclComponent
31 | *
32 | * @var AclComponent
33 | * @access public
34 | */
35 | public $Acl;
36 |
37 | /**
38 | * Contains arguments parsed from the command line.
39 | *
40 | * @var array
41 | * @access public
42 | */
43 | public $args;
44 |
45 | /**
46 | * Contains database source to use
47 | *
48 | * @var string
49 | * @access public
50 | */
51 | public $dataSource = 'default';
52 |
53 | /**
54 | * Root node name.
55 | *
56 | * @var string
57 | **/
58 | public $rootNode = 'controllers';
59 |
60 | /**
61 | * Internal Clean Actions switch
62 | *
63 | * @var boolean
64 | **/
65 | protected $_clean = false;
66 |
67 | /**
68 | * Start up And load Acl Component / Aco model
69 | *
70 | * @return void
71 | **/
72 | public function startup($controller = null) {
73 | if (!$controller) {
74 | $controller = new Controller(new CakeRequest());
75 | }
76 | $collection = new ComponentCollection();
77 | $this->Acl = new AclComponent($collection);
78 | $this->Acl->startup($controller);
79 | $this->Aco = $this->Acl->Aco;
80 | $this->controller = $controller;
81 | }
82 |
83 | public function out($msg) {
84 | if (!empty($this->controller->Session)) {
85 | $this->controller->Flash->set($msg);
86 | } else {
87 | return $this->Shell->out($msg);
88 | }
89 | }
90 |
91 | public function err($msg) {
92 | if (!empty($this->controller->Session)) {
93 | $this->controller->Flash->set($msg);;
94 | } else {
95 | return $this->Shell->err($msg);
96 | }
97 | }
98 |
99 | /**
100 | * Sync the ACO table
101 | *
102 | * @return void
103 | **/
104 | public function aco_sync($params = array()) {
105 | $this->_clean = true;
106 | $this->aco_update($params);
107 | }
108 |
109 | /**
110 | * Updates the Aco Tree with new controller actions.
111 | *
112 | * @return void
113 | **/
114 | public function aco_update($params = array()) {
115 | $root = $this->_checkNode($this->rootNode, $this->rootNode, null);
116 |
117 | if (empty($params['plugin'])) {
118 | $controllers = $this->getControllerList();
119 | $this->_updateControllers($root, $controllers);
120 | $plugins = CakePlugin::loaded();
121 | } else {
122 | $plugin = $params['plugin'];
123 | if (!in_array($plugin, App::objects('plugin')) || !CakePlugin::loaded($plugin)) {
124 | $this->err(__('Plugin %s not found or not activated', $plugin));
125 | return false;
126 | }
127 | $plugins = array($params['plugin']);
128 | }
129 |
130 | foreach ($plugins as $plugin) {
131 | $controllers = $this->getControllerList($plugin);
132 |
133 | $path = $this->rootNode . '/' . $plugin;
134 | $pluginRoot = $this->_checkNode($path, $plugin, $root['Aco']['id']);
135 | $this->_updateControllers($pluginRoot, $controllers, $plugin);
136 | }
137 | $this->out(__('Aco Update Complete'));
138 | return true;
139 | }
140 |
141 | /**
142 | * Updates a collection of controllers.
143 | *
144 | * @param array $root Array or ACO information for root node.
145 | * @param array $controllers Array of Controllers
146 | * @param string $plugin Name of the plugin you are making controllers for.
147 | * @return void
148 | */
149 | protected function _updateControllers($root, $controllers, $plugin = null) {
150 | $dotPlugin = $pluginPath = $plugin;
151 | if ($plugin) {
152 | $dotPlugin .= '.';
153 | $pluginPath .= '/';
154 | }
155 | $appIndex = array_search($plugin . 'AppController', $controllers);
156 | if ($appIndex !== false) {
157 | App::uses($plugin . 'AppController', $dotPlugin . 'Controller');
158 | unset($controllers[$appIndex]);
159 | }
160 | // look at each controller
161 | foreach ($controllers as $controller) {
162 | App::uses($controller, $dotPlugin . 'Controller');
163 | $controllerName = preg_replace('/Controller$/', '', $controller);
164 |
165 | $path = $this->rootNode . '/' . $pluginPath . $controllerName;
166 | $controllerNode = $this->_checkNode($path, $controllerName, $root['Aco']['id']);
167 | $this->_checkMethods($controller, $controllerName, $controllerNode, $pluginPath);
168 | }
169 | if ($this->_clean) {
170 | if (!$plugin) {
171 | $controllers = array_merge($controllers, App::objects('plugin', null, false));
172 | }
173 | $controllerFlip = array_flip($controllers);
174 |
175 | $this->Aco->id = $root['Aco']['id'];
176 | $controllerNodes = $this->Aco->children(null, true);
177 | foreach ($controllerNodes as $ctrlNode) {
178 | $alias = $ctrlNode['Aco']['alias'];
179 | $name = $alias . 'Controller';
180 | if (!isset($controllerFlip[$name]) && !isset($controllerFlip[$alias])) {
181 | if ($this->Aco->delete($ctrlNode['Aco']['id'])) {
182 | $this->out(__(
183 | 'Deleted %s and all children',
184 | $this->rootNode . '/' . $ctrlNode['Aco']['alias']
185 | ), 1, Shell::VERBOSE);
186 | }
187 | }
188 | }
189 | }
190 | }
191 |
192 | /**
193 | * Get a list of controllers in the app and plugins.
194 | *
195 | * Returns an array of path => import notation.
196 | *
197 | * @param string $plugin Name of plugin to get controllers for
198 | * @return array
199 | **/
200 | public function getControllerList($plugin = null) {
201 | if (!$plugin) {
202 | $controllers = App::objects('Controller', null, false);
203 | } else {
204 | $controllers = App::objects($plugin . '.Controller', null, false);
205 | }
206 | return $controllers;
207 | }
208 |
209 | /**
210 | * Check a node for existance, create it if it doesn't exist.
211 | *
212 | * @param string $path
213 | * @param string $alias
214 | * @param int $parentId
215 | * @return array Aco Node array
216 | */
217 | protected function _checkNode($path, $alias, $parentId = null) {
218 | $node = $this->Aco->node($path);
219 | if (!$node) {
220 | $this->Aco->create(array('parent_id' => $parentId, 'model' => null, 'alias' => $alias));
221 | $node = $this->Aco->save();
222 | $node['Aco']['id'] = $this->Aco->id;
223 | $this->out(__('Created Aco node: %s', $path), 1, Shell::VERBOSE);
224 | } else {
225 | $node = $node[0];
226 | }
227 | return $node;
228 | }
229 |
230 | /**
231 | * Get a list of registered callback methods
232 | */
233 | protected function _getCallbacks($className) {
234 | $callbacks = array();
235 | $reflection = new ReflectionClass($className);
236 | if ($reflection->isAbstract()) {
237 | return $callbacks;
238 | }
239 | try {
240 | $method = $reflection->getMethod('implementedEvents');
241 | } catch (ReflectionException $e) {
242 | return $callbacks;
243 | }
244 | if (version_compare(phpversion(), '5.4', '>=')) {
245 | $object = $reflection->newInstanceWithoutConstructor();
246 | } else {
247 | $object = unserialize(
248 | sprintf('O:%d:"%s":0:{}', strlen($className), $className)
249 | );
250 | }
251 | $implementedEvents = $method->invoke($object);
252 | foreach ($implementedEvents as $event => $callable) {
253 | if (is_string($callable)) {
254 | $callbacks[] = $callable;
255 | }
256 | if (is_array($callable) && isset($callable['callable'])) {
257 | $callbacks[] = $callable['callable'];
258 | }
259 | }
260 | return $callbacks;
261 | }
262 |
263 | /**
264 | * Check and Add/delete controller Methods
265 | *
266 | * @param string $controller
267 | * @param array $node
268 | * @param string $plugin Name of plugin
269 | * @return void
270 | */
271 | protected function _checkMethods($className, $controllerName, $node, $pluginPath = false) {
272 | $excludes = $this->_getCallbacks($className);
273 | $baseMethods = get_class_methods('Controller');
274 | $actions = get_class_methods($className);
275 | if ($actions == null) {
276 | $this->err(__('Unable to get methods for "%s"', $className));
277 | return false;
278 | }
279 | $methods = array_diff($actions, $baseMethods);
280 | $methods = array_diff($methods, $excludes);
281 | foreach ($methods as $action) {
282 | if (strpos($action, '_', 0) === 0) {
283 | continue;
284 | }
285 | $path = $this->rootNode . '/' . $pluginPath . $controllerName . '/' . $action;
286 | $this->_checkNode($path, $action, $node['Aco']['id']);
287 | }
288 |
289 | if ($this->_clean) {
290 | $actionNodes = $this->Aco->children($node['Aco']['id']);
291 | $methodFlip = array_flip($methods);
292 | foreach ($actionNodes as $action) {
293 | if (!isset($methodFlip[$action['Aco']['alias']])) {
294 | $this->Aco->id = $action['Aco']['id'];
295 | if ($this->Aco->delete()) {
296 | $path = $this->rootNode . '/' . $controllerName . '/' . $action['Aco']['alias'];
297 | $this->out(__('Deleted Aco node: %s', $path), 1, Shell::VERBOSE);
298 | }
299 | }
300 | }
301 | }
302 | return true;
303 | }
304 |
305 | /**
306 | * Verify a Acl Tree
307 | *
308 | * @param string $type The type of Acl Node to verify
309 | * @access public
310 | * @return void
311 | */
312 | public function verify() {
313 | $type = Inflector::camelize($this->args[0]);
314 | $return = $this->Acl->{$type}->verify();
315 | if ($return === true) {
316 | $this->out(__('Tree is valid and strong'));
317 | } else {
318 | $this->err(print_r($return, true));
319 | return false;
320 | }
321 | }
322 |
323 | /**
324 | * Recover an Acl Tree
325 | *
326 | * @param string $type The Type of Acl Node to recover
327 | * @access public
328 | * @return void
329 | */
330 | public function recover() {
331 | $type = Inflector::camelize($this->args[0]);
332 | $return = $this->Acl->{$type}->recover();
333 | if ($return === true) {
334 | $this->out(__('Tree has been recovered, or tree did not need recovery.'));
335 | } else {
336 | $this->err(__('Tree recovery failed.'));
337 | return false;
338 | }
339 | }
340 |
341 | }
342 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Acl Extras
2 |
3 | Acl Extras provides a console app that helps you manage DbAcl records more easily. Its main feature and purpose is to make generating Aco nodes for all your controllers and actions easier. It also includes some helper methods for verifying and recovering corrupted trees.
4 |
5 | ## Installation
6 |
7 | Clone the repo or download a tarball and install it into `app/Plugin/AclExtras` or in any of your pluginPaths.
8 |
9 | Then activate the plugin in your app/Config/bootstrap.php file as shown below:
10 |
11 | CakePlugin::load('AclExtras');
12 |
13 | ## Usage
14 |
15 | You can find a list of commands by running `Console/cake AclExtras.AclExtras -h` from your command line.
16 |
17 | ### Setting up the contorller
18 |
19 | You'll need to configure AuthComponent to use the Actions authorization method.
20 | In your `beforeFilter` add the following:
21 |
22 | $this->Auth->authorize = 'actions';
23 | $this->Auth->actionPath = 'controllers/';
24 |
25 | ## Issues
26 |
27 | If you find an issue in the code or want to suggest something, please use the tickets at http://github.com/markstory/acl_extras/issues
28 |
29 | ## License
30 |
31 | Acl Extras is licensed under the MIT license.
32 |
--------------------------------------------------------------------------------
/Test/Case/AllTestsTest.php:
--------------------------------------------------------------------------------
1 | addTestDirectoryRecursive(App::pluginPath('AclExtras') . 'Test' . DS . 'Case' . DS);
15 |
16 | return $suite;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Test/Case/Lib/AclExtrasTest.php:
--------------------------------------------------------------------------------
1 |
17 | * @license http://www.opensource.org/licenses/mit-license.php The MIT License
18 | */
19 | App::uses('Shell', 'Console');
20 | App::uses('Aco', 'Model');
21 | App::uses('AclComponent', 'Controller/Component');
22 | App::uses('Controller', 'Controller');
23 | App::uses('AclExtras', 'AclExtras.Lib');
24 |
25 |
26 | //Mock::generate('Aco', 'MockAco', array('children', 'verify', 'recover'));
27 |
28 | //import test controller class names.
29 | include dirname(dirname(dirname(__FILE__))) . DS . 'test_controllers.php';
30 |
31 | /**
32 | * AclExtras Shell Test case
33 | *
34 | * @package acl_extras.tests.cases
35 | */
36 | class AclExtrasShellTestCase extends CakeTestCase {
37 |
38 | public $fixtures = array('core.aco', 'core.aro', 'core.aros_aco');
39 |
40 | /**
41 | * startTest
42 | *
43 | * @return void
44 | * @access public
45 | */
46 | public function setUp() {
47 | parent::setUp();
48 | Configure::write('Acl.classname', 'DbAcl');
49 | Configure::write('Acl.database', 'test');
50 |
51 | $this->Task = $this->getMock(
52 | 'AclExtras',
53 | array('in', 'out', 'hr', 'createFile', 'error', 'err', 'clear', 'getControllerList')
54 | );
55 | }
56 |
57 | /**
58 | * end the test
59 | *
60 | * @return void
61 | **/
62 | public function tearDown() {
63 | parent::tearDown();
64 | unset($this->Task);
65 | }
66 |
67 | /**
68 | * test recover
69 | *
70 | * @return void
71 | **/
72 | public function testRecover() {
73 | $this->Task->startup();
74 | $this->Task->args = array('Aco');
75 | $this->Task->Acl->Aco = $this->getMock('Aco', array('recover'));
76 | $this->Task->Acl->Aco->expects($this->once())
77 | ->method('recover')
78 | ->will($this->returnValue(true));
79 |
80 | $this->Task->expects($this->once())
81 | ->method('out')
82 | ->with($this->matchesRegularExpression('/recovered/'));
83 |
84 | $this->Task->recover();
85 | }
86 |
87 | /**
88 | * test verify
89 | *
90 | * @return void
91 | **/
92 | public function testVerify() {
93 | $this->Task->startup();
94 | $this->Task->args = array('Aco');
95 | $this->Task->Acl->Aco = $this->getMock('Aco', array('verify'));
96 | $this->Task->Acl->Aco->expects($this->once())
97 | ->method('verify')
98 | ->will($this->returnValue(true));
99 |
100 | $this->Task->expects($this->once())
101 | ->method('out')
102 | ->with($this->matchesRegularExpression('/valid/'));
103 |
104 | $this->Task->verify();
105 | }
106 |
107 | /**
108 | * test startup
109 | *
110 | * @return void
111 | **/
112 | public function testStartup() {
113 | $this->assertEqual($this->Task->Acl, null);
114 | $this->Task->startup();
115 | $this->assertInstanceOf('AclComponent', $this->Task->Acl);
116 | }
117 |
118 | /**
119 | * clean fixtures and setup mock
120 | *
121 | * @return void
122 | **/
123 | protected function _cleanAndSetup() {
124 | $tableName = $this->db->fullTableName('acos');
125 | $this->db->execute('DELETE FROM ' . $tableName);
126 | $this->Task->expects($this->any())
127 | ->method('getControllerList')
128 | ->will($this->returnValue(array('CommentsController', 'PostsController', 'BigLongNamesController')));
129 |
130 | $this->Task->startup();
131 | }
132 | /**
133 | * Test aco_update method.
134 | *
135 | * @return void
136 | **/
137 | public function testAcoUpdate() {
138 | $this->_cleanAndSetup();
139 | $this->Task->aco_update();
140 |
141 | $Aco = $this->Task->Acl->Aco;
142 |
143 | $result = $Aco->node('controllers/Comments');
144 | $this->assertEqual($result[0]['Aco']['alias'], 'Comments');
145 |
146 | $result = $Aco->children($result[0]['Aco']['id']);
147 | $this->assertEqual(count($result), 3);
148 | $this->assertEqual($result[0]['Aco']['alias'], 'add');
149 | $this->assertEqual($result[1]['Aco']['alias'], 'index');
150 | $this->assertEqual($result[2]['Aco']['alias'], 'delete');
151 |
152 | $result = $Aco->node('controllers/Posts');
153 | $this->assertEqual($result[0]['Aco']['alias'], 'Posts');
154 | $result = $Aco->children($result[0]['Aco']['id']);
155 | $this->assertEqual(count($result), 3);
156 |
157 | $result = $Aco->node('controllers/BigLongNames');
158 | $this->assertEqual($result[0]['Aco']['alias'], 'BigLongNames');
159 | $result = $Aco->children($result[0]['Aco']['id']);
160 | $this->assertEqual(count($result), 4);
161 | }
162 |
163 | /**
164 | * test syncing of Aco records
165 | *
166 | * @return void
167 | **/
168 | public function testAcoSyncRemoveMethods() {
169 | $this->_cleanAndSetup();
170 | $this->Task->aco_update();
171 |
172 | $Aco = $this->Task->Acl->Aco;
173 | $Aco->cacheQueries = false;
174 |
175 | $result = $Aco->node('controllers/Comments');
176 | $new = array(
177 | 'parent_id' => $result[0]['Aco']['id'],
178 | 'alias' => 'some_method'
179 | );
180 | $Aco->create($new);
181 | $Aco->save();
182 | $children = $Aco->children($result[0]['Aco']['id']);
183 | $this->assertEqual(count($children), 4);
184 |
185 | $this->Task->aco_sync();
186 | $children = $Aco->children($result[0]['Aco']['id']);
187 | $this->assertEqual(count($children), 3);
188 |
189 | $method = $Aco->node('controllers/Commments/some_method');
190 | $this->assertFalse($method);
191 | }
192 |
193 | /**
194 | * test adding methods with aco_update
195 | *
196 | * @return void
197 | **/
198 | public function testAcoUpdateAddingMethods() {
199 | $this->_cleanAndSetup();
200 | $this->Task->aco_update();
201 |
202 | $Aco = $this->Task->Acl->Aco;
203 | $Aco->cacheQueries = false;
204 |
205 | $result = $Aco->node('controllers/Comments');
206 | $children = $Aco->children($result[0]['Aco']['id']);
207 | $this->assertEqual(count($children), 3);
208 |
209 | $Aco->delete($children[0]['Aco']['id']);
210 | $Aco->delete($children[1]['Aco']['id']);
211 | $this->Task->aco_update();
212 |
213 | $children = $Aco->children($result[0]['Aco']['id']);
214 | $this->assertEqual(count($children), 3);
215 | }
216 |
217 | /**
218 | * test adding controllers on sync
219 | *
220 | * @return void
221 | **/
222 | public function testAddingControllers() {
223 | $this->_cleanAndSetup();
224 | $this->Task->aco_update();
225 |
226 | $Aco = $this->Task->Acl->Aco;
227 | $Aco->cacheQueries = false;
228 |
229 | $result = $Aco->node('controllers/Comments');
230 | $Aco->delete($result[0]['Aco']['id']);
231 |
232 | $this->Task->aco_update();
233 | $newResult = $Aco->node('controllers/Comments');
234 | $this->assertNotEqual($newResult[0]['Aco']['id'], $result[0]['Aco']['id']);
235 | }
236 | }
237 |
--------------------------------------------------------------------------------
/Test/test_controllers.php:
--------------------------------------------------------------------------------
1 | =5.2.17",
21 | "cakephp/cakephp": ">=2.4 <3.0",
22 | "composer/installers": "*"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------