Completed
Push — develop ( 914305...389adb )
by Tino
05:10
created

MetaStatements::addSelfReferencingCanonical()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 7
nc 4
nop 0
dl 0
loc 13
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * Copyright (c) by the ACP3 Developers.
5
 * See the LICENSE file at the top-level module directory for licensing details.
6
 */
7
8
namespace ACP3\Modules\ACP3\Seo\Helper;
9
10
use ACP3\Core\Controller\AreaEnum;
11
use ACP3\Core\Http\RequestInterface;
12
use ACP3\Core\Modules;
13
use ACP3\Core\Router\RouterInterface;
14
use ACP3\Core\Settings\SettingsInterface;
15
use ACP3\Modules\ACP3\Seo\Cache as SeoCache;
16
use ACP3\Modules\ACP3\Seo\Installer\Schema;
17
18
class MetaStatements
19
{
20
    /**
21
     * @var \ACP3\Core\Http\RequestInterface
22
     */
23
    protected $request;
24
    /**
25
     * @var RouterInterface
26
     */
27
    private $router;
28
    /**
29
     * @var \ACP3\Core\Modules
30
     */
31
    private $modules;
32
    /**
33
     * @var \ACP3\Core\Settings\SettingsInterface
34
     */
35
    protected $config;
36
    /**
37
     * @var \ACP3\Modules\ACP3\Seo\Cache
38
     */
39
    protected $seoCache;
40
41
    /**
42
     * @var null|array
43
     */
44
    protected $aliasesCache;
45
    /**
46
     * @var string
47
     */
48
    protected $nextPage = '';
49
    /**
50
     * @var string
51
     */
52
    protected $previousPage = '';
53
    /**
54
     * @var string
55
     */
56
    protected $canonicalUrl = '';
57
    /**
58
     * @var string
59
     */
60
    protected $metaDescriptionPostfix = '';
61
    /**
62
     * @var string
63
     */
64
    private $metaRobots = '';
65
66
    private static $robotSettingsMaps = [
67
        1 => 'index,follow',
68
        2 => 'index,nofollow',
69
        3 => 'noindex,follow',
70
        4 => 'noindex,nofollow',
71
    ];
72
73
    /**
74
     * MetaStatements constructor.
75
     *
76
     * @param \ACP3\Core\Http\RequestInterface      $request
77
     * @param RouterInterface                       $router
78
     * @param Modules                               $modules
79
     * @param \ACP3\Modules\ACP3\Seo\Cache          $seoCache
80
     * @param \ACP3\Core\Settings\SettingsInterface $config
81
     */
82
    public function __construct(
83
        RequestInterface $request,
84
        RouterInterface $router,
85
        Modules $modules,
86
        SeoCache $seoCache,
87
        SettingsInterface $config
88
    ) {
89
        $this->request = $request;
90
        $this->seoCache = $seoCache;
91
        $this->config = $config;
92
        $this->router = $router;
93
        $this->modules = $modules;
94
    }
95
96
    /**
97
     * @param string $metaRobots
98
     *
99
     * @return $this
100
     */
101
    public function setPageRobotsSettings(string $metaRobots)
102
    {
103
        $this->metaRobots = $metaRobots;
104
105
        return $this;
106
    }
107
108
    /**
109
     * Returns the meta tags of the current page.
110
     *
111
     * @return array
112
     */
113
    public function getMetaTags(): array
114
    {
115
        if ($this->modules->isActive(Schema::MODULE_NAME) === false) {
116
            return [];
117
        }
118
119
        $this->addSelfReferencingCanonical();
120
121
        return [
122
            'description' => $this->isInAdmin() ? '' : $this->getPageDescription(),
123
            'keywords' => $this->isInAdmin() ? '' : $this->getPageKeywords(),
124
            'robots' => $this->isInAdmin() ? 'noindex,nofollow' : $this->getPageRobotsSetting(),
125
            'previous_page' => $this->previousPage,
126
            'next_page' => $this->nextPage,
127
            'canonical' => $this->canonicalUrl,
128
        ];
129
    }
130
131
    private function addSelfReferencingCanonical(): void
132
    {
133
        if ($this->isInAdmin()) {
134
            return;
135
        }
136
        if (!empty($this->canonicalUrl)) {
137
            return;
138
        }
139
        if (\strpos($this->request->getQuery(), 'errors/') === 0) {
140
            return;
141
        }
142
143
        $this->canonicalUrl = $this->router->route($this->request->getQuery());
144
    }
145
146
    /**
147
     * @return bool
148
     */
149
    private function isInAdmin(): bool
150
    {
151
        return $this->request->getArea() === AreaEnum::AREA_ADMIN;
152
    }
153
154
    /**
155
     * Returns the SEO description of the current page.
156
     *
157
     * @return string
158
     */
159
    public function getPageDescription(): string
160
    {
161
        $description = $this->getDescription($this->request->getUriWithoutPages());
162
        if (empty($description)) {
163
            $description = $this->getDescription($this->request->getFullPath());
164
        }
165
        if (empty($description)) {
166
            $description = $this->getDescription($this->request->getModule());
167
        }
168
        if (empty($description)) {
169
            $description = $this->getSeoSettings()['meta_description'];
170
        }
171
172
        $postfix = '';
173
        if (!empty($description) && !empty($this->metaDescriptionPostfix)) {
174
            $postfix .= ' - ' . $this->metaDescriptionPostfix;
175
        }
176
177
        return $description . $postfix;
178
    }
179
180
    /**
181
     * @return array
182
     */
183
    protected function getSeoSettings(): array
184
    {
185
        return $this->config->getSettings(Schema::MODULE_NAME);
186
    }
187
188
    /**
189
     * Returns the SEO description of the given page.
190
     *
191
     * @param string $path
192
     *
193
     * @return string
194
     */
195
    public function getDescription(string $path): string
196
    {
197
        return $this->getSeoInformation($path, 'description');
198
    }
199
200
    /**
201
     * Returns the SEO keywords of the current page.
202
     *
203
     * @return string
204
     */
205
    public function getPageKeywords(): string
206
    {
207
        $keywords = $this->getKeywords($this->request->getUriWithoutPages());
208
        if (empty($keywords)) {
209
            $keywords = $this->getKeywords($this->request->getFullPath());
210
        }
211
        if (empty($keywords)) {
212
            $keywords = $this->getKeywords($this->request->getModule());
213
        }
214
215
        return \strtolower(!empty($keywords) ? $keywords : $this->getSeoSettings()['meta_keywords']);
216
    }
217
218
    /**
219
     * Returns the SEO keywords of the given page.
220
     *
221
     * @param string $path
222
     *
223
     * @return string
224
     */
225
    public function getKeywords(string $path): string
226
    {
227
        return $this->getSeoInformation($path, 'keywords');
228
    }
229
230
    /**
231
     * Returns the meta title of the given page.
232
     *
233
     * @param string $path
234
     *
235
     * @return string
236
     */
237
    public function getTitle(string $path): string
238
    {
239
        return $this->getSeoInformation($path, 'title');
240
    }
241
242
    /**
243
     * @param string $path
244
     * @param string $key
245
     * @param string $defaultValue
246
     *
247
     * @return string
248
     */
249
    public function getSeoInformation(string $path, string $key, string $defaultValue = ''): string
250
    {
251
        if (!$this->modules->isActive(Schema::MODULE_NAME)) {
252
            return '';
253
        }
254
255
        // Lazy load the cache
256
        if ($this->aliasesCache === null) {
257
            $this->aliasesCache = $this->seoCache->getCache();
258
        }
259
260
        $path .= !\preg_match('/\/$/', $path) ? '/' : '';
261
262
        return !empty($this->aliasesCache[$path][$key]) ? $this->aliasesCache[$path][$key] : $defaultValue;
263
    }
264
265
    /**
266
     * Returns the SEO robots setting for the current page.
267
     *
268
     * @return string
269
     */
270
    public function getPageRobotsSetting(): string
271
    {
272
        if (!empty($this->metaRobots)) {
273
            return $this->metaRobots;
274
        }
275
276
        $robots = $this->getRobotsSetting($this->request->getUriWithoutPages());
277
        if (empty($robots)) {
278
            $robots = $this->getRobotsSetting($this->request->getFullPath());
279
        }
280
        if (empty($robots)) {
281
            $robots = $this->getRobotsSetting($this->request->getModule());
282
        }
283
284
        return \strtolower(!empty($robots) ? $robots : $this->getRobotsSetting());
285
    }
286
287
    /**
288
     * Returns the SEO robots settings for the given page.
289
     *
290
     * @param string $path
291
     *
292
     * @return string
293
     */
294
    public function getRobotsSetting(string $path = ''): string
295
    {
296
        if ($path === '') {
297
            return \strtr($this->getSeoSettings()['robots'], $this->getRobotsMap());
298
        }
299
300
        $robot = $this->getSeoInformation($path, 'robots', 0);
301
302
        if ($robot == 0) {
303
            $robot = $this->getSeoSettings()['robots'];
304
        }
305
306
        return \strtr($robot, $this->getRobotsMap());
307
    }
308
309
    public function getRobotsMap(): array
310
    {
311
        return self::$robotSettingsMaps;
312
    }
313
314
    /**
315
     * Sets a SEO description postfix for te current page.
316
     *
317
     * @param string $value
318
     *
319
     * @return $this
320
     */
321
    public function setDescriptionPostfix(string $value)
322
    {
323
        $this->metaDescriptionPostfix = $value;
324
325
        return $this;
326
    }
327
328
    /**
329
     * Sets the canonical URL for the current page.
330
     *
331
     * @param string $path
332
     *
333
     * @return $this
334
     */
335
    public function setCanonicalUri(string $path)
336
    {
337
        $this->canonicalUrl = $path;
338
339
        return $this;
340
    }
341
342
    /**
343
     * Sets the next page (useful for pagination).
344
     *
345
     * @param string $path
346
     *
347
     * @return $this
348
     */
349
    public function setNextPage(string $path)
350
    {
351
        $this->nextPage = $path;
352
353
        return $this;
354
    }
355
356
    /**
357
     * Sets the previous page (useful for pagination).
358
     *
359
     * @param string $path
360
     *
361
     * @return $this
362
     */
363
    public function setPreviousPage(string $path)
364
    {
365
        $this->previousPage = $path;
366
367
        return $this;
368
    }
369
}
370