public static function fromArray(array $array) { $route = new self(); foreach ($array as $name => $value) { $route->{$name} = $value; } if ($route->endPoint && substr($route->endPoint, 0, 2) == 'C:') { $route->endPoint = unserialize($route->endPoint); } if ($route->to) { $route->to = ActionToken::fromArray($route->to); } return $route; }
/** * Verifies that the route exists and returns the path as string. */ protected function ensureRouteExists($controllerClass, $actionName, array $parameters) { $nameParts = array_map(function ($part) { return lcfirst($part); }, explode('\\', preg_replace('/Controller$/', '', $controllerClass))); $normalizedControllerName = implode(ActionToken::NAMESPACE_SEPARATOR, $nameParts); $tokenParams = ['controller' => $normalizedControllerName, 'action' => $actionName]; $token = new ActionToken($tokenParams); array_unshift($parameters, $token->toString()); $url = $this->routeSet->urlFor($parameters); if (!$url) { array_shift($parameters); $parameters = array_merge($tokenParams, $parameters); $pairs = []; foreach ($parameters as $key => $value) { $pairs[] = $key . '=>' . (is_scalar($value) ? '"' . $value . '"' : '(' . gettype($value) . ')'); } throw new \Exception(sprintf('No route matches [%s]', implode(', ', $pairs))); } $pos = strpos($url, '?'); if ($pos) { $url = substr($url, 0, $pos); } return $url; }
protected function buildEndpoint() { $options = $this->options; if (isset($options['to']) && (is_string($options['to']) && ctype_upper(substr($options['to'], 0, 1)) || $options['to'] instanceof SerializableClosure)) { $this->endPoint = $options['to']; unset($this->options['to']); return; } $scope = $this->scope; $parts = ['namespaces' => []]; if ($options['to']) { $token = new ActionToken($options['to']); $parts['controller'] = $token->controller(); $parts['action'] = $token->action(); } elseif (array_key_exists('action', $options) || isset($scope['action'])) { $parts['action'] = $options['action'] ?: $scope['action']; if (isset($scope['controller'])) { $parts['controller'] = $scope['controller']; } elseif (isset($scope['scopeLevelResource'])) { $parts['controller'] = $scope['scopeLevelResource']->controller(); } else { throw new \UnexpectedValueException("Couldn't find controller option"); } } if (isset($scope['namespace'])) { $parts['namespaces'][] = $scope['namespace']; } if (isset($options['namespace'])) { $parts['namespaces'][] = $options['namespace']; } $token = new ActionToken($parts); $this->to = $token; $this->controller = $token->controller(); $this->action = $token->action(); $this->namespaces = $token->namespaces(); }
public function render($baseHelper, $model, $options, Closure $block = null) { if ($options instanceof Closure) { $block = $options; $options = []; } $inf = $baseHelper->getService('inflector'); $modelClass = get_class($model); $controller = str_replace('/', ActionToken::NAMESPACE_SEPARATOR, lcfirst($inf->pluralize($modelClass))); // $primaryKey = $modelClass::primaryKey(); $urlPath = null; if (isset($options['url'])) { if ($baseHelper->isUrl($options['url'])) { $urlPath = $options['url']; } else { if (is_array($options['url'])) { $token = new ActionToken($options['url'][0]); } else { # Action token (string) assumed. $token = new ActionToken($options['url']); } $action = $token->action(); $urlPath = $baseHelper->urlFor($token->toString()); } } else { if ($id = $model->id()) { $action = 'update'; $urlParams = [$controller . '#' . $action, $model]; } else { $action = 'create'; $urlParams = [$controller . '#' . $action]; } $urlPath = $baseHelper->urlFor($urlParams); } if (!isset($options['html'])) { $htmlAttrs = []; } else { $htmlAttrs = $options['html']; } if (isset($options['as'])) { $inputNamespace = $options['as']; } else { $inputNamespace = null; } switch ($action) { case 'create': $resourceName = $baseHelper->objectName($model); if (empty($htmlAttrs['method'])) { $htmlAttrs['method'] = 'post'; } if (empty($htmlAttrs['id'])) { $htmlAttrs['id'] = 'new_' . $resourceName; } $baseHelper->addClass($htmlAttrs, 'new_' . $resourceName); break; case 'update': $resourceName = $baseHelper->objectName($model); if (empty($htmlAttrs['method'])) { $htmlAttrs['method'] = 'patch'; } if (empty($htmlAttrs['id'])) { $htmlAttrs['id'] = 'edit_' . $resourceName . '_' . $model->id(); } $baseHelper->addClass($htmlAttrs, 'edit_' . $resourceName); break; case 'destroy': if (empty($htmlAttrs['method'])) { $htmlAttrs['method'] = 'delete'; } break; } if (!empty($options['remote'])) { $htmlAttrs['data-remote'] = 'true'; } if (empty($options['builder'])) { $formBuilder = $baseHelper->helperSet()->invoke('getFormBuilder', [$model, $inputNamespace]); } else { # "builder" option could be the name of a class extending FormBuilder. $formBuilder = new $options['builder']($baseHelper->helperSet(), $model, $inputNamespace); } return $baseHelper->helperSet()->invoke('formTag', [$urlPath, $htmlAttrs, function () use($block, $formBuilder) { $formBuilder->runBlock($block); }]); }
/** * Get the URL path for a route by providing an "action token" as array or string. * * Options used by this method: * * route - Returns both the built path and the matched route. * * ``` * $set->urlFor([['controller' => 'posts', 'action' => 'index']]); * $set->urlFor([['controller' => 'posts', 'action' => 'show'], 'id' => 15]); * $set->urlFor('posts#index'); * $set->urlFor(['posts#show', 'id' => 15]); * ``` * * @param string|array $criteria */ public function urlFor($criteria, array $options = []) { if (is_array($criteria)) { $pathParams = array_slice($criteria, 1); $criteria = array_shift($criteria); } else { $pathParams = []; } $token = new ActionToken($criteria); foreach ($this->routes as $route) { $route->build(); if ($route->to() == $token->toString()) { if ($path = $this->buildRouteUrl($route, $pathParams, $options)) { if (!empty($options['route'])) { return [$path, $route]; } return $path; } } } $routeParams = implode(', ', array_map(function ($name, $val) { return $name . '=>' . $val; }, array_keys($options), $options)); $message = "Couldn't find route '%s' and options { %s }"; throw new Exception\InvalidArgumentException(sprintf($message, $token->toString(), $routeParams)); # TODO: invalid argument exception? return false; }