PluginProbe
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution / 2.5.0
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution v2.5.0
2.5.0 2.4.0 2.3.0 2.2.5 2.2.0 2.1.2 2.1.1 trunk 1.10.0 1.10.01 1.10.02 1.5.0 1.5.01 1.5.02 1.5.1 1.5.10 1.5.20 1.5.21 1.5.22 1.5.23 1.5.24 1.5.25 1.6.0 1.7.0 1.7.1 All 34 releases
← All changes | vendor/wpfluent/framework/src/WPFluent/Http/URL.php +477 -11 1.5.01 → 2.5.0 View file →
@@ -1,11 +1,155 @@
1 1 <?php
2 2
3 3 namespace FluentBooking\Framework\Http;
4 4
5 +use Exception;
6 +use InvalidArgumentException;
7 +use FluentBooking\Framework\Support\Util;
8 +use FluentBooking\Framework\Foundation\App;
9 +use FluentBooking\Framework\Support\UriTemplate;
10 +
5 11 class URL
6 12 {
7 13 /**
14 + * The full URL string.
15 + *
16 + * @var string
17 + */
18 + protected $url = '';
19 +
20 + /**
21 + * URL generator instance used for signing and route generation.
22 + *
23 + * @var UrlGenerator|null
24 + */
25 + protected $generator = null;
26 +
27 + /**
28 + * URL scheme (e.g., 'http', 'https').
29 + *
30 + * @var string
31 + */
32 + protected $scheme = '';
33 +
34 + /**
35 + * URL host (e.g., 'example.com').
36 + *
37 + * @var string|null
38 + */
39 + protected $host = null;
40 +
41 + /**
42 + * URL port (e.g., 80, 443).
43 + *
44 + * @var int|null
45 + */
46 + protected $port = null;
47 +
48 + /**
49 + * URL path (e.g., '/users/view').
50 + *
51 + * @var string
52 + */
53 + protected $path = '';
54 +
55 + /**
56 + * URL query parameters as an associative array.
57 + *
58 + * @var array
59 + */
60 + protected $query = [];
61 +
62 + /**
63 + * URL fragment (e.g., 'top' in '#top').
64 + *
65 + * @var string|null
66 + */
67 + protected $fragment = null;
68 +
69 + /**
70 + * URL username for authentication (if any).
71 + *
72 + * @var string|null
73 + */
74 + protected $user = null;
75 +
76 + /**
77 + * URL password for authentication (if any).
78 + *
79 + * @var string|null
80 + */
81 + protected $pass = null;
82 +
83 + /**
84 + * Constructor.
85 + *
86 + * @param string|null $url Optional URL to initialize. Defaults to current URL.
87 + * @param UrlGenerator|null $generator Optional generator instance for signing/routes.
88 + *
89 + * @throws InvalidArgumentException If the given URL is invalid.
90 + */
91 + public function __construct($url = '', $generator = null)
92 + {
93 + $this->prepareRfcProperties(
94 + $this->url = $url ?: $this->current()
95 + );
96 +
97 + $this->generator = $generator ?: new UrlGenerator();
98 + }
99 +
100 + /**
101 + * Parse a URL according to RFC 3986 and populate internal components.
102 + *
103 + * @param string $url The URL to parse.
104 + *
105 + * @return void
106 + *
107 + * @throws InvalidArgumentException If the URL cannot be parsed.
108 + */
109 + protected function prepareRfcProperties($url)
110 + {
111 + // --- Parse URL according to RFC3986 ---
112 + $parts = parse_url($url);
113 +
114 + if ($parts === false) {
115 + throw new InvalidArgumentException("Invalid URL: {$url}");
116 + }
117 +
118 + $this->scheme = $parts['scheme'] ?? '';
119 + $this->host = $parts['host'] ?? null;
120 + $this->port = $parts['port'] ?? null;
121 + $this->path = $parts['path'] ?? null;
122 + $this->user = $parts['user'] ?? null;
123 + $this->pass = $parts['pass'] ?? null;
124 + $this->fragment = $parts['fragment'] ?? null;
125 +
126 + if (isset($parts['query'])) {
127 + parse_str($parts['query'], $query);
128 + $this->query = $query;
129 + } else {
130 + $this->query = [];
131 + }
132 + }
133 +
134 + /**
135 + * Create a new URL instance.
136 + *
137 + * @param string $uri
138 + * @return static
139 + */
140 + public static function of($uri)
141 + {
142 + $parts = parse_url($uri);
143 +
144 + if ($parts === false) {
145 + throw new InvalidArgumentException("Invalid URI: {$uri}");
146 + }
147 +
148 + return new static($uri);
149 + }
150 +
151 + /**
8 152 * Get the current URL
9 153 *
10 154 * @return string
11 155 */
@@ -10,9 +154,9 @@
10 154 * @return string
11 155 */
12 156 public function current()
13 157 {
14 - return get_site_url() . rtrim(preg_replace('/\?.*/', '', $_SERVER['REQUEST_URI']), '/');
158 + return rtrim(get_site_url(), '/') . $_SERVER['REQUEST_URI'];
15 159 }
16 160
17 161 /**
18 162 * Parse a url from uncompiled route
@@ -22,24 +166,346 @@
22 166 * @return string
23 167 */
24 168 public function parse(string $url, array $params)
25 169 {
26 - return preg_replace_callback('#\{[a-zA-Z0-9-_]+\}#', function($matches) use ($params) {
27 - foreach ($matches as $match) {
28 - $match = str_replace(['{', '}'], ['', ''], $match);
29 - if (isset($params[$match])) {
30 - return $params[$match];
31 - }
32 - }
33 - }, $url);
170 + return UriTemplate::expand($url, $params);
34 171 }
35 172
36 173 /**
37 - * Returns the string representation of the URL object
174 + * Sign the current url.
38 175 *
176 + * @param array $params
177 + * @return string
178 + */
179 + public function signCurrentUrl($params = [])
180 + {
181 + return $this->sign($this->current(), $params);
182 + }
183 +
184 + /**
185 + * Sign a URL
186 + *
187 + * @param string $url
188 + * @param array $params
189 + * @return string
190 + */
191 + public function sign($url, $params = [])
192 + {
193 + return $this->generator->sign($url, $params);
194 + }
195 +
196 + /**
197 + * Validate a URL
198 + *
199 + * @param string $url
200 + * @return mixed (false or array)
201 + */
202 + public function validate($url)
203 + {
204 + return $this->generator->validate($url);
205 + }
206 +
207 + /**
208 + * Helper method for home_url.
209 + *
210 + * @return string
211 + */
212 + public function wp($path = '')
213 + {
214 + $wp = get_option('siteUrl');
215 +
216 + if ($path) {
217 + $wp .= '/' . trim($path, '/');
218 + }
219 +
220 + return $wp;
221 + }
222 +
223 + /**
224 + * Retrieve the wp-content URL.
225 + *
226 + * Note: The wp-content directory is renamable by devs so it's not
227 + * guaranteed to be wp-content, so use this method for safety.
228 + *
229 + * @param string $path
230 + * @return string
231 + */
232 + public function content($path = '')
233 + {
234 + return content_url($path);
235 + }
236 +
237 + /**
238 + * Retrieve the wp-content/plugins URL.
239 + *
240 + * @param string $path
241 + * @return string
242 + */
243 + public function plugins($path = '')
244 + {
245 + return $this->content('/plugins/' . ltrim($path, '/'));
246 + }
247 +
248 + /**
249 + * Retrieve the wp-content/plugins URL.
250 + *
251 + * @param string $path
252 + * @return string
253 + */
254 + public function plugin($path = '')
255 + {
256 + $pluginUrl = rtrim(plugin_dir_url(
257 + App::make('__pluginfile__')
258 + ), '/');
259 +
260 + if ($path) {
261 + $pluginUrl .= '/' . trim($path, '/');
262 + }
263 +
264 + return $pluginUrl;
265 + }
266 +
267 + /**
268 + * Retrieve the wp-content/themes URL.
269 + *
270 + * @param string $path
271 + * @return string
272 + */
273 + public function themes($path = '')
274 + {
275 + return $this->content('/themes/' . ltrim($path, '/'));
276 + }
277 +
278 + /**
279 + * Retrieve the wp-content/uploads URL.
280 + *
281 + * @param string $path
282 + * @return string
283 + */
284 + public function uploads($path = '')
285 + {
286 + return $this->content('/uploads/' . ltrim($path, '/'));
287 + }
288 +
289 + /**
290 + * Retrieve the site/home URL.
291 + *
292 + * @param string $path
293 + * @return string
294 + */
295 + public function home($path = '', $scheme = null)
296 + {
297 + return site_url($path, $scheme);
298 + }
299 +
300 + /**
301 + * Generate a URL from a file path.
302 + *
303 + * @param string $path
304 + * @param bool $checkFile Whether to check if the file exists
305 + * @return string
306 + *
307 + * @phpstan-ignore-next-line
308 + */
309 + public function fromFile(string $path, bool $checkFile = false): string
310 + {
311 + return Util::pathToUrl($path, $checkFile);
312 + }
313 +
314 + /**
315 + * Generate a URL from a named route.
316 + *
317 + * @param string $name
318 + * @param array $params
319 + * @param array $query
320 + * @return string|null
321 + */
322 + public function route($name, $params = [], $query = [])
323 + {
324 + return $this->generator->route($name, $params, $query);
325 + }
326 +
327 + /**
328 + * Return a clone of the URL with a new path.
329 + *
330 + * @param string $path
331 + * @return $this
332 + */
333 + public function withPath($path)
334 + {
335 + $clone = clone $this;
336 + $clone->path = $path;
337 + return $clone;
338 + }
339 +
340 + /**
341 + * Return a clone of the URL with a new query.
342 + *
343 + * @param array|string $query An array of query params or a query string
344 + * @return $this
345 + */
346 + public function withQuery($query)
347 + {
348 + $clone = clone $this;
349 +
350 + if (is_string($query)) {
351 + parse_str($query, $query);
352 + }
353 +
354 + $clone->query = $query;
355 + return $clone;
356 + }
357 +
358 + /**
359 + * Return a clone of the URL with a new fragment.
360 + *
361 + * @param string $fragment
362 + * @return $this
363 + */
364 + public function withFragment($fragment)
365 + {
366 + $clone = clone $this;
367 + $clone->fragment = $fragment;
368 + return $clone;
369 + }
370 +
371 + /**
372 + * Return a clone of the URL with a new scheme.
373 + *
374 + * @param string $scheme
375 + * @return $this
376 + */
377 + public function withScheme($scheme)
378 + {
379 + $clone = clone $this;
380 + $clone->scheme = $scheme;
381 + return $clone;
382 + }
383 +
384 + /**
385 + * Get the URL scheme (e.g., 'http' or 'https').
386 + *
387 + * @return string
388 + */
389 + public function scheme()
390 + {
391 + return $this->scheme;
392 + }
393 +
394 + /**
395 + * Get the URL host.
396 + *
397 + * @return string|null
398 + */
399 + public function host()
400 + {
401 + return $this->host;
402 + }
403 +
404 + /**
405 + * Get the URL port.
406 + *
407 + * @return int|null
408 + */
409 + public function port()
410 + {
411 + return $this->port;
412 + }
413 +
414 + /**
415 + * Get the URL path.
416 + *
417 + * @return string
418 + */
419 + public function path()
420 + {
421 + return $this->path;
422 + }
423 +
424 + /**
425 + * Get the URL query as an array.
426 + *
427 + * @return array
428 + */
429 + public function query()
430 + {
431 + return $this->query;
432 + }
433 +
434 + /**
435 + * Get the URL fragment.
436 + *
437 + * @return string|null
438 + */
439 + public function fragment()
440 + {
441 + return $this->fragment;
442 + }
443 +
444 + /**
445 + * Get the URL pass.
446 + *
447 + * @return string|null
448 + */
449 + public function pass()
450 + {
451 + return $this->pass;
452 + }
453 +
454 + /**
455 + * Get the URL user.
456 + *
457 + * @return string
458 + */
459 + public function user()
460 + {
461 + return $this->user;
462 + }
463 +
464 + /**
465 + * Returns the string representation of the URL object.
466 + *
39 467 * @return string Current URL.
40 468 */
41 469 public function __toString()
42 470 {
43 - return $this->current();
471 + $url = '';
472 +
473 + if ($this->scheme) {
474 + $url .= "{$this->scheme}://";
475 + }
476 +
477 + if ($this->user) {
478 + $url .= $this->user;
479 + if ($this->pass) {
480 + $url .= ":{$this->pass}";
481 + }
482 + $url .= '@';
483 + }
484 +
485 + if ($this->host) {
486 + $url .= $this->host;
487 + }
488 +
489 + if ($this->port) {
490 + $url .= ":{$this->port}";
491 + }
492 +
493 + if ($this->path !== null) {
494 + $url .= $this->path === '' || str_starts_with($this->path, '/')
495 + ? $this->path
496 + : '/' . $this->path;
497 + }
498 +
499 + if (!empty($this->query)) {
500 + $url .= '?' . http_build_query(
501 + $this->query, '', '&', PHP_QUERY_RFC3986
502 + );
503 + }
504 +
505 + if ($this->fragment) {
506 + $url .= "#{$this->fragment}";
507 + }
508 +
509 + return $url;
44 510 }
45 511 }