protected function expandUriTemplate($url, array $parameters, array $defaultParameters)
{
$parameters += $defaultParameters;
static $operatorFlags = ['' => ['prefix' => '', 'separator' => ',', 'named' => FALSE, 'ifEmpty' => '', 'reserved' => FALSE], '+' => ['prefix' => '', 'separator' => ',', 'named' => FALSE, 'ifEmpty' => '', 'reserved' => TRUE], '#' => ['prefix' => '#', 'separator' => ',', 'named' => FALSE, 'ifEmpty' => '', 'reserved' => TRUE], '.' => ['prefix' => '.', 'separator' => '.', 'named' => FALSE, 'ifEmpty' => '', 'reserved' => FALSE], '/' => ['prefix' => '/', 'separator' => '/', 'named' => FALSE, 'ifEmpty' => '', 'reserved' => FALSE], ';' => ['prefix' => ';', 'separator' => ';', 'named' => TRUE, 'ifEmpty' => '', 'reserved' => FALSE], '?' => ['prefix' => '?', 'separator' => '&', 'named' => TRUE, 'ifEmpty' => '=', 'reserved' => FALSE], '&' => ['prefix' => '&', 'separator' => '&', 'named' => TRUE, 'ifEmpty' => '=', 'reserved' => FALSE]];
return preg_replace_callback('~{([+#./;?&])?([^}]+?)}~', function ($m) use($url, &$parameters, $operatorFlags) {
$flags = $operatorFlags[$m[1]];
$translated = [];
foreach (explode(',', $m[2]) as $name) {
$explode = FALSE;
$maxLength = NULL;
if (preg_match('~^(.+)(?:(\\*)|:(\\d+))$~', $name, $tmp)) {
// TODO: Speed up?
$name = $tmp[1];
if (isset($tmp[3])) {
$maxLength = (int) $tmp[3];
} else {
$explode = TRUE;
}
}
if (!isset($parameters[$name])) {
// TODO: Throw exception?
continue;
}
$value = $parameters[$name];
if (is_scalar($value)) {
$translated[] = $this->prefix($flags, $name, $this->escape($flags, $value, $maxLength));
} else {
$value = (array) $value;
$isAssoc = key($value) !== 0;
// The '*' (explode) modifier
if ($explode) {
$parts = [];
if ($isAssoc) {
$this->walk($value, function ($v, $k) use(&$parts, $flags, $maxLength) {
$parts[] = $this->prefix(['named' => TRUE] + $flags, $k, $this->escape($flags, $v, $maxLength));
});
} elseif ($flags['named']) {
$this->walk($value, function ($v) use(&$parts, $flags, $name, $maxLength) {
$parts[] = $this->prefix($flags, $name, $this->escape($flags, $v, $maxLength));
});
} else {
$this->walk($value, function ($v) use(&$parts, $flags, $maxLength) {
$parts[] = $this->escape($flags, $v, $maxLength);
});
}
if (isset($parts[0])) {
if ($flags['named']) {
$translated[] = implode($flags['separator'], $parts);
} else {
$translated[] = $this->prefix($flags, $name, implode($flags['separator'], $parts));
}
}
} else {
$parts = [];
$this->walk($value, function ($v, $k) use(&$parts, $isAssoc, $flags, $maxLength) {
if ($isAssoc) {
$parts[] = $this->escape($flags, $k);
}
$parts[] = $this->escape($flags, $v, $maxLength);
});
if (isset($parts[0])) {
$translated[] = $this->prefix($flags, $name, implode(',', $parts));
}
}
}
}
if (isset($translated[0])) {
return $flags['prefix'] . implode($flags['separator'], $translated);
}
return '';
}, $url);
}