1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Frontend\Core\Header; |
4
|
|
|
|
5
|
|
|
use Common\Core\Header\Asset; |
6
|
|
|
use Common\Core\Header\AssetCollection; |
7
|
|
|
use Common\Core\Header\JsData; |
8
|
|
|
use Common\Core\Header\Minifier; |
9
|
|
|
use Common\Core\Header\Priority; |
10
|
|
|
use ForkCMS\App\KernelLoader; |
11
|
|
|
use ForkCMS\Google\TagManager\TagManager; |
12
|
|
|
use ForkCMS\Privacy\ConsentDialog; |
13
|
|
|
use Frontend\Core\Engine\Model; |
14
|
|
|
use Frontend\Core\Engine\Theme; |
15
|
|
|
use Frontend\Core\Engine\TwigTemplate; |
16
|
|
|
use Frontend\Core\Engine\Url; |
17
|
|
|
use Frontend\Core\Language\Locale; |
18
|
|
|
use Symfony\Component\HttpKernel\KernelInterface; |
19
|
|
|
|
20
|
|
|
/** |
21
|
|
|
* This class will be used to alter the head-part of the HTML-document that will be created by the frontend |
22
|
|
|
* Therefore it will handle meta-stuff (title, including JS, including CSS, ...) |
23
|
|
|
*/ |
24
|
|
|
class Header extends KernelLoader |
25
|
|
|
{ |
26
|
|
|
/** |
27
|
|
|
* The canonical URL |
28
|
|
|
* |
29
|
|
|
* @var string |
30
|
|
|
*/ |
31
|
|
|
private $canonical; |
32
|
|
|
|
33
|
|
|
/** |
34
|
|
|
* The added css-files |
35
|
|
|
* |
36
|
|
|
* @var AssetCollection |
37
|
|
|
*/ |
38
|
|
|
private $cssFiles; |
39
|
|
|
|
40
|
|
|
/** |
41
|
|
|
* Data that will be passed to js |
42
|
|
|
* |
43
|
|
|
* @var JsData |
44
|
|
|
*/ |
45
|
|
|
private $jsData; |
46
|
|
|
|
47
|
|
|
/** |
48
|
|
|
* The added js-files |
49
|
|
|
* |
50
|
|
|
* @var AssetCollection |
51
|
|
|
*/ |
52
|
|
|
private $jsFiles; |
53
|
|
|
|
54
|
|
|
/** |
55
|
|
|
* Meta data and links |
56
|
|
|
* |
57
|
|
|
* @var MetaCollection |
58
|
|
|
*/ |
59
|
|
|
private $meta; |
60
|
|
|
|
61
|
|
|
/** |
62
|
|
|
* The custom meta data |
63
|
|
|
* |
64
|
|
|
* @var string |
65
|
|
|
*/ |
66
|
|
|
private $metaCustom = ''; |
67
|
|
|
|
68
|
|
|
/** |
69
|
|
|
* Page title |
70
|
|
|
* |
71
|
|
|
* @var string |
72
|
|
|
*/ |
73
|
|
|
private $pageTitle; |
74
|
|
|
|
75
|
|
|
/** |
76
|
|
|
* Content title |
77
|
|
|
* |
78
|
|
|
* @var string |
79
|
|
|
*/ |
80
|
|
|
private $contentTitle; |
81
|
|
|
|
82
|
|
|
/** |
83
|
|
|
* TwigTemplate instance |
84
|
|
|
* |
85
|
|
|
* @var TwigTemplate |
86
|
|
|
*/ |
87
|
|
|
protected $template; |
88
|
|
|
|
89
|
|
|
/** |
90
|
|
|
* URL instance |
91
|
|
|
* |
92
|
|
|
* @var Url |
93
|
|
|
*/ |
94
|
|
|
protected $url; |
95
|
|
|
|
96
|
26 |
|
public function __construct(KernelInterface $kernel) |
97
|
|
|
{ |
98
|
26 |
|
parent::__construct($kernel); |
99
|
|
|
|
100
|
26 |
|
$container = $this->getContainer(); |
101
|
26 |
|
$container->set('header', $this); |
102
|
|
|
|
103
|
26 |
|
$this->template = $container->get('templating'); |
104
|
26 |
|
$this->url = $container->get('url'); |
105
|
|
|
|
106
|
26 |
|
$this->cssFiles = new AssetCollection( |
107
|
26 |
|
Minifier::css( |
108
|
26 |
|
$container->getParameter('site.path_www'), |
109
|
26 |
|
FRONTEND_CACHE_URL . '/MinifiedCss/', |
110
|
26 |
|
FRONTEND_CACHE_PATH . '/MinifiedCss/' |
111
|
|
|
) |
112
|
|
|
); |
113
|
26 |
|
$this->jsFiles = new AssetCollection( |
114
|
26 |
|
Minifier::js( |
115
|
26 |
|
$container->getParameter('site.path_www'), |
116
|
26 |
|
FRONTEND_CACHE_URL . '/MinifiedJs/', |
117
|
26 |
|
FRONTEND_CACHE_PATH . '/MinifiedJs/' |
118
|
|
|
) |
119
|
|
|
); |
120
|
|
|
|
121
|
|
|
$jsData = [ |
122
|
26 |
|
'LANGUAGE' => Locale::frontendLanguage(), |
123
|
26 |
|
'privacyConsent' => $this->get(ConsentDialog::class)->getJsData(), |
124
|
|
|
]; |
125
|
26 |
|
$this->jsData = new JsData($jsData); |
126
|
|
|
|
127
|
26 |
|
$this->meta = new MetaCollection(); |
128
|
|
|
|
129
|
|
|
// add some default CSS files |
130
|
26 |
|
$this->addCSS('/src/Frontend/Core/Layout/Css/screen.css'); |
131
|
|
|
|
132
|
|
|
// debug stylesheet |
133
|
26 |
|
if ($container->getParameter('kernel.debug')) { |
134
|
26 |
|
$this->addCSS('/src/Frontend/Core/Layout/Css/debug.css', true, false, Priority::debug()); |
135
|
|
|
} |
136
|
|
|
|
137
|
|
|
// add default javascript-files |
138
|
26 |
|
$this->addJS('/js/vendors/jquery.min.js', false, false, Priority::core()); |
139
|
26 |
|
$this->addJS('/src/Frontend/Core/Js/jquery/jquery.frontend.js', true, false, Priority::core()); |
140
|
26 |
|
$this->addJS('/src/Frontend/Core/Js/utils.js', true, false, Priority::core()); |
141
|
26 |
|
$this->addJS('/src/Frontend/Core/Js/frontend.js', true, false, Priority::core()); |
142
|
26 |
|
} |
143
|
|
|
|
144
|
|
|
/** |
145
|
|
|
* Add a CSS file into the array |
146
|
|
|
* |
147
|
|
|
* @param string $file The path for the CSS-file that should be loaded. |
148
|
|
|
* @param bool $minify Should the CSS be minified? |
149
|
|
|
* @param bool $addTimestamp May we add a timestamp for caching purposes? |
150
|
|
|
* @param Priority|null $priority Provides a way to change the order that things are loaded |
151
|
|
|
*/ |
152
|
26 |
|
public function addCSS( |
153
|
|
|
string $file, |
154
|
|
|
bool $minify = true, |
155
|
|
|
bool $addTimestamp = false, |
156
|
|
|
Priority $priority = null |
157
|
|
|
): void { |
158
|
26 |
|
$isExternalUrl = $this->get('fork.validator.url')->isExternalUrl($file); |
159
|
26 |
|
$file = $isExternalUrl ? $file : Theme::getPath($file); |
160
|
26 |
|
$minify = $minify && !$isExternalUrl; |
161
|
|
|
|
162
|
26 |
|
$this->cssFiles->add(new Asset($file, $addTimestamp, $priority), $minify); |
163
|
26 |
|
} |
164
|
|
|
|
165
|
|
|
/** |
166
|
|
|
* Add a javascript file into the array |
167
|
|
|
* |
168
|
|
|
* @param string $file The path to the javascript-file that should be loaded. |
169
|
|
|
* @param bool $minify Should the javascript be minified? |
170
|
|
|
* @param bool $addTimestamp May we add a timestamp for caching purposes? |
171
|
|
|
* @param Priority|null $priority Provides a way to change the order that things are loaded |
172
|
|
|
*/ |
173
|
26 |
|
public function addJS( |
174
|
|
|
string $file, |
175
|
|
|
bool $minify = true, |
176
|
|
|
bool $addTimestamp = false, |
177
|
|
|
Priority $priority = null |
178
|
|
|
): void { |
179
|
26 |
|
$isExternalUrl = $this->get('fork.validator.url')->isExternalUrl($file); |
180
|
26 |
|
$file = $isExternalUrl ? $file : Theme::getPath($file); |
181
|
26 |
|
$minify = $minify && !$isExternalUrl; |
182
|
|
|
|
183
|
26 |
|
$this->jsFiles->add(new Asset($file, $addTimestamp, $priority), $minify); |
184
|
26 |
|
} |
185
|
|
|
|
186
|
|
|
/** |
187
|
|
|
* Add data into the jsData |
188
|
|
|
* |
189
|
|
|
* @param string $module The name of the module. |
190
|
|
|
* @param string $key The key whereunder the value will be stored. |
191
|
|
|
* @param mixed $value The value |
192
|
|
|
*/ |
193
|
|
|
public function addJsData(string $module, string $key, $value): void |
194
|
|
|
{ |
195
|
|
|
$this->jsData->add($module, $key, $value); |
196
|
|
|
} |
197
|
|
|
|
198
|
|
|
/** |
199
|
|
|
* @param array $attributes The attributes to parse. |
200
|
|
|
* @param bool $overwrite Should we overwrite the current value? |
201
|
|
|
* @param string[] $uniqueAttributeKeys Which keys can we use to decide if an item is unique. |
202
|
|
|
*/ |
203
|
|
|
public function addLink( |
204
|
|
|
array $attributes, |
205
|
|
|
bool $overwrite = false, |
206
|
|
|
array $uniqueAttributeKeys = ['rel', 'hreflang', 'type', 'title'] |
207
|
|
|
): void { |
208
|
|
|
if (!isset($attributes['href']) || empty($attributes['href'])) { |
209
|
|
|
return; |
210
|
|
|
} |
211
|
|
|
$href = $attributes['href']; |
212
|
|
|
unset($attributes['href']); |
213
|
|
|
|
214
|
|
|
$this->meta->addMetaLink(new MetaLink($href, $attributes, $uniqueAttributeKeys), $overwrite); |
215
|
|
|
} |
216
|
|
|
|
217
|
|
|
/** |
218
|
|
|
* @param array $attributes The attributes to parse. |
219
|
|
|
* @param bool $overwrite Should we overwrite the current value? |
220
|
|
|
* @param array $uniqueAttributeKeys Which keys can we use to decide if an item is unique. |
221
|
|
|
* @param string $uniqueKeySuffix This additional key helps you to create your own custom unique keys if required. |
222
|
|
|
*/ |
223
|
2 |
|
public function addMetaData( |
224
|
|
|
array $attributes, |
225
|
|
|
bool $overwrite = false, |
226
|
|
|
array $uniqueAttributeKeys = ['name'], |
227
|
|
|
string $uniqueKeySuffix = null |
228
|
|
|
): void { |
229
|
2 |
|
if (!isset($attributes['content']) || $attributes['content'] === '') { |
230
|
|
|
return; |
231
|
|
|
} |
232
|
|
|
|
233
|
2 |
|
$content = $attributes['content']; |
234
|
2 |
|
unset($attributes['content']); |
235
|
|
|
|
236
|
2 |
|
$this->meta->addMetaData( |
237
|
2 |
|
new MetaData($content, $attributes, $uniqueAttributeKeys, $uniqueKeySuffix), |
238
|
2 |
|
$overwrite |
239
|
|
|
); |
240
|
2 |
|
} |
241
|
|
|
|
242
|
|
|
/** |
243
|
|
|
* Add meta-description, somewhat a shortcut for the addMetaData-method |
244
|
|
|
* |
245
|
|
|
* @param string $metaDescription The description. |
246
|
|
|
* @param bool $overwrite Should we overwrite the previous value? |
247
|
|
|
*/ |
248
|
26 |
|
public function addMetaDescription(string $metaDescription, bool $overwrite = false): void |
249
|
|
|
{ |
250
|
26 |
|
$this->meta->addMetaData(MetaData::forName('description', $metaDescription), $overwrite); |
251
|
26 |
|
} |
252
|
|
|
|
253
|
|
|
/** |
254
|
|
|
* Add meta-keywords, somewhat a shortcut for the addMetaData-method |
255
|
|
|
* |
256
|
|
|
* @param string $metaKeywords The keywords. |
257
|
|
|
* @param bool $overwrite Should we overwrite the previous value? |
258
|
|
|
*/ |
259
|
26 |
|
public function addMetaKeywords(string $metaKeywords, bool $overwrite = false): void |
260
|
|
|
{ |
261
|
26 |
|
$this->meta->addMetaData(MetaData::forName('keywords', $metaKeywords), $overwrite); |
262
|
26 |
|
} |
263
|
|
|
|
264
|
|
|
/** |
265
|
|
|
* @param string $property The key (without og:). |
266
|
|
|
* @param string $openGraphData The value. |
267
|
|
|
* @param bool $overwrite Should we overwrite the previous value? |
268
|
|
|
*/ |
269
|
2 |
|
public function addOpenGraphData(string $property, string $openGraphData, bool $overwrite = false): void |
270
|
|
|
{ |
271
|
2 |
|
$this->meta->addMetaData(MetaData::forProperty('og:' . $property, $openGraphData), $overwrite); |
272
|
2 |
|
} |
273
|
|
|
|
274
|
|
|
public function addOpenGraphImage($image, bool $overwrite = false, int $width = 0, int $height = 0): void |
275
|
|
|
{ |
276
|
|
|
// remove site url from path |
277
|
|
|
$image = str_replace(SITE_URL, '', $image); |
278
|
|
|
|
279
|
|
|
// check if it no longer points to an absolute uri |
280
|
|
|
if (!$this->getContainer()->get('fork.validator.url')->isExternalUrl($image)) { |
281
|
|
|
if (!is_file(PATH_WWW . strtok($image, '?'))) { |
282
|
|
|
return; |
283
|
|
|
} |
284
|
|
|
$image = SITE_URL . $image; |
285
|
|
|
} |
286
|
|
|
|
287
|
|
|
$this->meta->addMetaData(MetaData::forProperty('og:image', $image, ['property', 'content']), $overwrite); |
288
|
|
|
if (SITE_PROTOCOL === 'https') { |
289
|
|
|
$this->meta->addMetaData( |
290
|
|
|
MetaData::forProperty('og:image:secure_url', $image, ['property', 'content']), |
291
|
|
|
$overwrite |
292
|
|
|
); |
293
|
|
|
} |
294
|
|
|
|
295
|
|
|
if ($width !== 0) { |
296
|
|
|
$this->meta->addMetaData( |
297
|
|
|
MetaData::forProperty('og:image:width', $width, ['property', 'content']), |
298
|
|
|
$overwrite |
299
|
|
|
); |
300
|
|
|
} |
301
|
|
|
|
302
|
|
|
if ($height !== 0) { |
303
|
|
|
$this->meta->addMetaData( |
304
|
|
|
MetaData::forProperty('og:image:height', $height, ['property', 'content']), |
305
|
|
|
$overwrite |
306
|
|
|
); |
307
|
|
|
} |
308
|
|
|
} |
309
|
|
|
|
310
|
8 |
|
public function addRssLink(string $title, string $link): void |
311
|
|
|
{ |
312
|
8 |
|
$this->meta->addMetaLink(MetaLink::rss($link, $title), true); |
313
|
8 |
|
} |
314
|
|
|
|
315
|
|
|
/** |
316
|
|
|
* Extract images from content that can be added add Open Graph image |
317
|
|
|
* |
318
|
|
|
* @param string $content The content (where from to extract the images). |
319
|
|
|
*/ |
320
|
2 |
|
public function extractOpenGraphImages(string $content): void |
321
|
|
|
{ |
322
|
2 |
|
$images = []; |
323
|
|
|
|
324
|
|
|
// check if any img-tags are present in the content |
325
|
2 |
|
if (preg_match_all('/<img.*?src="(.*?)".*?\/>/i', $content, $images)) { |
326
|
|
|
// loop all found images and add to Open Graph metadata |
327
|
|
|
foreach ($images[1] as $image) { |
328
|
|
|
$this->addOpenGraphImage($image); |
329
|
|
|
} |
330
|
|
|
} |
331
|
2 |
|
} |
332
|
|
|
|
333
|
26 |
|
public function getMetaCustom(): string |
334
|
|
|
{ |
335
|
26 |
|
return (string) $this->metaCustom; |
336
|
|
|
} |
337
|
|
|
|
338
|
26 |
|
public function getPageTitle(): string |
339
|
|
|
{ |
340
|
26 |
|
return (string) $this->pageTitle; |
341
|
|
|
} |
342
|
|
|
|
343
|
|
|
/** |
344
|
|
|
* Parse the header into the template |
345
|
|
|
*/ |
346
|
26 |
|
public function parse(): void |
347
|
|
|
{ |
348
|
|
|
// @deprecated remove this in Fork 6, check if this still should be used. |
349
|
26 |
|
$facebook = new Facebook($this->get('fork.settings')); |
|
|
|
|
350
|
26 |
|
$facebook->addOpenGraphMeta($this); |
351
|
26 |
|
$this->parseSeo(); |
352
|
|
|
|
353
|
|
|
// in debug mode we don't want our pages to be indexed. |
354
|
26 |
|
if ($this->getContainer()->getParameter('kernel.debug')) { |
355
|
26 |
|
$this->meta->addMetaData(MetaData::forName('robots', 'noindex, nofollow'), true); |
356
|
|
|
} |
357
|
|
|
|
358
|
26 |
|
$this->template->assignGlobal('meta', $this->meta); |
359
|
26 |
|
$this->template->assignGlobal('metaCustom', $this->getMetaCustom()); |
360
|
26 |
|
$this->cssFiles->parse($this->template, 'cssFiles'); |
361
|
26 |
|
$this->jsFiles->parse($this->template, 'jsFiles'); |
362
|
|
|
|
363
|
26 |
|
$siteHTMLHead = ''; |
364
|
26 |
|
$siteHTMLStartOfBody = ''; |
365
|
|
|
|
366
|
|
|
// Add Google Tag Manager code if needed |
367
|
26 |
|
$googleTagManagerContainerId = $this->get('fork.settings')->get('Core', 'google_tracking_google_tag_manager_container_id', ''); |
368
|
26 |
|
if ($googleTagManagerContainerId !== '') { |
369
|
|
|
$googleTagManager = $this->get(TagManager::class); |
370
|
|
|
$siteHTMLHead .= $googleTagManager->generateHeadCode() . "\n"; |
371
|
|
|
|
372
|
|
|
$siteHTMLStartOfBody .= $googleTagManager->generateStartOfBodyCode() . "\n"; |
373
|
|
|
} |
374
|
|
|
|
375
|
|
|
// Add Google Analytics code if needed |
376
|
26 |
|
$googleAnalyticsTrackingId = $this->get('fork.settings')->get('Core', 'google_tracking_google_analytics_tracking_id', ''); |
377
|
26 |
|
if ($googleAnalyticsTrackingId !== '') { |
378
|
|
|
$siteHTMLHead .= new GoogleAnalytics( |
379
|
|
|
$this->get('fork.settings'), |
|
|
|
|
380
|
|
|
$this->get(ConsentDialog::class), |
|
|
|
|
381
|
|
|
$this->get('fork.cookie') |
|
|
|
|
382
|
|
|
) . "\n"; |
383
|
|
|
} |
384
|
|
|
|
385
|
|
|
// @deprecated fallback to site_html_header as this was used in the past |
386
|
26 |
|
$siteHTMLHead .= (string) $this->get('fork.settings')->get('Core', 'site_html_head', $this->get('fork.settings')->get('Core', 'site_html_header', '')) . "\n"; |
387
|
26 |
|
$siteHTMLHead .= "\n" . $this->jsData; |
388
|
26 |
|
$this->template->assignGlobal('siteHTMLHead', trim($siteHTMLHead)); |
389
|
|
|
|
390
|
|
|
// @deprecated remove this in Fork 6, use siteHTMLHead |
391
|
26 |
|
$this->template->assignGlobal('siteHTMLHeader', trim($siteHTMLHead)); |
392
|
|
|
|
393
|
|
|
// @deprecated fallback to site_start_of_body_scripts as this was used in the pased |
394
|
26 |
|
$siteHTMLStartOfBody .= $this->get('fork.settings')->get('Core', 'site_html_start_of_body', $this->get('fork.settings')->get('Core', 'site_start_of_body_scripts', '')); |
395
|
26 |
|
$this->template->assignGlobal('siteHTMLStartOfBody', trim($siteHTMLStartOfBody)); |
396
|
|
|
|
397
|
26 |
|
$this->template->assignGlobal('pageTitle', $this->getPageTitle()); |
398
|
26 |
|
$this->template->assignGlobal('contentTitle', $this->getContentTitle()); |
399
|
26 |
|
$this->template->assignGlobal( |
400
|
26 |
|
'siteTitle', |
401
|
26 |
|
(string) $this->get('fork.settings')->get('Core', 'site_title_' . LANGUAGE, SITE_DEFAULT_TITLE) |
402
|
|
|
); |
403
|
26 |
|
} |
404
|
|
|
|
405
|
26 |
|
private function getCanonical(): string |
406
|
|
|
{ |
407
|
26 |
|
$queryString = trim($this->url->getQueryString(), '/'); |
408
|
26 |
|
$language = $this->get('fork.settings')->get('Core', 'default_language', SITE_DEFAULT_LANGUAGE); |
409
|
26 |
|
if ($queryString === $language) { |
410
|
|
|
$this->canonical = rtrim(SITE_URL, '/'); |
411
|
|
|
|
412
|
|
|
if ($this->getContainer()->getParameter('site.multilanguage')) { |
413
|
|
|
$this->canonical .= '/' . $language; |
414
|
|
|
} |
415
|
|
|
} |
416
|
|
|
|
417
|
26 |
|
if (!empty($this->canonical)) { |
418
|
6 |
|
return $this->canonical; |
419
|
|
|
} |
420
|
|
|
|
421
|
|
|
// get the chunks of the current url |
422
|
22 |
|
$urlChunks = parse_url($this->url->getQueryString()); |
423
|
|
|
|
424
|
|
|
// a canonical url should contain the domain. So make sure you |
425
|
|
|
// redirect your website to a single url with .htaccess |
426
|
22 |
|
$url = rtrim(SITE_URL, '/'); |
427
|
22 |
|
if (isset($urlChunks['port'])) { |
428
|
|
|
$url .= ':' . $urlChunks['port']; |
429
|
|
|
} |
430
|
22 |
|
if (isset($urlChunks['path'])) { |
431
|
22 |
|
$url .= $urlChunks['path']; |
432
|
|
|
} |
433
|
|
|
|
434
|
|
|
// any items provided through GET? |
435
|
22 |
|
if (!isset($urlChunks['query']) || !Model::getRequest()->query->has('page')) { |
436
|
21 |
|
return $url; |
437
|
|
|
} |
438
|
|
|
|
439
|
3 |
|
return $url . '?page=' . Model::getRequest()->query->get('page'); |
440
|
|
|
} |
441
|
|
|
|
442
|
|
|
/** |
443
|
|
|
* Parse SEO specific data |
444
|
|
|
*/ |
445
|
26 |
|
private function parseSeo(): void |
446
|
|
|
{ |
447
|
26 |
|
if ($this->get('fork.settings')->get('Core', 'seo_noodp', false)) { |
448
|
|
|
$this->meta->addMetaData(MetaData::forName('robots', 'noodp')); |
449
|
|
|
} |
450
|
|
|
|
451
|
26 |
|
if ($this->get('fork.settings')->get('Core', 'seo_noydir', false)) { |
452
|
|
|
$this->meta->addMetaData(MetaData::forName('robots', 'noydir')); |
453
|
|
|
} |
454
|
|
|
|
455
|
26 |
|
$charset = $this->getContainer()->getParameter('kernel.charset'); |
456
|
26 |
|
if ($charset === 'utf-8') { |
457
|
|
|
$this->meta->addMetaLink(MetaLink::canonical(\SpoonFilter::htmlspecialchars($this->getCanonical()))); |
458
|
|
|
|
459
|
|
|
return; |
460
|
|
|
} |
461
|
|
|
|
462
|
26 |
|
$this->meta->addMetaLink(MetaLink::canonical(\SpoonFilter::htmlentities($this->getCanonical()))); |
463
|
26 |
|
} |
464
|
|
|
|
465
|
6 |
|
public function setCanonicalUrl(string $canonicalUrl): void |
466
|
|
|
{ |
467
|
6 |
|
if (strpos($canonicalUrl, '/') === 0) { |
468
|
2 |
|
$canonicalUrl = SITE_URL . $canonicalUrl; |
469
|
|
|
} |
470
|
|
|
|
471
|
6 |
|
$this->canonical = $canonicalUrl; |
472
|
6 |
|
} |
473
|
|
|
|
474
|
26 |
|
public function setMetaCustom(string $meta = null): void |
475
|
|
|
{ |
476
|
26 |
|
$this->metaCustom = $meta; |
477
|
26 |
|
} |
478
|
|
|
|
479
|
26 |
|
public function setContentTitle(string $contentTitle): void |
480
|
|
|
{ |
481
|
26 |
|
$this->contentTitle = $contentTitle; |
482
|
26 |
|
} |
483
|
|
|
|
484
|
26 |
|
public function getContentTitle(): string |
485
|
|
|
{ |
486
|
26 |
|
return $this->contentTitle; |
487
|
|
|
} |
488
|
|
|
|
489
|
|
|
/** |
490
|
|
|
* @param string $value The page title to be set or to be prepended. |
491
|
|
|
* @param bool $overwrite Should the existing page title be overwritten? |
492
|
|
|
*/ |
493
|
26 |
|
public function setPageTitle(string $value, bool $overwrite = false): void |
494
|
|
|
{ |
495
|
26 |
|
$this->setContentTitle($value); |
496
|
|
|
|
497
|
26 |
|
$value = trim($value); |
498
|
|
|
|
499
|
26 |
|
if ($overwrite) { |
500
|
|
|
$this->pageTitle = $value; |
501
|
|
|
|
502
|
|
|
return; |
503
|
|
|
} |
504
|
|
|
|
505
|
26 |
|
if (empty($value)) { |
506
|
|
|
$this->pageTitle = $this->get('fork.settings')->get('Core', 'site_title_' . LANGUAGE, SITE_DEFAULT_TITLE); |
507
|
|
|
|
508
|
|
|
return; |
509
|
|
|
} |
510
|
|
|
|
511
|
26 |
|
if ($this->pageTitle === null || $this->pageTitle === '') { |
512
|
26 |
|
$this->pageTitle = $this->get('fork.settings')->get('Core', 'site_title_' . LANGUAGE, SITE_DEFAULT_TITLE); |
513
|
26 |
|
$this->pageTitle = $value . ' - ' . $this->pageTitle; |
514
|
|
|
|
515
|
26 |
|
return; |
516
|
|
|
} |
517
|
|
|
|
518
|
18 |
|
$this->pageTitle = $value . ' - ' . $this->pageTitle; |
519
|
18 |
|
} |
520
|
|
|
|
521
|
|
|
/** |
522
|
|
|
* @param string $title The title (maximum 70 characters) |
523
|
|
|
* @param string $description A brief description of the card (maximum 200 characters) |
524
|
|
|
* @param string $imageUrl The URL of the image (minimum 280x150 and <1MB) |
525
|
|
|
* @param string $cardType The cardtype, possible types: https://dev.twitter.com/cards/types |
526
|
|
|
* @param string $siteHandle (optional) Twitter handle of the site |
527
|
|
|
* @param string $creatorHandle (optional) Twitter handle of the author |
528
|
|
|
*/ |
529
|
2 |
|
public function setTwitterCard( |
530
|
|
|
string $title, |
531
|
|
|
string $description, |
532
|
|
|
string $imageUrl, |
533
|
|
|
string $cardType = 'summary', |
534
|
|
|
string $siteHandle = null, |
535
|
|
|
string $creatorHandle = null |
536
|
|
|
): void { |
537
|
2 |
|
$this->meta->addMetaData(MetaData::forName('twitter:card', $cardType)); |
538
|
2 |
|
$this->meta->addMetaData(MetaData::forName('twitter:title', $title)); |
539
|
2 |
|
$this->meta->addMetaData(MetaData::forName('twitter:description', $description)); |
540
|
2 |
|
$this->meta->addMetaData(MetaData::forName('twitter:image', $imageUrl)); |
541
|
|
|
|
542
|
2 |
|
if ($siteHandle !== null) { |
543
|
|
|
$this->meta->addMetaData(MetaData::forName('twitter:site', $siteHandle)); |
544
|
|
|
} |
545
|
|
|
|
546
|
2 |
|
if ($creatorHandle !== null) { |
547
|
|
|
$this->meta->addMetaData(MetaData::forName('twitter:creator', $creatorHandle)); |
548
|
|
|
} |
549
|
2 |
|
} |
550
|
|
|
|
551
|
|
|
public function addMetaLink(MetaLink $metaLink, bool $overwrite = false): void |
552
|
|
|
{ |
553
|
|
|
$this->meta->addMetaLink($metaLink, $overwrite); |
554
|
|
|
} |
555
|
|
|
} |
556
|
|
|
|