ILIAS  release_9 Revision v9.13-25-g2c18ec4c24f
URLBuilder.php
Go to the documentation of this file.
1 <?php
2 
18 declare(strict_types=1);
19 
20 namespace ILIAS\UI;
21 
22 use ILIAS\Data\URI;
23 
40 {
45  public const URL_MAX_LENGTH = 2048;
49  public const SEPARATOR = '_';
53  private URI $uri;
58  private ?string $fragment = null;
65  private array $params = [];
71  private array $tokens = [];
72 
73  public function __construct(URI $uri)
74  {
75  $this->uri = $uri;
76  }
77 
81  public function withURI(URI $uri): self
82  {
83  $clone = clone $this;
84  $clone->uri = $uri;
85  return $clone;
86  }
87 
91  public function withFragment(?string $fragment): self
92  {
93  $clone = clone $this;
94  $clone->fragment = $fragment;
95  return $clone;
96  }
97 
118  public function acquireParameter(array $namespace, string $name, ?string $initial_value = null): array
119  {
120  if ($name === '' || empty($namespace)) {
121  throw new \InvalidArgumentException("Parameter name or namespace not set");
122  }
123 
124  $parameter = implode(self::SEPARATOR, $namespace) . self::SEPARATOR . $name;
125  if ($this->parameterExists($parameter)) {
126  throw new \ilException("Parameter '" . $parameter . "' already reserved in URL");
127  }
128 
129  $token = new URLBuilderToken($namespace, $name);
130  $clone = clone $this;
131  $clone->params[$parameter] = ($initial_value) ?? '';
132  $clone->tokens[$parameter] = $token;
133 
134  return [$clone, $token];
135  }
136 
137  public function acquireParameters(array $namespace, string ...$names): array
138  {
139  $tokens = [];
140  $builder = $this;
141  foreach ($names as $name) {
142  list($builder, $token) = $builder->acquireParameter($namespace, $name);
143  $tokens[] = $token;
144  }
145  array_unshift($tokens, $builder);
146  return $tokens;
147  }
148 
152  public function deleteParameter(URLBuilderToken $token): self
153  {
154  $this->checkToken($token);
155  $clone = clone $this;
156  unset($clone->params[$token->getName()]);
157  unset($clone->tokens[$token->getName()]);
158 
159  return $clone;
160  }
161 
165  public function withParameter(URLBuilderToken $token, string|array $value): self
166  {
167  $this->checkToken($token);
168  $clone = clone $this;
169  $clone->params[$token->getName()] = $value;
170 
171  return $clone;
172  }
173 
182  public function renderTokens(array $tokens): string
183  {
184  $token_render = [];
185  foreach ($tokens as $token) {
186  $token_render[] = '["' . $token->getName() . '",' . $token->render() . ']';
187  }
188  $output = 'new Map([' . implode(',', $token_render) . '])';
189  return $output;
190  }
191 
202  public function renderObject(array $tokens): string
203  {
204  $output = 'new il.UI.core.URLBuilder(new URL("' . $this->buildURI() . '"), ' . $this->renderTokens($tokens) . ')';
205  return $output;
206  }
207 
211  public function buildURI(): URI
212  {
213  $uri = new URI($this->uri->getBaseURI() . $this->buildQuery() . $this->buildFragment());
214  $this->checkLength($uri);
215  return $uri;
216  }
217 
224  private function buildQuery(): string
225  {
226  $params = array_merge($this->uri->getParameters(), $this->params);
227  $query = (! empty($params)) ? '?' . http_build_query($params) : '';
228  $query = preg_replace('/%5B[0-9]+%5D/simU', '%5B%5D', $query);
229  return $query;
230  }
231 
235  private function buildFragment(): string
236  {
237  if ($this->fragment !== null) {
238  return ($this->fragment !== '') ? '#' . $this->fragment : '';
239  }
240  $fragment = ($this->uri->getFragment()) ? '#' . $this->uri->getFragment() : '';
241  return $fragment;
242  }
243 
247  private function parameterExists(string $name): bool
248  {
249  return array_key_exists($name, $this->params);
250  }
251 
258  private function checkToken(URLBuilderToken $token): void
259  {
260  if (! in_array($token, $this->tokens)
261  || $this->tokens[$token->getName()]->getToken() !== $token->getToken()) {
262  throw new \DomainException("Token for '" . $token->getName() . "' is not valid");
263  }
264  if (! $this->parameterExists($token->getName())) {
265  throw new \ilException("Parameter '" . $token->getName() . "' does not exist in URL");
266  }
267  }
268 
274  private function checkLength(URI $uri): void
275  {
276  if (! (strlen((string) $uri) <= self::URL_MAX_LENGTH)) {
277  throw new \LengthException("The final URL is longer than " . self::URL_MAX_LENGTH . " and will not be valid.");
278  }
279  }
280 }
if($err=$client->getError()) $namespace
string $fragment
Stores the URL fragment/hash (#) (always changeable due to its usage)
Definition: URLBuilder.php:58
getName()
Get the full name of the token including its namespace.
URI $uri
Base URI for the URLBuilder.
Definition: URLBuilder.php:53
parameterExists(string $name)
Check if parameter was already acquired.
Definition: URLBuilder.php:247
buildFragment()
Create the fragment/hash part of the URL.
Definition: URLBuilder.php:235
buildURI()
Get a URI representation of the full URL including query string and fragment/hash.
Definition: URLBuilder.php:211
const URL_MAX_LENGTH
A maximum length of 2048 characters should be safe to use in most browsers, even though longer URLs w...
Definition: URLBuilder.php:45
acquireParameters(array $namespace, string ... $names)
Definition: URLBuilder.php:137
const SEPARATOR
Separator for parts of a parameter&#39;s namespace.
Definition: URLBuilder.php:49
withFragment(?string $fragment)
Change the fragment/hash part of the URL.
Definition: URLBuilder.php:91
getToken()
Get the token hash value.
renderObject(array $tokens)
Renders a Javascript URLBuilder object with changeable parameters for all given tokens.
Definition: URLBuilder.php:202
__construct(URI $uri)
Definition: URLBuilder.php:73
renderTokens(array $tokens)
Renders a Javascript Map of all given tokens.
Definition: URLBuilder.php:182
$token
Definition: xapitoken.php:70
buildQuery()
Create the query part of the URL from all parameters Claimed parameters overwrite base parameters in ...
Definition: URLBuilder.php:224
The scope of this class is split ilias-conform URI&#39;s into components.
Definition: URI.php:18
checkLength(URI $uri)
Check the full length of the URI against URL_MAX_LENGTH.
Definition: URLBuilder.php:274
withParameter(URLBuilderToken $token, string|array $value)
Change an acquired parameter&#39;s value if the supplied token is valid.
Definition: URLBuilder.php:165
withURI(URI $uri)
Changes the base URI of the Builder.
Definition: URLBuilder.php:81
array $tokens
Stores all generated tokens for acquired parameters.
Definition: URLBuilder.php:71
deleteParameter(URLBuilderToken $token)
Delete an acquired parameter if the supplied token is valid.
Definition: URLBuilder.php:152
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
acquireParameter(array $namespace, string $name, ?string $initial_value=null)
Add a new parameter with a namespace and get its token for subsequent changes.
Definition: URLBuilder.php:118
array $params
Stores all acquired parameters These always take precedence over existing parameters in the base URI...
Definition: URLBuilder.php:65
URLBuilder.
Definition: URLBuilder.php:39
checkToken(URLBuilderToken $token)
Check if a token is valid.
Definition: URLBuilder.php:258