/** * 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']); }