An Automated tool for creating ACOs
As mentioned before, there is no pre-built way to input all of our controllers and actions into the Acl. However, we all hate doing repetitive things like typing in what could be hundreds of actions in a large application. I've whipped up an automated function to build my Aco table. This function will look at every controller in your application. It will add any non-private, non Controller methods to the Acl table, nicely nested underneath the the owning controller. You can add and run this in your AppController or any controller for that matter, just be sure to remove it before putting your application into production.
/*** Rebuild the Acl based on the current controllers in the application** @return void*/function buildAcl() {$log = array();$aco =& $this->Acl->Aco;$root = $aco->node('controllers');if (!$root) {$aco->create(array('parent_id' => null, 'model' => null, 'alias' => 'controllers'));$root = $aco->save();$root['Aco']['id'] = $aco->id;$log[] = 'Created Aco node for controllers';} else {$root = $root[0];}App::import('Core', 'File');$Controllers = Configure::listObjects('controller');$appIndex = array_search('App', $Controllers);if ($appIndex !== false ) {unset($Controllers[$appIndex]);}$baseMethods = get_class_methods('Controller');$baseMethods[] = 'buildAcl';// look at each controller in app/controllersforeach ($Controllers as $ctrlName) {App::import('Controller', $ctrlName);$ctrlclass = $ctrlName . 'Controller';$methods = get_class_methods($ctrlclass);// find / make controller node$controllerNode = $aco->node('controllers/'.$ctrlName);if (!$controllerNode) {$aco->create(array('parent_id' => $root['Aco']['id'], 'model' => null, 'alias' => $ctrlName));$controllerNode = $aco->save();$controllerNode['Aco']['id'] = $aco->id;$log[] = 'Created Aco node for '.$ctrlName;} else {$controllerNode = $controllerNode[0];}//clean the methods. to remove those in Controller and private actions.foreach ($methods as $k => $method) {if (strpos($method, '_', 0) === 0) {unset($methods[$k]);continue;}if (in_array($method, $baseMethods)) {unset($methods[$k]);continue;}$methodNode = $aco->node('controllers/'.$ctrlName.'/'.$method);if (!$methodNode) {$aco->create(array('parent_id' => $controllerNode['Aco']['id'], 'model' => null, 'alias' => $method));$methodNode = $aco->save();$log[] = 'Created Aco node for '. $method;}}}debug($log);}
You might want to keep this function around as it will add new ACO's for all of the controllers & actions that are in your application any time you run it. It does not remove nodes for actions that no longer exist though. Now that all the heavy lifting is done, we need to set up some permissions, and remove the code that disabled AuthComponent earlier.
Now, once you get this working, you may notice that you have trouble accessing any plugins that you may be using. The trick to automating the controller ACOs for plugins, is that the App::import needs to follow the plugin naming convention of PluginName.PluginControllerName.
So what we need is a function that will give us a list of plugin controller names, and import them in the same way we did in the code above for the regular controllers. The function below will do just that:
Простой текст/*** Get the names of the plugin controllers ...** This function will get an array of the plugin controller names, and* also makes sure the controllers are available for us to get the* method names by doing an App::import for each plugin controller.** @return array of plugin names.**/function _get_plugin_controller_names(){App::import('Core', 'File', 'Folder');$paths = Configure::getInstance();$folder =& new Folder();// Change directory to the plugins$folder->cd(APP.'plugins');// Get a list of the files that have a file name that ends// with controller.php$files = $folder->findRecursive('.*_controller\.php');// Get the list of plugins$Plugins = Configure::listObjects('plugin');// Loop through the controllers we found int the plugins directoryforeach($files as $f => $fileName){// Get the base file name$file = basename($fileName);// Get the controller name$file = Inflector::camelize(substr($file, 0, strlen($file)-strlen('_controller.php')));// Loop through the pluginsforeach($Plugins as $pluginName){if (preg_match('/^'.$pluginName.'/', $file)){// First get rid of the App controller for the plugin// We do this because the app controller is never called// directly ...if (preg_match('/^'.$pluginName.'App/', $file)){unset($files[$f]);} else {if (!App::import('Controller', $pluginName.'.'.$file)){debug('Error importing '.$file.' for plugin '.$pluginName);}/// Now prepend the Plugin name ...// This is required to allow us to fetch the method names.$files[$f] = $file;}break;}}}return $files;}
You can then either modify the original code to include the plugin controllers by merging them with the list you got (place this before the foreach loop):
Простой текст$Plugins = $this->_get_plugin_controller_names();$Controllers = array_merge($Controllers, $Plugins);


Коментарии:
Добавить коментарий