Подтвердить что ты не робот

Получите все модули, контроллеры и действия из приложения Zend Framework

Я хочу создать Zend Controller для управления ACL, поэтому моя проблема: как я могу получить все имена модулей, имена управления и имена Action в приложении Zend для создания ACL-элемента управления?

Я использую Zend_Navigation и если ресурс не существует в вашем ACL Zend_Navigation, это исключение. И я хочу использовать базу данных для отказа и доступа. Поэтому я должен сначала создать базу данных. И если я должен сделать это вручную, это больно для этого.

4b9b3361

Ответ 1

Я создал функцию, которая может получить все действия, контроллеры и модули из приложения zend. Вот он:

$module_dir = substr(str_replace("\\","/",$this->getFrontController()->getModuleDirectory()),0,strrpos(str_replace("\\","/",$this->getFrontController()->getModuleDirectory()),'/'));
    $temp = array_diff( scandir( $module_dir), Array( ".", "..", ".svn"));
    $modules = array();
    $controller_directorys = array();
    foreach ($temp as $module) {
        if (is_dir($module_dir . "/" . $module)) {
            array_push($modules,$module);
            array_push($controller_directorys, str_replace("\\","/",$this->getFrontController()->getControllerDirectory($module)));
        }
    }

    foreach ($controller_directorys as $dir) {
        foreach (scandir($dir) as $dirstructure) {
            if (is_file($dir  . "/" . $dirstructure)) {
                if (strstr($dirstructure,"Controller.php") != false) {
                    include_once($dir . "/" . $dirstructure);
                }
            }

        }
    }

    $default_module = $this->getFrontController()->getDefaultModule();

    $db_structure = array();

    foreach(get_declared_classes() as $c){
        if(is_subclass_of($c, 'Zend_Controller_Action')){
            $functions = array();
            foreach (get_class_methods($c) as $f) {
                if (strstr($f,"Action") != false) {
                    array_push($functions,substr($f,0,strpos($f,"Action")));
                }
            }
            $c = strtolower(substr($c,0,strpos($c,"Controller")));

            if (strstr($c,"_") != false) {
                $db_structure[substr($c,0,strpos($c,"_"))][substr($c,strpos($c,"_") + 1)] = $functions;
            }else{
                $db_structure[$default_module][$c] = $functions;
            }
        }
    }       
}

Ответ 2

Это может быть старый вопрос, но я так делаю это...

    $front = $this->getFrontController();
    $acl = array();

    foreach ($front->getControllerDirectory() as $module => $path) {

        foreach (scandir($path) as $file) {

            if (strstr($file, "Controller.php") !== false) {

                include_once $path . DIRECTORY_SEPARATOR . $file;

                foreach (get_declared_classes() as $class) {

                    if (is_subclass_of($class, 'Zend_Controller_Action')) {

                        $controller = strtolower(substr($class, 0, strpos($class, "Controller")));
                        $actions = array();

                        foreach (get_class_methods($class) as $action) {

                            if (strstr($action, "Action") !== false) {
                                $actions[] = $action;
                            }
                        }
                    }
                }

                $acl[$module][$controller] = $actions;
            }
        }
    }

Ответ 3

На самом деле я нашел лучший способ иметь легкодоступную ссылку на отражение, чтобы рекурсивно маркировать правильные каталоги, а затем создавать XML-документ в результате. Кэширование XML-документа для скорости и использование xpath для извлечения данных.

Плагин строит отражение xml и кэширует его позже. Я выбрал этот код из его первоначальной реализации, поэтому его больше, чтобы дать вам ощущение, а не копировать и вставлять.

Конечно, база данных работает так же хорошо. Но если вы пытаетесь ограничить свои запросы на странице, файл cached xml работает очень хорошо.

class My_Reflection_Plugin extends My_Controller_Plugin_Abstract
{
    public function routeShutdown(Zend_Controller_Request_Abstract $request)
    {
        $cache = $this -> getCacheManager() -> getCache('general');

        if (!$xml = $cache->load("Reflection"))
        {
            $paths = array(
                PATH_APPLICATION . "/Core",
                PATH_SITE . "/Project"
            );

            foreach ($paths as $path)
            {
                $this -> inspectDir($path);
            }

            $cache -> save($this->getReflectionXML(), "Reflection");
        }
        else
        {
            $this -> getReflectionXML($xml);
        }
    }

    private function inspectDir($path)
    {
        $rdi = new RecursiveDirectoryIterator($path);
        $rii = new RecursiveIteratorIterator($rdi);
        $filtered = new My_Reflection_Filter($rii);

        iterator_apply($filtered, array($this, 'process'), array($filtered));
    }

    private function process($it = false)
    {
        $this -> getReflectionXML() -> addItem($it -> current());

        return true;
    }
}

Токсификация происходит внутри фильтра:

class My_Reflection_Filter extends FilterIterator
{
    public function accept()
    {
        $file = $this->getInnerIterator()->current();

        // If we somehow have something other than an SplFileInfo object, just
        // return false
        if (!$file instanceof SplFileInfo) {
            return false;
        }

        // If we have a directory, it not a file, so return false
        if (!$file->isFile()) {
            return false;
        }

        // If not a PHP file, skip
        if ($file->getBasename('.php') == $file->getBasename()) {
            return false;
        }

        // Resource forks are no good either.
        if (substr($file->getBaseName(), 0, 2) == '._')
        {
            return false;
        }

        $contents = file_get_contents($file->getRealPath());
        $tokens   = token_get_all($contents);

        $file->className = NULL;
        $file->classExtends = NULL;
        $file->classImplements = array();

        $last = null;
        while (count($tokens) > 0)
        {
            $token = array_shift($tokens);

            if (!is_array($token))
            {
                continue;
            }

            list($id, $content, $line) = $token;

            switch ($id)
            {
                case T_ABSTRACT:
                case T_CLASS:
                case T_INTERFACE:
                        $last = 'object';
                    break;
                case T_EXTENDS:
                        $last = "extends";
                    break;
                case T_IMPLEMENTS:
                        $last = "implements";
                    break;
                case T_STRING:
                        switch ($last)
                        {
                            case "object":
                                    $file -> className = $content;
                                break;
                            case "extends":
                                    $file -> classExtends = $content;
                                break;
                            case "implements":
                                    $file -> classImplements[] = $content;
                                break;
                        }
                    break;
                case T_WHITESPACE:
                        // Do nothing, whitespace should be ignored but it shouldnt reset $last.
                    break;
                default:
                        // If its not directly following a keyword specified by $last, reset last to nothing.
                        $last = null;
                    break;
            }
        }

        return true;
    }
}

После того, как ваше отражение xml заполнено любой информацией, необходимой вам из класса, ваш плагин acl может последовать за ним и запросить эту информацию с помощью xpath.

Ответ 4

Я не думаю, что в Zend есть решение для этого. Вам придется сделать это самостоятельно...

Один из способов сделать это - перечислить все классы и проверить, расширяются ли классы (например) класс Zend_Controller_Action...

проверить функции php get_declared_classes и is_subclass_of

foreach(get_declared_classes() as $c){
  if(is_subclass_of($c, 'Zend_Controller_Action')){
     ...
  }
}