Zend Framework uygulamadan tüm modülleri, kontrolörler ve eylemleri alın

4 Cevap php

Nasıl bir ACL denetim oluşturmak için Zend uygulama tüm Modülü isimleri, Kontrol isimleri ve Eylem adları alabilirsiniz:? Yüzden benim problem ACL yönetimi için bir Zend denetleyicisi oluşturmak istiyorum

Ben Zend_Navigation kullanımı ve kaynak ACL Zend_Navigation var yoksa bir istisna atılır. Ve ben erişimini engellemek ve izin vermek için bir veritabanı kullanmak istiyorum. Bu yüzden ilk veritabanını oluşturmak gerekir. Ve eğer ben elle bunu yapmak için bir ağrı olduğunu yapmalıyız.

4 Cevap

Ben bir zend uygulamadan tüm eylemleri, kontrolörleri ve modülleri alabilirsiniz fonksiyonu oluşturduk. İşte:

$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;
			}
		}
    }    	
}

Bu eski bir soru olabilir ama bu ben bu yapıyorum nasıl ...

    $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;
			}
		}
	}

Ben aslında kolay ulaşılabilir bir yansıması referans ardışık doğru dizinleri tokenise ve ardından sonuç olarak bir xml belgesini inşa edildi için en iyi yolu bulundu. Hız için xml belgeyi önbelleğe alma ve veri almak için XPath kullanarak.

Eklentisi yansıma xml oluşturur ve sonrası için önbelleğe alır. Ben orijinal uygulanmasından bu kodu aldım, bu yüzden onun daha bir fikir vermek yerine kopyalama ve yapıştırma.

Tabii ki, bir veritabanı burada sadece iyi çalışır. Sayfa başı sorguları sınırlamak için çalışıyorsanız Ama, önbelleğe alınmış bir xml doc oldukça iyi çalışıyor.

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;
    }
}

Tokenisation filtrenin içinde olur:

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's 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;
    }
}

Eğer yansıma xml sınıfın dışında ihtiyacınız ne olursa olsun bilgi ile doldurulur var sonra, acl eklenti bundan sonra gelen ve XPath ile bu bilgileri sorgulayabilirsiniz.

Ben Zend bunun için bir çözüm olduğunu düşünmüyorum. Bunu kendiniz yapmak zorunda olacak ...

Bunu yapmanın tek yolu, bütün sınıfları listesi ve sınıfları (örneğin) Zend_Controller_Action sınıfını genişletmek olmadığını kontrol etmektir ...

php fonksiyonları kontrol get_declared_classes ve is_subclass_of

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