/** * Generate a url based on a route * * @param string $name The route key * @param array $params key=>value pairs of route parameters * @param boolean $relative Whether to generate an url relative to web root or an absolute * * @return string */ public function generate($name, $params = array(), $relative = true, $querydiv = '/', $divider = '/', $equals = '/') { if (mb_substr($name, 0, 1) == '@') { $name = mb_substr($name, 1); $details = explode('?', $name); $name = array_shift($details); if (count($details)) { $param_details = array_shift($details); $param_details = explode('&', $param_details); foreach ($param_details as $detail) { $param_detail = explode('=', $detail); if (count($param_detail) > 1) { $params[$param_detail[0]] = $param_detail[1]; } } } } if (!isset($this->routes[$name])) { Logging::log("The route '{$name}' does not exist", 'routing', Logging::LEVEL_FATAL); throw new \Exception("The route '{$name}' does not exist"); } list($url, $regexp, $names, $names_hash, $action, $module, $defaults, $csrf_enabled) = $this->routes[$name]; $defaults = array('action' => $action, 'module' => $module); // all params must be given foreach ($names as $tmp) { if (!isset($params[$tmp]) && !isset($defaults[$tmp])) { throw new \Exception(sprintf('Route named "%s" have a mandatory "%s" parameter', $name, $tmp)); } } $params = self::arrayDeepMerge($defaults, $params); if ($csrf_enabled) { $params['csrf_token'] = Caspar::generateCSRFtoken(); } $real_url = preg_replace_callback('/\\/\\:([^\\/]+)/', function ($matches) use($params) { return '/' . $params[$matches[1]]; }, $url); // we add all other params if * if (mb_strpos($real_url, '*')) { $tmp = array(); foreach ($params as $key => $value) { if (isset($names_hash[$key]) || isset($defaults[$key])) { continue; } if (is_array($value)) { foreach ($value as $k => $v) { if (is_array($v)) { foreach ($v as $vk => $vv) { if (is_array($vv)) { foreach ($vv as $vvk => $vvv) { $tmp[] = "{$key}[{$k}][{$vk}][{$vvk}]" . $equals . urlencode($vvv); } } else { $tmp[] = "{$key}[{$k}][{$vk}]" . $equals . urlencode($vv); } } } else { $tmp[] = "{$key}[{$k}]" . $equals . urlencode($v); } } } else { $tmp[] = urlencode($key) . $equals . urlencode($value); } } $tmp = implode($divider, $tmp); if (mb_strlen($tmp) > 0) { $tmp = $querydiv . $tmp; } $real_url = preg_replace('/\\/\\*(\\/|$)/', "{$tmp}\$1", $real_url); } // strip off last divider character if (mb_strlen($real_url) > 1) { $real_url = rtrim($real_url, $divider); } if (!$relative) { return Caspar::getBaseUrl() . $real_url; } return $real_url; }