/** * Constructor * * @param string $id Module unique identifier * @param string $path Module location * @param ResourcesInterface $resourceMap Pointer to module resource map * @param SystemInterface $system */ public function __construct($id, $path, ResourcesInterface $resourceMap, SystemInterface $system) { // Inject generic module dependencies $this->system = $system; // Store pointer to module resource map // TODO: Should be changed or removed $this->resourceMap = $resourceMap = ResourceMap::get($path); // Save views list $this->views = $resourceMap->views; // Set default view context name $this->view_context = self::VD_POINTER_DEF; // Set up default view data pointer $this->data =& $this->view_data[$this->view_context]; // Set module identifier $this->id = $id; // Set path to module $this->path(realpath($path)); // Generate unique module identifier $this->uid = rand(0, 9999999) . '_' . microtime(true); // Add to module identifier to view data stack $this->data['id'] = $this->id; // Generate unique module cache path in local web-application $this->cache_path = __SAMSON_CWD__ . __SAMSON_CACHE_PATH . $this->id . '/'; // Save ONLY ONE copy of this instance in static instances collection, // avoiding rewriting by cloned modules !isset(self::$instances[$this->id]) ? self::$instances[$this->id] =& $this : ''; // Make view path relative to module - remove module path from view path $this->views = str_replace($this->path, '', $this->views); //elapsed('Registering module: '.$this->id.'('.$path.')' ); }
public function setUp() { $path = __DIR__; // Build resources map $map = ResourceMap::get($path); // Create core $core = new Core($map); // Create module $this->module = new TestingModule('test', $path, $map, $core); }
/** {@inheritdoc} */ public function getModule(string $moduleName) : Module { // Check if module exists if (!array_key_exists($moduleName, $this->composerModules)) { throw new \Exception(sprintf('Module with name "%s" not found', $moduleName)); } $composerModule = $this->composerModules[$moduleName]; $modulePath = $this->appPath . $this->vendorDir . $moduleName; // Convert resource map to module type $resourceMap = ResourceMap::get($modulePath); // Get all module classes $classes = []; foreach ($resourceMap->classData as $classData) { $classes[$classData['path']] = $classData['className']; if (array_key_exists('implements', $classData)) { foreach ($classData['implements'] as $interfaceName) { $this->implements[$interfaceName] = $classData['className']; } } if (array_key_exists('extends', $classData) && isset($classData['extends'][0])) { $this->extends[$classData['extends']] = $classData['className']; } } foreach ($this->implements as $interface => $class) { if (array_key_exists($class, $this->extends)) { $this->implements[$interface] = $this->extends[$class]; } } // Create new module $module = new Module($moduleName, $modulePath, $classes); $module->composerParameters = $composerModule; if (isset($resourceMap->module[0])) { $module->className = $resourceMap->module[0]; $module->pathName = $resourceMap->module[1]; } $module->isVirtualModule = !array_key_exists(0, $resourceMap->module) && array_key_exists(self::COMPRESSABLE_MODULE_ID, $composerModule) && (bool) $composerModule[self::COMPRESSABLE_MODULE_ID] === true; return $module; }
/** * Core constructor. * * @param ContainerBuilderInterface $builder Container builder * @param ResourceMap|null $map system resources * @InjectService(container="container") * InjectArgument(builder="samsonframework\container\ContainerBuilderInterface") * InjectArgument(builder="samsonframework\core\ResourceInterface") */ public function __construct(ContainerInterface $container, ContainerBuilderInterface $builder = null, ResourceMap $map = null) { $this->container = $container; $this->builder = $builder; // Get correct web-application path $this->system_path = __SAMSON_CWD__; // Get web-application resource map $this->map = ResourceMap::get($this->system_path, false, array('src/')); // Temporary add template worker $this->subscribe('core.rendered', array($this, 'generateTemplate')); // Fire core creation event Event::fire('core.created', array(&$this)); // Signal core configure event Event::signal('core.configure', array($this->system_path . __SAMSON_CONFIG_PATH)); }
/** * Load module from path to core. * * @param string $path Path for module loading * @param array $parameters Collection of loading parameters * * @return $this|bool */ public function load($path, $parameters = array()) { // Check path if (file_exists($path)) { /** @var ResourceMap $resourceMap Gather all resources from path */ $resourceMap = ResourceMap::get($path); if (isset($resourceMap->module[0])) { /** @var string $controllerPath Path to module controller file */ $controllerPath = $resourceMap->module[1]; /** @var string $moduleClass Name of module controller class to load */ $moduleClass = $resourceMap->module[0]; // Require module controller class into PHP if (file_exists($controllerPath)) { require_once $controllerPath; } // TODO: this should be done via composer autoload file field // Iterate all function-style controllers and require them foreach ($resourceMap->controllers as $controller) { require_once $controller; } /** @var ExternalModule $connector Create module controller instance */ $connector = new $moduleClass($path, $resourceMap, $this); // Set composer parameters $connector->composerParameters = $parameters; // Get module identifier $moduleID = $connector->id(); // Fire core module load event Event::fire('core.module_loaded', array($moduleID, &$connector)); // Signal core module configure event Event::signal('core.module.configure', array(&$connector, $moduleID)); // TODO: Think how to decouple this // Call module preparation handler if (!$connector->prepare()) { // Handle module failed preparing } // Trying to find parent class for connecting to it to use View/Controller inheritance $parentClass = get_parent_class($connector); if (!in_array($parentClass, array('samson\\core\\ExternalModule', 'samson\\core\\CompressableExternalModule'))) { // Переберем загруженные в систему модули foreach ($this->module_stack as &$m) { // Если в систему был загружен модуль с родительским классом if (get_class($m) == $parentClass) { $connector->parent =& $m; //elapsed('Parent connection for '.$moduleClass.'('.$connector->uid.') with '.$parent_class.'('.$m->uid.')'); } } } } elseif (is_array($parameters) && isset($parameters['samsonphp_package_compressable']) && $parameters['samsonphp_package_compressable'] == 1) { /** @var \samson\core\ExternalModule $connector Create module controller instance */ $connector = new VirtualModule($path, $resourceMap, $this, str_replace('/', '', $parameters['module_id'])); // Set composer parameters $connector->composerParameters = $parameters; } else { // Signal error return e('Cannot load module from: "##"', E_SAMSON_FATAL_ERROR, $path); } } else { return e('Cannot load module from[##]', E_SAMSON_FATAL_ERROR, $path); } // Chaining return $this; }
/** * Load modules * * @throws \Exception */ public function init() { $containerPath = __DIR__ . '/../../../../../www/cache'; $containerName = 'ContainerCore'; $containerNamespace = 'samsonphp\\core\\loader'; /** @var Module $module */ $modules = $this->moduleManager->getRegisteredModules(); $localModulesPath = '../src'; ResourceMap::get('cache'); $resourceMap = ResourceMap::get($localModulesPath); $localModules = $resourceMap->modules; if (false || !file_exists($containerPath . '/' . $containerName . '.php')) { $builder = new DefinitionBuilder(new ParameterBuilder()); $xmlResolver = new XmlResolver(); $xmlResolver->resolveFile($builder, __DIR__ . '/../../../../../app/config/config.xml'); new Service(''); new InjectService(''); new InjectClass(''); new InjectParameter(''); foreach ($modules as $module) { if ($module->className && !$builder->hasDefinition($module->className)) { // Fix samson.php files if (!class_exists($module->className)) { require_once $module->pathName; } /** @var ClassDefinition $classDefinition */ $classDefinition = $builder->addDefinition($module->className); if ($id = $this->getModuleId($module->pathName)) { $classDefinition->setServiceName($id); } else { // Generate identifier from module class $classDefinition->setServiceName(strtolower(ltrim(str_replace(__NS_SEPARATOR__, '_', $module->className), '_'))); } $classDefinition->addScope(new ModuleScope())->setIsSingleton(true); $this->defineConstructor($classDefinition, $module->path); } } $classDefinition = $builder->addDefinition(VirtualModule::class); $classDefinition->addScope(new ModuleScope())->setServiceName('local')->setIsSingleton(true); $this->defineConstructor($classDefinition, getcwd()); foreach ($localModules as $moduleFile) { if (!$builder->hasDefinition($moduleFile[0])) { /** @var ClassDefinition $classDefinition */ $classDefinition = $builder->addDefinition($moduleFile[0]); $classDefinition->addScope(new ModuleScope()); $classDefinition->setIsSingleton(true); if ($id = $this->getModuleId($moduleFile[1])) { $classDefinition->setServiceName($id); } else { throw new \Exception('Can not get id of local module'); } $modulePath = explode('/', str_replace(realpath($localModulesPath), '', $moduleFile[1])); $this->defineConstructor($classDefinition, $localModulesPath . '/' . $modulePath[1]); } } /** * Add implementors */ foreach ($this->moduleManager->implements as $interfaceName => $class) { $builder->defineImplementors($interfaceName, new ClassReference($class)); } // Init compiler $reader = new AnnotationReader(); $compiler = new DefinitionCompiler(new DefinitionGenerator(new ClassGenerator()), (new DefinitionAnalyzer())->addClassAnalyzer(new AnnotationClassAnalyzer($reader))->addClassAnalyzer(new ReflectionClassAnalyzer())->addMethodAnalyzer(new AnnotationMethodAnalyzer($reader))->addMethodAnalyzer(new ReflectionMethodAnalyzer())->addPropertyAnalyzer(new AnnotationPropertyAnalyzer($reader))->addPropertyAnalyzer(new ReflectionPropertyAnalyzer())->addParameterAnalyzer(new ReflectionParameterAnalyzer())); $container = $compiler->compile($builder, $containerName, $containerNamespace, $containerPath); } else { $containerClassName = $containerNamespace . '\\' . $containerName; require_once $containerPath . '/' . $containerName . '.php'; $container = new $containerClassName(); } $GLOBALS['__core'] = $container->get('core'); $this->prepareModules($modules, $container); /** @var array $module */ foreach ($localModules as $module) { $instance = $container->get($module[0]); $instance->parent = $this->getClassParentModule($container, get_parent_class($instance)); } // $container->get('core')->active($container->get('local')); return $container; }