/**
* Scan for resources/actions
*
* @return void
*/
private function scan()
{
$cacheService = \Zend_Registry::get('container')->getService('newscoop.cache');
$options = $this->getOptions() + array('cache_ttl' => 300);
$cacheKey = $cacheService->getCacheKey(self::CACHE_NAMESPACE);
if ($cacheService->contains($cacheKey)) {
list($this->resources, $this->access) = json_decode($cacheService->fetch($cacheKey), TRUE);
return;
}
$resources = $access = array();
// load resources from file if any
$file = APPLICATION_PATH . '/configs/resources.ini';
if (file_exists($file)) {
$config = new Zend_Config_Ini($file);
$resources = $config->toArray();
}
// load dynamic resources from storage
foreach ($this->storage->getResources() as $resource => $actions) {
if (!isset($resources[$resource])) {
$resources[$resource] = array();
}
$resources[$resource] += $actions;
}
$reader = $this->getAnnotationReader();
// get modules to scan
$front = Zend_Controller_Front::getInstance();
$paths = $front->getControllerDirectory();
$modules = !empty($options['modules']) ? $options['modules'] : array();
foreach ($modules as $module) {
$path = $paths[$module];
foreach (glob("{$path}/*Controller.php") as $controllerFile) {
require_once $controllerFile;
$controller = ucfirst($module) . '_' . current(explode('.', basename($controllerFile)));
$reflection = new ReflectionClass($controller);
$resource = $this->formatName($controller, $module);
$defaultAction = NULL;
$controllerKey = $resource;
$access[$controllerKey] = array();
// process annotations
$annotation = $reader->getClassAnnotation($reflection, self::ANNOTATION);
if ($annotation !== NULL) {
if (!empty($annotation->ignore)) {
// ignored class
continue;
}
if (!empty($annotation->resource)) {
$resource = $this->formatName($annotation->resource);
}
if (!empty($annotation->action)) {
$defaultAction = $this->formatName($annotation->action);
}
}
// get actions
$actions = array();
foreach ($reflection->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
if (!preg_match('/Action$/', $method->getName())) {
continue;
}
$action = $this->formatName($method->getName());
$target = $resource;
$methodKey = $action;
$access[$controllerKey][$methodKey] = array(null, null);
// process annotations
$annotation = $reader->getMethodAnnotation($method, self::ANNOTATION);
if ($annotation !== NULL) {
if (!empty($annotation->ignore)) {
continue;
}
if (!empty($annotation->resource)) {
$target = $this->formatName($annotation->resource);
}
if (!empty($annotation->action)) {
$action = $this->formatName($annotation->action);
}
} elseif ($defaultAction !== NULL) {
$action = $defaultAction;
}
// add action to target resource
if (!isset($resources[$target])) {
$resources[$target] = array($action);
} elseif (!in_array($action, $resources[$target])) {
$resources[$target][] = $action;
}
if ($target) {
$access[$controllerKey][$methodKey] = array($target, $action);
}
}
}
}
// TODO: remove this dirty hack - replace this with registering custom Acl annotation in symfony controllers.
$resources['playlist'] = array('manage');
$resources['ingest'] = array('manage');
$this->resources = $resources;
$this->access = $access;
$cacheService->save($cacheKey, json_encode(array($resources, $access)), (int) $options['cache_ttl']);
}