in realtà ho trovato il modo migliore per avere un riferimento riflessione facilmente disponibile era quello di come risultato ricorsivamente le directory corrette e quindi creare un documento xml. Memorizzazione nella cache del documento xml per la velocità e utilizzo di xpath per il recupero dei dati.
Il plug-in crea il riflesso xml e lo memorizza nella cache per dopo. Ho preso questo codice fuori dalla sua implementazione originale, quindi è più per darti un'idea piuttosto che copiare e incollare.
Ovviamente, un database funziona altrettanto bene qui. Ma se stai cercando di limitare le tue query per pagina, un documento XML memorizzato nella cache funziona piuttosto bene.
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;
}
}
tokenizzazione accade all'interno del filtro:
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;
}
}
Una volta che avete la vostra xml riflessione popolato con qualsiasi informazioni di cui avete bisogno fuori della classe, il vostro plugin ACL può venire dopo di esso e richiedere che le informazioni con XPath .
Perché è necessario avere TUTTE le azioni e i nomi dei controller? Basti pensare a una whitelist: è possibile accedere solo alle azioni o ai controller che si trovano in un gruppo speciale. Tutti gli altri non lo sono. – powtac
Avresti dovuto fare una risposta, dato che sei corretto. Una lista bianca è davvero il modo migliore per procedere con l'ACL basato su controller/azioni –
C'è un solo problema se si utilizza Zend_Navigation e la risorsa non esiste nella LCA in cui viene generata un'eccezione. E voglio usare un database per negare e consentire l'accesso. Quindi devo prima creare il database. E se devo farlo a mano è doloroso farlo. –