/** * 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, , $names, $names_hash, $action, $module, , $options, , ) = $this->routes[$name]; $defaults = array('action' => $action, 'module' => $module); $params = self::arrayDeepMerge($defaults, $params); if (array_key_exists('csrf_enabled', $options) && $options['csrf_enabled']) { $params['csrf_token'] = Context::generateCSRFtoken(); } // 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)); } } // in PHP 5.5, preg_replace with /e modifier is deprecated; preg_replace_callback is recommended $callback = function ($matches) use($params) { return array_key_exists($matches[1], $params) ? urlencode($params[$matches[1]]) : $matches[0]; }; $real_url = preg_replace_callback('/\\:([^\\/]+)/', $callback, $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 Context::getURLhost() . Context::getStrippedWebroot() . $real_url; } return Context::getStrippedWebroot() . $real_url; }