/** * @param $source Reflection_Source the PHP source file object * @param $compiler PHP\Compiler the main compiler * @return boolean true if compilation process did something, else false */ public function compile(Reflection_Source $source, PHP\Compiler $compiler = null) { $compiled = false; foreach ($source->getClasses() as $class) { // replace extends with the built replacement class if (!Builder::isBuilt($class->name)) { $parent_class_name = $class->getParentName(); if ($parent_class_name) { $replacement_class_name = Builder::className($parent_class_name); if ($replacement_class_name != $parent_class_name) { $class_exists = class_exists($replacement_class_name, false); if ($class_exists && is_a($replacement_class_name, $parent_class_name) || !$class_exists && Reflection_Source::of($replacement_class_name)->getClass($replacement_class_name)->isA($class->name)) { $replacement_class_name = $parent_class_name; } } if (is_array($replacement_class_name)) { trigger_error("Replacement classes should all be compiled", E_USER_ERROR); $compiler->addSource($source); } elseif ($replacement_class_name !== $parent_class_name && Builder::isBuilt($replacement_class_name)) { $extended = null; $buffer = $source->getSource(); $short_class_name = Namespaces::shortClassName($class->name); $buffer = preg_replace_callback('%(\\s+class\\s+' . $short_class_name . '\\s+extends\\s+)([\\\\\\w]+)(\\s+)%', function ($match) use(&$extended, $replacement_class_name) { $extended = $match[2]; return $match[1] . BS . $replacement_class_name . $match[3]; }, $buffer); if ($extended) { $buffer = preg_replace_callback('%(\\n\\s+\\*\\s+@link\\s+)(' . str_replace(BS, BS . BS, $extended) . ')(\\s+)%', function ($match) use($replacement_class_name) { return $match[1] . BS . $replacement_class_name . $match[3]; }, $buffer); } $source->setSource($buffer); $compiled = true; } } } } return $compiled; }
/** * @param $sources Reflection_Source[] * @return Reflection_Source[] added sources list */ public function moreSourcesToCompile(&$sources) { $added = []; // search into dependencies : used classes /** @var $search Dependency */ $search = Search_Object::create(Dependency::class); $search->type = Dependency::T_USE; foreach ($sources as $source) { foreach ($source->getClasses() as $class) { if ($class->type === T_TRAIT) { $search->dependency_name = $class->name; foreach (Dao::search($search, Dependency::class) as $dependency) { while ($dependency && Builder::isBuilt($dependency->class_name)) { $search_built_parent = Search_Object::create(Dependency::class); $search_built_parent->class_name = $dependency->class_name; $search_built_parent->type = Dependency::T_EXTENDS; $dependency = Dao::searchOne($search_built_parent); if (!$dependency) { trigger_error('Not parent class for built class ' . $search_built_parent->class_name, E_USER_ERROR); } $search_built_parent->class_name = $dependency->dependency_name; $search_built_parent->type = Dependency::T_DECLARATION; $dependency = Dao::searchOne($search_built_parent); if (!$dependency) { trigger_error('Not declaration dependency for class ' . $search_built_parent->class_name, E_USER_ERROR); } } /** @var $dependency Dependency */ if (!isset($sources[$dependency->file_name])) { $source = new Reflection_Source($dependency->file_name); $sources[$dependency->file_name] = $source; $added[$dependency->file_name] = $source; } } } } } // search into dependencies : registered methods foreach ($sources as $source) { $search->file_name = $source->file_name; $search->dependency_name = Registerable::class; $search->type = Dependency::T_IMPLEMENTS; if (Dao::searchOne($search, Dependency::class)) { unset($search->dependency_name); $search->type = Dependency::T_CLASS; foreach (Dao::search($search, Dependency::class) as $dependency) { $source = Reflection_Source::of($dependency->dependency_name); if (!isset($sources[$source->file_name])) { $sources[$source->file_name] = $source; $added[$source->file_name] = $source; } } } } // classes that are already into $sources $already = []; foreach ($sources as $source) { foreach ($source->getClasses() as $class) { $already[$class->name] = true; } } // search into advices and add sources that have sources to compile as advice foreach ($this->weaver->getJoinpoints() as $class_name => $joinpoint) { if (!isset($already[$class_name])) { foreach ($joinpoint as $advices) { foreach ($advices as $advice) { if (is_array($advice = $advice[1])) { $advice_class = $advice[0]; if (is_object($advice_class)) { $advice_class = get_class($advice_class); } if (isset($already[$advice_class])) { $source = Reflection_Source::of($class_name); /* if ($source->file_name && !$source->isInternal() && !is_file($source->file_name)) { $applicant_source = Reflection_Source::of($advice_class); if ( !$source->searchFile($class_name, array_keys($applicant_source->getRequires())) ) { trigger_error( 'Reflection_Source file not found for class ' . $class_name, E_USER_ERROR ); } } */ if ($source->getClass($class_name)) { $sources[$source->file_name] = $source; $added[$source->file_name] = $source; $already[$class_name] = true; } else { trigger_error('No class ' . $class_name . ' into file ' . $source->file_name, E_USER_ERROR); } } } } } } } return $added; }
/** * @param $class_name string * @return Reflection_Class */ public static function of($class_name) { return Reflection_Source::of($class_name)->getClass($class_name); }