/** * @param string $path * @return string * @throws RouterException */ private function resolvePath(string $path) : string { // Filter path $pathKey = $this->filterPath($path); // Check in predefined routes foreach ($this->routes as $route => $controller) { if (preg_match(sprintf("~^%s\$~", $route), $pathKey)) { // Match found return $controller; } } // Make sure default controllers base directory path is set if (!$this->controllersPath) { throw RouterException::controllersPathNull(); } // Dynamically convert path to class name $pathIndex = -1; $controllerClass = array_map(function ($piece) use(&$pathIndex) : string { $pathIndex++; if ($piece && !in_array($pathIndex, $this->ignorePathIndexes)) { return \Comely::pascalCase($piece); } return ""; }, explode("/", trim(Strings::filter(strtolower($path), "an", false, "/_"), "/"))); $controllerClass = trim(implode("\\", $controllerClass), "\\"); $controllerClass = preg_replace("/\\\\{2,}/", "\\", $controllerClass); // Join PascalCased class name with default namespace preset $controllerClass = $this->controllersNamespace . $controllerClass; // Return name of class return $controllerClass; }
/** * Resolves a variable and applies modifiers * @param string $input * @return string */ private function resolveVariable(string $input) : string { // Split $modifiers = explode("|", trim($input)); $var = $modifiers[0]; unset($modifiers[0]); // Resolve var if (!preg_match('/^\\$[a-z\\_][a-z0-9\\_\\.]+$/i', $var)) { $this->throwException('Bad variable syntax'); } // Explode var into pieces (Array) $pieces = explode(".", $var); $var = $pieces[0]; unset($pieces[0]); // Check if its reserved variable (i.e. being used by foreach/count clause) if (!$this->reserved->has($var)) { // Load from assigned data $var = sprintf('$this->data["%s"]', strtolower(substr($var, 1))); } // Assemble pieces array style foreach ($pieces as $piece) { $var .= sprintf('["%s"]', $piece); } // Apply modifiers foreach ($modifiers as $modifier) { preg_match_all("~'[^']++'|\\([^)]++\\)|[^:]++~", $modifier, $modifier); $modifier = $modifier[0]; $opts = $modifier; unset($opts[0]); $modifier = $modifier[0]; // Check modifier args $opts = array_values($opts); $optsCount = count($opts); for ($i = 0; $i < $optsCount; $i++) { if (preg_match('/^\\$[a-z\\_][a-z0-9\\_\\.]+$/i', $opts[$i])) { // Variable $opts[$i] = $this->resolveVariable($opts[$i]); } elseif (preg_match('/^[0-9][\\.0-9]*$/', $opts[$i])) { // Integer or float $cast = strpos($opts[$i], ".") ? "floatval" : "intval"; $opts[$i] = call_user_func($cast, $opts[$i]); } elseif (in_array(strtolower($opts[$i]), ["true", "false"])) { // Boolean $opts[$i] = boolval($opts[$i]); } elseif (strtolower($opts[$i]) === "null") { // NULL $opts[$i] = null; } else { // String $opts[$i] = str_replace(["'", '""'], "", $opts[$i]); // Remove quotes } } try { $modifierInstance = $this->modifiers->pull($modifier, function ($repo, $key) { // Modifier not instantiated yet $modifierClass = sprintf('Comely\\Knit\\Modifiers\\%s', \Comely::pascalCase($key)); if (!class_exists($modifierClass)) { $this->throwException(sprintf("Modifier '%s' not found", $key)); } $modifier = new $modifierClass(); $repo->push($modifier, $key); return $modifier; }); $var = call_user_func_array([$modifierInstance, "apply"], [$var, $opts]); } catch (\Throwable $e) { $this->throwException(sprintf("Modifier '%s' %s", $modifier, $e->getMessage())); } } return $var; }