*/ class Factory { /** * * @param string $extensionId * @return ControllerDescription[] array of controller descriptions */ public function getControllers($extensionId) { $ext = \common_ext_ExtensionsManager::singleton()->getExtensionById($extensionId); $controllers = []; foreach ($this->getControllerClasses($ext) as $className) { $controllers[] = $this->getControllerDescription($className); } return $controllers; } /** * Get a description of the controller * * @param string $controllerClassName * @return ControllerDescription */ public function getControllerDescription($controllerClassName) { $reflector = new ReflectionClass($controllerClassName); return new ControllerDescription($reflector); } /** * Get a description of the action * * @param string $controllerClassName * @param string $actionName * @return ActionDescription * @throws ActionNotFoundException */ public function getActionDescription($controllerClassName, $actionName) { if (!class_exists($controllerClassName) || !method_exists($controllerClassName, $actionName)) { throw new ActionNotFoundException('Unknown ' . $controllerClassName . '@' . $actionName); } $reflector = new \ReflectionMethod($controllerClassName, $actionName); return new ActionDescription($reflector); } /** * Helper to find all controllers * * @param \common_ext_Extension $extension * @return array * @ignore */ private function getControllerClasses(\common_ext_Extension $extension) { $returnValue = []; // routes $namespaces = []; foreach ($extension->getManifest()->getRoutes() as $mapedPath => $ns) { if (is_string($ns)) { $namespaces[] = trim($ns, '\\'); } } if (!empty($namespaces)) { common_Logger::t('Namespace found in routes for extension ' . $extension->getId()); $classes = []; $recDir = new RecursiveDirectoryIterator($extension->getDir()); $recIt = new RecursiveIteratorIterator($recDir); $regexIt = new RegexIterator($recIt, '/^.+\.php$/i', RecursiveRegexIterator::GET_MATCH); foreach ($regexIt as $entry) { $info = helpers_PhpTools::getClassInfo($entry[0]); if (!empty($info['ns'])) { $ns = trim($info['ns'], '\\'); if (!empty($info['ns']) && in_array($ns, $namespaces)) { $returnValue[$info['class']] = $ns . '\\' . $info['class']; } } } } // legacy if ($extension->hasConstant('DIR_ACTIONS') && file_exists($extension->getConstant('DIR_ACTIONS'))) { $dir = new DirectoryIterator($extension->getConstant('DIR_ACTIONS')); foreach ($dir as $fileinfo) { if (preg_match('/^class\.[^.]*\.php$/', $fileinfo->getFilename())) { $module = substr($fileinfo->getFilename(), 6, -4); $returnValue[$module] = $extension->getId() . '_actions_' . $module; } } } $returnValue = array_filter($returnValue, [$this, 'isControllerClassNameValid']); return (array) $returnValue; } /** * Validates controller class name to: * - exist * - have valid base class * - be not abstract * * @param string $controllerClassName * * @return bool */ private function isControllerClassNameValid($controllerClassName) { $returnValue = true; if (!class_exists($controllerClassName)) { common_Logger::w($controllerClassName . ' not found'); $returnValue = false; } elseif (!is_subclass_of($controllerClassName, 'Module') && !is_subclass_of($controllerClassName, Controller::class)) { common_Logger::w($controllerClassName . ' is not a valid Controller.'); $returnValue = false; } else { // abstract so just move along $reflection = new \ReflectionClass($controllerClassName); if ($reflection->isAbstract()) { common_Logger::i($controllerClassName . ' is abstract'); $returnValue = false; } } return $returnValue; } }