/** * When a class is compiled, all classes that extends it must be compiled too * * @param &$sources Reflection_Source[] * @return Reflection_Source[] added sources list */ public function moreSourcesToCompile(&$sources) { $added = []; // we will search all extends dependencies /** @var $dependency Dependency */ $dependency_search = Search_Object::create(Dependency::class); $dependency_search->type = Dependency::T_EXTENDS; foreach ($sources as $source) { foreach ($source->getClasses() as $class) { if (!Builder::isBuilt($class->name)) { // add all classes that extend source classes $dependency_search->dependency_name = $class->name; foreach (Dao::search($dependency_search) as $dependency) { if (!isset($sources[$dependency->file_name]) && !Builder::isBuilt($dependency->class_name)) { $added[$dependency->file_name] = new Reflection_Source($dependency->file_name); } } } } } return $added; }
/** * Includes the php file that contains the given class (must contain namespace) * * @param $class_name string class name (with or without namespace) * @return boolean */ public function autoload($class_name) { if ($i = strrpos($class_name, '\\')) { $namespace = strtolower(str_replace('\\', '/', substr($class_name, 0, $i))); $file_name = substr($class_name, $i + 1); // 'A\Class' stored into 'a/class/Class.php' if (file_exists($file1 = strtolower($namespace . '/' . $file_name) . '/' . $file_name . '.php')) { /** @noinspection PhpIncludeInspection */ $result = (include_once Include_Filter::file($file1)); } elseif (file_exists($file2 = strtolower($namespace) . '/' . $file_name . '.php')) { /** @noinspection PhpIncludeInspection */ $result = (include_once Include_Filter::file($file2)); } else { if (Builder::isBuilt($class_name)) { $file = 'cache/compiled/' . str_replace(SL, '-', Names::classToPath($class_name)); if (file_exists($file)) { /** @noinspection PhpIncludeInspection */ $result = (include_once $file); } } if (!isset($result)) { if (error_reporting()) { trigger_error('Class not found ' . $class_name . ', should be into ' . $file1 . ' or ' . $file2, E_USER_ERROR); } $result = false; } } } else { /** @noinspection PhpIncludeInspection */ $result = (include_once Include_Filter::file($class_name . '.php')); } // instantiate plugin if ($result && class_exists($class_name, false) && is_a($class_name, Plugin::class, true)) { if (Session::current()) { Session::current()->plugins->get($class_name); } } }
/** * @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; }
/** * Gets a Reflection_Source knowing its class _name. * Uses sources cache, or router's getClassFilename() and fill-in cache. * * @param $class_name string * @return Reflection_Source */ public function getClassFilename($class_name) { if (isset($this->sources_cache[$class_name])) { return $this->sources_cache[$class_name]; } else { /** @var $router Router */ $router = Session::current()->plugins->get(Router::class); if (Builder::isBuilt($class_name)) { $file_name = $this->getCacheDir() . SL . str_replace(SL, '-', Names::classToPath($class_name)); } else { $file_name = $router->getClassFilename($class_name); } $source = new Reflection_Source($file_name, $this, $class_name); foreach (array_keys($source->getClasses()) as $class_name) { $this->sources_cache[$class_name] = $source; if (count($this->sources_cache) > self::MAX_OPENED_SOURCES) { $source->free(self::SOURCES_FREE); } } return $this->sources_cache[$class_name]; } }
/** * @param $class_name string * @return Reflection_Source */ public static function of($class_name) { $file = Names::classToPath($class_name) . '.php'; if (Builder::isBuilt($class_name)) { $file = 'cache/compiled/' . str_replace(SL, '-', substr($file, 0, -4)); } if (!file_exists($file)) { $file = strtolower(substr($file, 0, -4)) . SL . rLastParse($file, SL); } return new Reflection_Source($file); }
/** * Generates a link for to an object and feature, using parameters if needed * * @param $object object|string linked object or class name * @param $feature string linked feature name * @param $parameters string|string[]|object|object[] optional parameters list * @param $arguments string|string[] optional arguments list * @return string */ public function link($object, $feature = null, $parameters = null, $arguments = null) { // class name : not Built, not Set $class_names = is_string($object) ? $object : get_class($object); $class_name = Names::setToClass($class_names, false); $set_class = $class_name != $class_names; while (Builder::isBuilt($class_name)) { $class_name = get_parent_class($class_name); } if ($set_class) { $class_name = Names::classToSet($class_name); } // build uri $link = str_replace(BS, SL, is_object($object) && Dao::getObjectIdentifier($object) ? $class_name . SL . Dao::getObjectIdentifier($object) : $class_name); if (isset($feature)) { $link .= SL . $feature; } if (isset($parameters)) { if (!is_array($parameters)) { $parameters = [$parameters]; } foreach ($parameters as $key => $value) { if (!is_numeric($key)) { $link .= SL . $key; } if (is_object($value)) { $link .= SL . Names::classToUri(get_class($value)) . SL . Dao::getObjectIdentifier($value); } else { $link .= SL . $value; } } } // build arguments if (!empty($arguments)) { if (!is_array($arguments)) { $link .= '?' . urlencode($arguments); } else { $link .= '?'; $first = true; foreach ($arguments as $key => $value) { if ($first) { $first = false; } else { $link .= '&'; } $link .= $key . '=' . urlencode($value); } } } return SL . $link; }