/** * @param $view_name string the view name is 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 * @return callable */ private static function getView($view_name, $feature_names, $template = null) { $view_engine_name = get_class(View::current()); $view_engine_name = Namespaces::shortClassName(Namespaces::of($view_engine_name)); if (isset($template)) { foreach ([$view_engine_name . '_View', 'View'] as $suffix) { foreach ($feature_names as $feature_name) { list($class, $method) = Getter::get($view_name, $feature_name, Names::methodToClass($template) . '_' . $suffix, 'php'); if (isset($class)) { break 2; } } } } if (!isset($class)) { foreach ([$view_engine_name . '_View', 'View'] as $suffix) { foreach ($feature_names as $feature_name) { list($class, $method) = Getter::get($view_name, $feature_name, $suffix, 'php'); if (isset($class)) { break 2; } } } } if (!isset($class)) { list($class, $method) = [__CLASS__ . BS . $view_engine_name . BS . 'Default_View', 'run']; } /** @noinspection PhpUndefinedVariableInspection if $class is set, then $method is set too */ return [$class, $method]; }
/** * @param $doc_comment string * @param $annotation_name string * @param $i integer * @param $annotation_class string * @param $reflection_object Has_Doc_Comment|Reflection * @return Annotation */ private static function parseAnnotationValue($doc_comment, $annotation_name, &$i, $annotation_class, Reflection $reflection_object) { $i += strlen($annotation_name) + 1; $next_char = $doc_comment[$i]; switch ($next_char) { case SP: case TAB: $i++; $j = strlen($doc_comment); $next_annotation = strpos($doc_comment, SP . '* @', $i); $end_doc_comment = strpos($doc_comment, SP . '*/', $i); $next_in = strpos($doc_comment, LF . self::DOC_COMMENT_IN, $i); if ($next_annotation !== false && $next_annotation < $j) { $j = $next_annotation; } if ($end_doc_comment !== false && $end_doc_comment < $j) { $j = $end_doc_comment; } if ($next_in !== false && $next_in < $j) { $j = $next_in; } if ($j === false) { trigger_error('Missing doc_comment end', E_USER_ERROR); } $value = trim(preg_replace('%\\s*\\n\\s+\\*\\s*%', '', substr($doc_comment, $i, $j - $i))); break; case CR: case LF: $value = true; break; default: $value = null; } /** @var $annotation Annotation */ $annotation = isset($value) ? new $annotation_class($value, $reflection_object, $annotation_name) : null; if (isset($annotation) && isA($annotation, Annotation_In::class)) { /** @var $annotation Annotation_In */ $j = strrpos(substr($doc_comment, 0, $i), LF . self::DOC_COMMENT_IN); if ($j === false) { $annotation->class_name = $reflection_object instanceof Reflection_Class_Component ? $reflection_object->getDeclaringClassName() : $reflection_object->getName(); } else { $j += strlen(self::DOC_COMMENT_IN) + 1; $k = strpos($doc_comment, LF, $j); $annotation->class_name = substr($doc_comment, $j, $k - $j); } } if (isset($annotation) && isA($annotation, Types_Annotation::class)) { $do = false; if (is_array($annotation->value)) { foreach ($annotation->value as $value) { if ($value && (ctype_upper($value[0]) || $value[0] == BS)) { $do = true; break; } } } else { $do = $annotation->value && ctype_upper($annotation->value[0]); } if ($do) { /** @var $annotation Types_Annotation */ $j = strrpos(substr($doc_comment, 0, $i), LF . self::DOC_COMMENT_IN); if ($j === false) { $class_name = $reflection_object instanceof Reflection_Class_Component ? $reflection_object->getDeclaringClassName() : $reflection_object->getName(); $namespace = Namespaces::of($class_name); $use = PHP\Reflection_Class::of($class_name)->getNamespaceUse(); } else { $j += strlen(self::DOC_COMMENT_IN) + 1; $k = strpos($doc_comment, LF, $j); $in_class = substr($doc_comment, $j, $k - $j); $namespace = Namespaces::of($in_class); $use = PHP\Reflection_Class::of($in_class)->getNamespaceUse(); } $annotation->applyNamespace($namespace, $use); } elseif (is_array($annotation->value)) { foreach ($annotation->value as $key => $value) { $annotation->value[$key] = Builder::className($value); } } else { if ($annotation->value[0] === BS) { $annotation->value = substr($annotation->value, 1); } $annotation->value = Builder::className($annotation->value); } } return $annotation; }
/** * @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; }
/** * Gets built name space for a class name * * @param $class_name string ie 'SAF\Framework\Module\Class_Name' * @return string ie 'Vendor\Application\Built\SAF\Framework\Module\Class_Name' */ public static function builtClassName($class_name) { $namespace = array_slice(explode(BS, Namespaces::of($class_name)), 1); $left = Application::current()->getNamespace(); $namespace = $left . BS . 'Built' . BS . join(BS, $namespace); $built_class = $namespace . BS . Namespaces::shortClassName($class_name); return $built_class; }
/** * Changes 'A\Namespace\Class_Names' into 'A\Namespace\Class_Name' * * @param $class_name string * @param $check_class boolean false if you don't want to check for existing classes * @return string */ public static function setToClass($class_name, $check_class = true) { $set_class_name = $class_name; $class_name = Namespaces::shortClassName($class_name); $right = ''; do { $class_name = self::setToSingle($class_name); $full_class_name = Namespaces::defaultFullClassName($class_name . $right, $set_class_name); if (@class_exists($full_class_name) || trait_exists($full_class_name, false)) { return $full_class_name; } $i = strrpos($class_name, '_'); if (strrpos($class_name, BS) > $i) { $i = false; } if ($i === false) { if ((@class_exists($set_class_name) || trait_exists($set_class_name, false)) && (new Reflection_Class($set_class_name))->getAnnotation('set')->value == $set_class_name) { return $set_class_name; } elseif ($check_class && error_reporting()) { trigger_error('No class found for set ' . $set_class_name, E_USER_ERROR); } else { $right = substr($class_name, $i) . $right; $class_name = substr($class_name, 0, $i); } } else { $right = substr($class_name, $i) . $right; $class_name = substr($class_name, 0, $i); } } while (!empty($class_name)); $class_name .= $right; if (class_exists($class_name, false) || trait_exists($class_name, false)) { return $class_name; } elseif (strrpos($set_class_name, '_') > strrpos($set_class_name, BS)) { $namespace = Namespaces::of($set_class_name); $class_name = substr($set_class_name, strpos($set_class_name, '_', strlen($namespace)) + 1); return self::setToClass($namespace . BS . $class_name, $check_class); } else { return $set_class_name; } }