1 | <?php |
||
2 | |||
3 | /** |
||
4 | * This file is part of Cecil. |
||
5 | * |
||
6 | * (c) Arnaud Ligny <[email protected]> |
||
7 | * |
||
8 | * For the full copyright and license information, please view the LICENSE |
||
9 | * file that was distributed with this source code. |
||
10 | */ |
||
11 | |||
12 | declare(strict_types=1); |
||
13 | |||
14 | namespace Cecil; |
||
15 | |||
16 | use Cecil\Assets\Asset; |
||
17 | use Cecil\Builder; |
||
18 | use Cecil\Collection\Menu\Entry as MenuEntry; |
||
19 | use Cecil\Collection\Page\Page; |
||
20 | use Cecil\Config; |
||
21 | use Cecil\Renderer\Page as PageRenderer; |
||
22 | use Cecil\Util; |
||
23 | use Cocur\Slugify\Slugify; |
||
24 | |||
25 | /** |
||
26 | * URL class. |
||
27 | * |
||
28 | * Builds an URL from a Page, a Menu Entry, an Asset or a string. |
||
29 | */ |
||
30 | class Url |
||
31 | { |
||
32 | /** @var Builder */ |
||
33 | protected $builder; |
||
34 | |||
35 | /** @var Config */ |
||
36 | protected $config; |
||
37 | |||
38 | /** @var string */ |
||
39 | protected $url; |
||
40 | |||
41 | /** @var Page Slugifier */ |
||
42 | private static $slugifier; |
||
43 | |||
44 | /** |
||
45 | * Creates an URL from a Page, a Menu Entry, an Asset or a string. |
||
46 | * |
||
47 | * @param Builder $builder |
||
48 | * @param Page|MenuEntry|Asset|string|null $value |
||
49 | * @param array|null $options Rendering options, e.g.: ['canonical' => true, 'format' => 'html', 'language' => 'fr'] |
||
50 | */ |
||
51 | 1 | public function __construct(Builder $builder, $value, ?array $options = null) |
|
52 | { |
||
53 | 1 | $this->builder = $builder; |
|
54 | 1 | $this->config = $builder->getConfig(); |
|
55 | 1 | if (!self::$slugifier instanceof Slugify) { |
|
0 ignored issues
–
show
introduced
by
![]() |
|||
56 | 1 | self::$slugifier = Slugify::create(['regexp' => Page::SLUGIFY_PATTERN]); |
|
0 ignored issues
–
show
It seems like
Cocur\Slugify\Slugify::c...Page::SLUGIFY_PATTERN)) of type Cocur\Slugify\Slugify is incompatible with the declared type Cecil\Collection\Page\Page of property $slugifier .
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.. ![]() |
|||
57 | } |
||
58 | |||
59 | // handles options |
||
60 | 1 | $canonical = null; // if true prefix url with baseurl config |
|
61 | 1 | $format = null; // output format |
|
62 | 1 | $language = null; // force language |
|
63 | 1 | extract(\is_array($options) ? $options : [], EXTR_IF_EXISTS); |
|
64 | |||
65 | // canonical URL? |
||
66 | 1 | $base = ''; |
|
67 | 1 | if ($this->config->isEnabled('canonicalurl') || $canonical === true) { |
|
68 | 1 | $base = rtrim((string) $this->config->get('baseurl'), '/'); |
|
69 | } |
||
70 | 1 | if ($canonical === false) { |
|
71 | 1 | $base = ''; |
|
72 | } |
||
73 | |||
74 | // if value is empty (i.e.: `url()`) returns home URL |
||
75 | 1 | if (\is_null($value) || empty($value) || $value == '/') { |
|
76 | 1 | $this->url = $base . '/'; |
|
77 | |||
78 | 1 | return; |
|
79 | } |
||
80 | |||
81 | switch (true) { |
||
82 | 1 | case $value instanceof Page: // $value is a Page |
|
83 | /** @var Page $value */ |
||
84 | 1 | if (!$format) { |
|
85 | 1 | $format = $value->getVariable('output'); |
|
86 | 1 | if (\is_array($value->getVariable('output'))) { |
|
87 | 1 | $default = array_search('html', $value->getVariable('output')) ?: 0; |
|
88 | 1 | $format = $value->getVariable('output')[$default]; |
|
89 | } |
||
90 | 1 | if (!$format) { |
|
91 | 1 | $format = 'html'; |
|
92 | } |
||
93 | } |
||
94 | 1 | $this->url = $base . '/' . ltrim((new PageRenderer($this->config))->getUrl($value, $format), '/'); |
|
95 | 1 | if ($canonical && $value->hasVariable('canonical') && $value->getVariable('canonical')['url']) { // canonical URL |
|
96 | $this->url = $value->getVariable('canonical')['url']; |
||
97 | } |
||
98 | 1 | break; |
|
99 | 1 | case $value instanceof MenuEntry: // $value is a Menu Entry |
|
100 | /** @var MenuEntry $value */ |
||
101 | if (Util\File::isRemote($value['url'])) { |
||
102 | $this->url = $value['url']; |
||
103 | break; |
||
104 | } |
||
105 | $this->url = $base . '/' . ltrim($value['url'], '/'); |
||
106 | break; |
||
107 | 1 | case $value instanceof Asset: // $value is an Asset |
|
108 | /** @var Asset $value */ |
||
109 | 1 | $this->url = $base . '/' . ltrim($value['path'], '/'); |
|
110 | 1 | if ($value->isImageInCdn()) { |
|
111 | $this->url = (string) $value; |
||
112 | } |
||
113 | 1 | break; |
|
114 | 1 | case \is_string($value): // others cases |
|
115 | /** @var string $value */ |
||
116 | // $value is a potential Page ID |
||
117 | 1 | $pageId = self::$slugifier->slugify($value); |
|
118 | // should force language? |
||
119 | 1 | $lang = ''; |
|
120 | 1 | if ($language !== null && $language != $this->config->getLanguageDefault()) { |
|
121 | 1 | $pageId = "$language/$pageId"; |
|
122 | 1 | $lang = "$language/"; |
|
123 | } |
||
124 | switch (true) { |
||
125 | 1 | case Util\File::isRemote($value): // $value is an external URL |
|
126 | 1 | $this->url = $value; |
|
127 | 1 | break; |
|
128 | 1 | case $this->builder->getPages()->has($pageId): // $pageId exists in pages collection |
|
129 | 1 | $this->url = (string) new self($this->builder, $this->builder->getPages()->get($pageId), $options); |
|
130 | 1 | break; |
|
131 | default: |
||
132 | // remove double language prefix |
||
133 | 1 | if ($lang && Util\Str::startsWith($value, $lang)) { |
|
134 | 1 | $value = substr($value, \strlen($lang)); |
|
135 | } |
||
136 | 1 | $this->url = $base . '/' . $lang . ltrim($value, '/'); |
|
137 | } |
||
138 | } |
||
139 | } |
||
140 | |||
141 | /** |
||
142 | * If called like a string returns built URL. |
||
143 | */ |
||
144 | 1 | public function __toString(): string |
|
145 | { |
||
146 | 1 | return $this->getUrl(); |
|
147 | } |
||
148 | |||
149 | /** |
||
150 | * Returns built URL. |
||
151 | */ |
||
152 | 1 | public function getUrl(): string |
|
153 | { |
||
154 | 1 | return (string) $this->url; |
|
155 | } |
||
156 | } |
||
157 |