An Automated tool for creating ACOs for CakePHP 2

There was a tool(code) for CakePHP 1.3 for creating ACOs automatically (https://book.cakephp.org/1.3/view/1549/An-Automated-tool-for-creating- ACOs). It didn’t work on 2.1 though. I made a few fixes so it seems to work fine (I haven’t tested it throughout and doubt that it’s bulletproof, but it did what I wanted it to do). Hope someone will find it useful.

function build_acl() {
    if (!Configure::read('debug')) {
        return $this->_stop();
    }
    $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::uses('File', 'Utility');
    $ControllersFresh = App::objects('Controller');

    foreach ($ControllersFresh as $cnt) {
        $Controllers[] = str_replace('Controller', '', $cnt);
    }
    $appIndex = array_search('App', $Controllers);
    if ($appIndex !== false) {
        unset($Controllers[$appIndex]);
    }
    $baseMethods = get_class_methods('Controller');
    $baseMethods[] = 'build_acl';

    $appcontr = get_class_methods('AppController');

    foreach ($appcontr as $appc) {
        $baseMethods[] = $appc;
    }

    $baseMethods = array_unique($baseMethods);

    $Plugins = $this->_getPluginControllerNames();
    $Controllers = array_merge($Controllers, $Plugins);

    // look at each controller in app/controllers
    foreach ($Controllers as $ctrlName) {
        $methods = $this->_getClassMethods($this->_getPluginControllerPath($ctrlName));

        // Do all Plugins First
        if ($this->_isPlugin($ctrlName)) {
            $pluginNode = $aco->node('controllers/' . $this->_getPluginName($ctrlName));
            if (!$pluginNode) {
                $aco->create(array('parent_id' => $root['Aco']['id'], 'model' => null, 'alias' => $this->_getPluginName($ctrlName)));
                $pluginNode = $aco->save();
                $pluginNode['Aco']['id'] = $aco->id;
                $log[] = 'Created Aco node for ' . $this->_getPluginName($ctrlName) . ' Plugin';
            }
        }
        // find / make controller node
        $controllerNode = $aco->node('controllers/' . $ctrlName);
        if (!$controllerNode) {
            if ($this->_isPlugin($ctrlName)) {
                $pluginNode = $aco->node('controllers/' . $this->_getPluginName($ctrlName));
                $aco->create(array('parent_id' => $pluginNode['0']['Aco']['id'], 'model' => null, 'alias' => $this->_getPluginControllerName($ctrlName)));
                $controllerNode = $aco->save();
                $controllerNode['Aco']['id'] = $aco->id;
                $log[] = 'Created Aco node for ' . $this->_getPluginControllerName($ctrlName) . ' ' . $this->_getPluginName($ctrlName) . ' Plugin Controller';
            } else {
                $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;
            }
        }
    }
    if (count($log) > 0) {
        debug($log);
    }

    exit;
}

function _getClassMethods($ctrlName = null) {
    if($this->_isPlugin($ctrlName)){
        App::uses($this->_getPluginControllerName ($ctrlName), $this->_getPluginName ($ctrlName). 'Controller');
    }
    else
        App::uses($ctrlName . 'Controller', 'Controller');


    if (strlen(strstr($ctrlName, '.')) > 0) {
        // plugin's controller
        $ctrlName = str_replace('Controller', '', $this->_getPluginControllerName ($ctrlName));
    }
    $ctrlclass = $ctrlName . 'Controller';
    $methods = get_class_methods($ctrlclass);

    // Add scaffold defaults if scaffolds are being used
    $properties = get_class_vars($ctrlclass);
    if (array_key_exists('scaffold', $properties)) {
        if ($properties['scaffold'] == 'admin') {
            $methods = array_merge($methods, array('admin_add', 'admin_edit', 'admin_index', 'admin_view', 'admin_delete'));
        } else {
            $methods = array_merge($methods, array('add', 'edit', 'index', 'view', 'delete'));
        }
    }
    return $methods;
}

function _isPlugin($ctrlName = null) {
    $arr = String::tokenize($ctrlName, '.');
    if (count($arr) > 1) {
        return true;
    } else {
        return false;
    }
}

function _getPluginControllerPath($ctrlName = null) {
    $arr = String::tokenize($ctrlName, '/');
    if (count($arr) == 2) {
        return $arr[0] . '.' . $arr[1];
    } else {
        return $arr[0];
    }
}

function _getPluginName($ctrlName = null) {
    $arr = String::tokenize($ctrlName, '.');
    if (count($arr) == 2) {
        return $arr[0];
    } else {
        return false;
    }
}

function _getPluginControllerName($ctrlName = null) {
    $arr = String::tokenize($ctrlName, '/');
    if (count($arr) == 2) {
        return $arr[1];
    } else {
        return false;
    }
}

/**
 * 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 _getPluginControllerNames() {
    App::uses('Folder', 'Utility');
    $folder = & new Folder();
    $folder->cd(APP . 'Plugin');

    // Get the list of plugins
    $Plugins = $folder->read();
    $Plugins = $Plugins[0];
    $arr = array();

    // Loop through the plugins
    foreach ($Plugins as $pluginName) {
        // Change directory to the plugin
        $didCD = $folder->cd(APP . 'Plugin' . DS . $pluginName . DS . 'Controller');
        if ($didCD) {
            // Get a list of the files that have a file name that ends
            // with controller.php
            $files = $folder->findRecursive('.*Controller\.php');

            // Loop through the controllers we found in the plugins directory
            foreach ($files as $fileName) {
                // Get the base file name
                $file = basename($fileName);

                // Get the controller name
                //$file = Inflector::camelize(substr($file, 0, strlen($file) - strlen('Controller.php')));
                if (!preg_match('/^' . Inflector::humanize($pluginName) . 'App/', $file)) {
                    $file = str_replace('.php', '', $file);

                    /// Now prepend the Plugin name ...
                    // This is required to allow us to fetch the method names.
                    $arr[] = Inflector::humanize($pluginName) . "." . $file;
                }

            }
        }
    }


    return $arr;

}