/** * @param $class_name string the associated data class name * @param $feature_names string[] feature and inherited feature which view will be searched * @param $template string if a specific template is set, the view named with it will be * searched into the view / feature namespace first * @param $template_file_type string can search template files with another extension than 'html' * @return string the resulting path of the found template file */ public static function getTemplateFile($class_name, $feature_names, $template = null, $template_file_type = 'html') { if (isset($template)) { foreach ($feature_names as $feature_name) { $class = Getter::get($class_name, $feature_name, $template, $template_file_type, false)[0]; if (isset($class)) { break; } } } if (!isset($class)) { foreach ($feature_names as $feature_name) { $class = Getter::get($class_name, $feature_name, '', $template_file_type, false)[0]; if (isset($class)) { break; } } } return isset($class) ? Names::classToPath($class) . DOT . $template_file_type : stream_resolve_include_path('default' . DOT . $template_file_type); }
/** * 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); } } }
/** * Gets replacement class name for a parent class name or a list of traits to implement * * @param $class_name string can be short or full class name * @return string */ private function replacementClassName($class_name) { if ($this->enabled) { $result = isset($this->replacements[$class_name]) ? $this->replacements[$class_name] : $class_name; if (is_array($result)) { if ($this->build) { $this->compositions[$class_name] = $result; $built_class_name = Class_Builder::builtClassName($class_name); if (file_exists(Application::current()->getCacheDir() . '/compiled/' . str_replace('/', '-', Names::classToPath($built_class_name)))) { $result = $built_class_name; } else { $result = Class_Builder::build($class_name, $result); } $this->replacements[$class_name] = $result; } else { $result = $class_name; } } elseif (!$this->build && self::isBuilt($result)) { $result = $class_name; } } else { $result = $class_name; } return $class_name != $result && !self::isBuilt($result) ? $this->replacementClassName($result) : $result; }
/** * 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); }
/** * @param $base_class string The base name for the class, ie 'SAF\Framework\User' * @param $feature_name string The name of the feature, ie 'dataList' * @param $suffix string Class suffix, ie 'Controller', 'View' * @param $extension string File extension, ie 'php', 'html' * @param $class_form boolean true to use 'Feature_Class' naming instead of 'featureClass' * @return string[] [$class, $method] */ public static function get($base_class, $feature_name, $suffix, $extension, $class_form = true) { // ie : $feature_class = 'featureName' transformed into 'Feature_Name' $feature_class = Names::methodToClass($feature_name); // $feature_what is $feature_class or $feature_name depending on $class_name $feature_what = $class_form ? $feature_class : $feature_name; $_suffix = $suffix ? '_' . $suffix : ''; $class_name = $base_class; $ext = DOT . $extension; $method = 'run'; $application_classes = Application::current()->getClassesTree(); // $classes : the controller class name and its parents // ['Vendor\Application\Module\Class_Name' => '\Module\Class_Name'] $classes = []; do { $classes[$class_name] = substr($class_name, strpos($class_name, BS, strpos($class_name, BS) + 1) + 1); if (@class_exists($class_name)) { $reflection_class = new Reflection_Class(Builder::className($class_name)); foreach ($reflection_class->getTraits() as $trait) { $classes[$trait->name] = explode(BS, $trait->name, 3)[2]; } foreach ($reflection_class->getListAnnotation('extends')->values() as $extends) { $classes[$extends] = explode(BS, $extends, 3)[2]; } } $class_name = @get_parent_class($class_name); } while ($class_name); // Looking for specific controller for each application $application_class = reset($application_classes); do { $namespace = Namespaces::of($application_class); // for the controller class and its parents foreach ($classes as $short_class_name) { $class_name = $namespace . BS . $short_class_name; $path = strtolower(str_replace(BS, SL, $class_name)); if (isset($GLOBALS['D'])) { echo '- try A1 ' . $path . SL . $feature_what . $_suffix . $ext . BR; } if (file_exists($path . SL . $feature_what . $_suffix . $ext)) { $class = $class_name . BS . $feature_what . $_suffix; break 2; } if (isset($GLOBALS['D'])) { echo '- try A2 ' . $path . SL . strtolower($feature_class) . SL . $feature_what . $_suffix . $ext . BR; } if (file_exists($path . SL . strtolower($feature_class) . SL . $feature_what . $_suffix . $ext)) { $class = $class_name . BS . $feature_class . BS . $feature_what . $_suffix; break 2; } if (isset($GLOBALS['D']) && $suffix) { echo '- try A3 ' . $path . SL . strtolower($feature_class) . SL . $suffix . $ext . BR; } if ($suffix && file_exists($path . SL . strtolower($feature_class) . SL . $suffix . $ext)) { $class = $class_name . BS . $feature_class . BS . $suffix; break 2; } if (isset($GLOBALS['D'])) { echo '- try A4 ' . Names::classToPath($class_name) . '_' . $feature_what . $_suffix . $ext . BR; } if (file_exists(Names::classToPath($class_name) . '_' . $feature_what . $_suffix . $ext)) { $class = $class_name . '_' . $feature_what . $_suffix; break 2; } if (isset($GLOBALS['D']) && $suffix) { echo '- try A5 ' . $path . SL . $suffix . $ext . BR; } if ($suffix && file_exists($path . SL . $suffix . $ext) && method_exists($class_name . BS . $suffix, 'run' . ucfirst($feature_name))) { $class = $class_name . BS . $suffix; $method = 'run' . ucfirst($feature_name); break 2; } } // next application is the parent one $application_class = next($application_classes); } while ($application_class); // Looking for default controller for each application if (empty($class)) { reset($application_classes); do { // looking for default controller $path = strtolower(str_replace(BS, SL, $namespace)); if (isset($GLOBALS['D']) && $suffix) { echo '- try B1 ' . $path . SL . strtolower($feature_class) . SL . $suffix . $ext . BR; } if ($suffix && file_exists($path . SL . strtolower($feature_class) . SL . $suffix . $ext)) { $class = $namespace . BS . $feature_class . BS . $suffix; break; } if (isset($GLOBALS['D'])) { echo '- try B2 ' . $path . SL . strtolower($feature_class) . SL . $feature_what . $_suffix . $ext . BR; } if (file_exists($path . SL . strtolower($feature_class) . SL . $feature_what . $_suffix . $ext)) { $class = $namespace . BS . $feature_class . BS . $feature_what . $_suffix; break; } if (isset($GLOBALS['D']) && $suffix) { echo '- try B3 ' . $path . SL . 'widget' . SL . strtolower($feature_class) . SL . $suffix . $ext . BR; } if ($suffix && file_exists($path . SL . 'widget' . SL . strtolower($feature_class) . SL . $suffix . $ext)) { $class = $namespace . BS . 'Widget' . BS . $feature_class . BS . $suffix; break; } if (isset($GLOBALS['D'])) { echo '- try B4 ' . $path . SL . 'widget' . SL . strtolower($feature_class) . SL . $feature_what . $_suffix . $ext . BR; } if (file_exists($path . SL . 'widget' . SL . strtolower($feature_class) . SL . $feature_what . $_suffix . $ext)) { $class = $namespace . BS . 'Widget' . BS . $feature_class . BS . $feature_what . $_suffix; break; } if (isset($GLOBALS['D']) && $suffix) { echo '- try B5 ' . $path . SL . 'webservice' . SL . strtolower($feature_class) . SL . $suffix . $ext . BR; } if ($suffix && file_exists($path . SL . 'webservice' . SL . strtolower($feature_class) . SL . $suffix . $ext)) { $class = $namespace . BS . 'Webservice' . BS . $feature_class . BS . $suffix; break; } if (isset($GLOBALS['D'])) { echo '- try B6 ' . $path . SL . 'webservice' . SL . strtolower($feature_class) . SL . $feature_what . $_suffix . $ext . BR; } if (file_exists($path . SL . 'webservice' . SL . strtolower($feature_class) . SL . $feature_what . $_suffix . $ext)) { $class = $namespace . BS . 'Webservice' . BS . $feature_class . BS . $feature_what . $_suffix; break; } // next application is the parent one } while (next($application_classes)); // Looking for direct feature call, without using any controller static $last_controller_class = ''; static $last_controller_method = ''; if (empty($class) && (strpos($suffix, 'View') === false || $last_controller_class !== $base_class && $last_controller_method !== $feature_name)) { if (strpos($suffix, 'Controller') !== false) { $last_controller_class = $base_class; $last_controller_method = $feature_name; } if (@method_exists($base_class, $feature_name)) { $class = $base_class; $method = $feature_name; } } // Looking for default controller for each application if (empty($class) && $suffix) { reset($application_classes); // $suffix == 'Html_View' => $sub = 'View/Html', $suffix = 'View' if (strpos($suffix, '_')) { $elements = explode('_', $suffix); $sub = join(SL, array_reverse($elements)); $suffix = end($elements); } else { $sub = $suffix; } do { if (isset($GLOBALS['D'])) { echo '- try C2 ' . $path . SL . strtolower($sub) . '/Default_' . $suffix . $ext . BR; } if (file_exists($path . SL . strtolower($sub) . '/Default_' . $suffix . $ext)) { $class = $namespace . BS . str_replace(SL, BS, $sub) . BS . 'Default_' . $suffix; break; } } while (next($application_classes)); } } $result = [isset($class) ? $class : null, $method]; if (isset($GLOBALS['D'])) { echo '- FOUND ' . join('::', $result) . BR; } return $result; }