Issues (281)

Branch: master

src/Backend/Core/Engine/Meta.php (1 issue)

Labels
Severity
1
<?php
2
3
namespace Backend\Core\Engine;
4
5
use Common\Doctrine\Entity\Meta as MetaEntity;
6
use Common\Uri as CommonUri;
7
use Backend\Core\Engine\Model as BackendModel;
8
use Backend\Core\Language\Language as BackendLanguage;
9
10
/**
11
 * This class represents a META-object
12
 *
13
 * @deprecated This class will be removed when all modules run on doctrine and will be replaced with the meta entity
14
 */
15
class Meta
16
{
17
    /**
18
     * The name of the field we should use to generate default-values
19
     *
20
     * @var string
21
     */
22
    protected $baseFieldName;
23
24
    /**
25
     * The callback method
26
     *
27
     * @var array
28
     */
29
    protected $callback = [];
30
31
    /**
32
     * Do we need meta custom
33
     *
34
     * @var bool
35
     */
36
    protected $custom;
37
38
    /**
39
     * The data, when a existing meta-record is loaded
40
     *
41
     * @var array
42
     */
43
    protected $data;
44
45
    /**
46
     * The form instance
47
     *
48
     * @var Form
49
     */
50
    protected $form;
51
52
    /**
53
     * The id, when an existing meta-record is loaded
54
     *
55
     * @var int
56
     */
57
    protected $id;
58
59
    /**
60
     * The URL-instance
61
     *
62
     * @var Url
63
     */
64
    protected $url;
65
66
    /**
67
     * @param Form $form An instance of Form, the elements will be parsed in here.
68
     * @param int $metaId The metaID to load.
69
     * @param string $baseFieldName The field where the URL should be based on.
70
     * @param bool $showCustomMeta Add/show custom-meta.
71
     *
72
     * @throws Exception
73
     */
74 5
    public function __construct(
75
        Form $form,
76
        int $metaId = null,
77
        string $baseFieldName = 'title',
78
        bool $showCustomMeta = false
79
    ) {
80
        // check if URL is available from the reference
81 5
        if (!BackendModel::getContainer()->has('url')) {
82
            throw new Exception('url service should be available in the container.');
83
        }
84
85
        // get BackendURL instance
86 5
        $this->url = BackendModel::getContainer()->get('url');
87
88 5
        $this->custom = $showCustomMeta;
89 5
        $this->form = $form;
90 5
        $this->baseFieldName = $baseFieldName;
91
92
        // metaId was specified, so we should load the item
93 5
        if ($metaId !== null) {
94 5
            $this->loadMeta($metaId);
95
        }
96
97
        // set default callback
98 5
        $this->setUrlCallback(
99 5
            'Backend\\Modules\\' . $this->url->getModule() . '\\Engine\\Model',
0 ignored issues
show
The method getModule() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

99
            'Backend\\Modules\\' . $this->url->/** @scrutinizer ignore-call */ getModule() . '\\Engine\\Model',

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
100 5
            'getUrl'
101
        );
102
103
        // load the form
104 5
        $this->loadForm();
105 5
    }
106
107
    /**
108
     * Generate an url, using the predefined callback.
109
     *
110
     * @param string $url The base-url to start from.
111
     *
112
     * @throws Exception When the function does not exist
113
     *
114
     * @return string
115
     *
116
     * @deprecated use the generateUrl method on the meta repository
117
     * This class will be removed when all modules run on doctrine
118
     */
119 1
    public function generateUrl(string $url): string
120
    {
121 1
        return Model::get('fork.repository.meta')->generateUrl(
122 1
            $url,
123 1
            $this->callback['class'],
124 1
            $this->callback['method'],
125 1
            $this->callback['parameters']
126
        );
127
    }
128
129
    public function getDescription(): ?string
130
    {
131
        // not set so return null
132
        if (!isset($this->data['description'])) {
133
            return null;
134
        }
135
136
        // return value
137
        return $this->data['description'];
138
    }
139
140
    public function getDescriptionOverwrite(): ?bool
141
    {
142
        // not set so return null
143
        if (!isset($this->data['description_overwrite'])) {
144
            return null;
145
        }
146
147
        // return value
148
        return (bool) $this->data['description_overwrite'];
149
    }
150
151
    public function getId(): ?int
152
    {
153
        // not set so return null
154
        if (!isset($this->data['id'])) {
155
            return null;
156
        }
157
158
        // return value
159
        return (int) $this->data['id'];
160
    }
161
162
    public function getKeywords(): ?string
163
    {
164
        // not set so return null
165
        if (!isset($this->data['keywords'])) {
166
            return null;
167
        }
168
169
        // return value
170
        return $this->data['keywords'];
171
    }
172
173
    public function getKeywordsOverwrite(): ?bool
174
    {
175
        // not set so return null
176
        if (!isset($this->data['keywords_overwrite'])) {
177
            return null;
178
        }
179
180
        // return value
181
        return (bool) $this->data['keywords_overwrite'];
182
    }
183
184
    public function getTitle(): ?string
185
    {
186
        // not set so return null
187
        if (!isset($this->data['title'])) {
188
            return null;
189
        }
190
191
        // return value
192
        return $this->data['title'];
193
    }
194
195
    public function getTitleOverwrite(): ?bool
196
    {
197
        // not set so return null
198
        if (!isset($this->data['title_overwrite'])) {
199
            return null;
200
        }
201
202
        // return value
203
        return (bool) $this->data['title_overwrite'];
204
    }
205
206 5
    public function getUrl(): ?string
207
    {
208
        // not set so return null
209 5
        if (!isset($this->data['url'])) {
210
            return null;
211
        }
212
213
        // return value
214 5
        return urldecode($this->data['url']);
215
    }
216
217
    public function getUrlOverwrite(): ?bool
218
    {
219
        // not set so return null
220
        if (!isset($this->data['url_overwrite'])) {
221
            return null;
222
        }
223
224
        // return value
225
        return (bool) $this->data['url_overwrite'];
226
    }
227
228
    public function getCanonicalUrl(): ?string
229
    {
230
        if (!isset($this->data['data']) || !is_array($this->data['data'])) {
231
            return null;
232
        }
233 2
234
        // not set so return null
235 2
        if (!array_key_exists('canonical_url', $this->data['data'])) {
236
            return null;
237
        }
238 2
239
        // return value
240
        return urldecode($this->data['data']['canonical_url']);
241 2
    }
242
243
    public function getCanonicalUrlOverwrite(): bool
244 2
    {
245
        if (!isset($this->data['data']) || !is_array($this->data['data'])) {
246
            return false;
247 2
        }
248
249
        // not set so return null
250 2
        if (!array_key_exists('canonical_url_overwrite', $this->data['data'])) {
251
            return false;
252
        }
253 2
254
        // return value
255
        return (bool) $this->data['data']['canonical_url_overwrite'];
256 2
    }
257
258
    /**
259
     * If the fields are disabled we don't have any values in the post.
260
     * When an error occurs in the other fields of the form the meta-fields would be cleared
261 5
     * therefore we alter the POST so it contains the initial values.
262
     */
263
    private function loadValuesOfDisabledFields(): void
264 5
    {
265 2
        if (!isset($_POST['page_title'])) {
266
            $_POST['page_title'] = $this->data['title'] ?? null;
267
        }
268
        if (!isset($_POST['meta_description'])) {
269 5
            $_POST['meta_description'] = $this->data['description'] ?? null;
270 5
        }
271 5
        if (!isset($_POST['meta_keywords'])) {
272
            $_POST['meta_keywords'] = $this->data['keywords'] ?? null;
273 5
        }
274
        if (!isset($_POST['url'])) {
275
            $_POST['url'] = $this->data['url'] ?? null;
276 5
        }
277 5
        if (!isset($_POST['canonical_url'])) {
278 5
            $_POST['canonical_url'] = $this->data['canonical_url'] ?? null;
279
        }
280 5
        if ($this->custom && !isset($_POST['meta_custom'])) {
281 5
            $_POST['meta_custom'] = $this->data['custom'] ?? null;
282 5
        }
283
        if (!isset($_POST['seo_index'])) {
284
            $_POST['seo_index'] = $this->data['seo_index'] ?? 'none';
285
        }
286 5
        if (!isset($_POST['seo_follow'])) {
287 5
            $_POST['seo_follow'] = $this->data['seo_follow'] ?? 'none';
288 5
        }
289
    }
290 5
291
    /**
292
     * Add all element into the form
293 5
     */
294 5
    protected function loadForm(): void
295 5
    {
296
        // is the form submitted?
297 5
        if ($this->form->isSubmitted()) {
298
            $this->loadValuesOfDisabledFields();
299
        }
300
301 5
        // add page title elements into the form
302
        $this->form->addCheckbox(
303
            'page_title_overwrite',
304
            isset($this->data['title_overwrite']) && $this->data['title_overwrite']
305 5
        );
306 5
        $this->form->addText('page_title', $this->data['title'] ?? null);
307 5
308 5
        // add meta description elements into the form
309
        $this->form->addCheckbox(
310
            'meta_description_overwrite',
311 5
            isset($this->data['description_overwrite']) && $this->data['description_overwrite']
312
        );
313
        $this->form->addText(
314
            'meta_description',
315 5
            $this->data['description'] ?? null
316 5
        );
317 5
318 5
        // add meta keywords elements into the form
319
        $this->form->addCheckbox(
320
            'meta_keywords_overwrite',
321
            isset($this->data['keywords_overwrite']) && $this->data['keywords_overwrite']
322 5
        );
323
        $this->form->addText('meta_keywords', $this->data['keywords'] ?? null);
324 5
325
        // add URL elements into the form
326
        $this->form->addCheckbox(
327 5
            'url_overwrite',
328 5
            isset($this->data['url_overwrite']) && $this->data['url_overwrite']
329 5
        );
330 5
        $this->form->addText('url', isset($this->data['url']) ? urldecode($this->data['url']) : null);
331 5
332 5
        // add canonical URL elements into the form
333 5
        $this->form->addCheckbox(
334
            'canonical_url_overwrite',
335
            $this->getCanonicalUrlOverwrite()
336
        );
337
        $this->form->addText(
338
            'canonical_url',
339
            $this->getCanonicalUrl()
340
        );
341
342 5
        // advanced SEO
343
        $indexValues = [
344 5
            ['value' => 'none', 'label' => BackendLanguage::getLabel('None')],
345
            ['value' => 'index', 'label' => 'index'],
346 5
            ['value' => 'noindex', 'label' => 'noindex'],
347 5
        ];
348
        $this->form->addRadiobutton(
349
            'seo_index',
350 5
            $indexValues,
351
            $this->data['seo_index'] ?? 'none'
352
        );
353
        $followValues = [
354 5
            ['value' => 'none', 'label' => BackendLanguage::getLabel('None')],
355
            ['value' => 'follow', 'label' => 'follow'],
356
            ['value' => 'nofollow', 'label' => 'nofollow'],
357
        ];
358
        $this->form->addRadiobutton(
359 5
            'seo_follow',
360
            $followValues,
361
            $this->data['seo_follow'] ?? 'none'
362 5
        );
363
364
        // should we add the meta-custom field
365
        if ($this->custom) {
366
            // add meta custom element into the form
367
            $this->form->addTextarea('meta_custom', $this->data['custom'] ?? null);
368
        }
369
370
        $this->form->addHidden('meta_id', $this->id);
371
        $this->form->addHidden('base_field_name', $this->baseFieldName);
372
        $this->form->addHidden('custom', $this->custom);
373
        $this->form->addHidden('class_name', $this->callback['class']);
374
        $this->form->addHidden('method_name', $this->callback['method']);
375
        $this->form->addHidden('parameters', \SpoonFilter::htmlspecialchars(serialize($this->callback['parameters'])));
376 1
    }
377
378 1
    /**
379
     * Load a specific meta-record
380
     *
381 1
     * @param int $id The id of the record to load.
382
     *
383
     * @throws Exception If no meta-record exists with the provided id
384
     */
385 1
    protected function loadMeta(int $id): void
386 1
    {
387
        $this->id = $id;
388
389
        $this->data = (array) BackendModel::getContainer()->get('database')->getRecord(
390 1
            'SELECT *
391
             FROM meta AS m
392 1
             WHERE m.id = ?',
393
            [$this->id]
394
        );
395
396
        // validate meta-record
397
        if (empty($this->data)) {
398 1
            throw new Exception('Meta-record doesn\'t exist.');
399
        }
400 1
401
        // unserialize data
402
        if (isset($this->data['data'])) {
403
            $this->data['data'] = @unserialize($this->data['data'], ['allowed_classes' => false]);
404
        }
405
    }
406
407
    /**
408
     * Saves the meta object
409
     *
410
     * @param bool $update Should we update the record or insert a new one.
411
     *
412 5
     * @throws Exception If no meta id was provided.
413
     *
414
     * @return int
415 5
     *
416
     * @deprecated just use the entity for doctrine.
417
     *             This class will be removed when all modules run on doctrine and will be replaced with the meta entity
418 5
     */
419 5
    public function save(bool $update = false): int
420
    {
421
        $this->validate();
422
423
        //serialize data for save
424
        if (!empty($this->data['data'])) {
425 2
            $this->data['data'] = serialize($this->data['data']);
426
        }
427
428 2
        if (empty($this->data['data'])) {
429
            $this->data['data'] = null;
430
        }
431
432
        // build meta
433 2
        $database = BackendModel::getContainer()->get('database');
434
435
        if ($this->id !== null && $update === true) {
436
            $database->update('meta', $this->data, 'id = ?', [$this->id]);
437
438 2
            return $this->id;
439
        }
440
441
        unset($this->data['id']);
442
443 2
        return (int) $database->insert('meta', $this->data);
444
    }
445
446
    /**
447
     * Set the callback to calculate an unique URL
448
     * REMARK: this method has to be public and static
449
     * REMARK: if you specify arguments they will be appended
450
     *
451
     * @param string $className Name of the class to use.
452
     * @param string $methodName Name of the method to use.
453
     * @param array $parameters Parameters to parse, they will be passed after ours.
454
     */
455
    public function setUrlCallback(string $className, string $methodName, array $parameters = []): void
456
    {
457 2
        // store in property
458 1
        $this->callback = ['class' => $className, 'method' => $methodName, 'parameters' => $parameters];
459
460
        // re-load the form
461 1
        $this->loadForm();
462 1
    }
463 1
464
    /**
465 1
     * Validates the form
466 1
     * It checks if there is a value when a checkbox is checked
467 1
     */
468 1
    public function validate(): void
469
    {
470 1
        // page title overwrite is checked
471 1
        if ($this->form->getField('page_title_overwrite')->isChecked()) {
472 1
            $this->form->getField('page_title')->isFilled(BackendLanguage::err('FieldIsRequired'));
473 1
        }
474
475 1
        // meta description overwrite is checked
476 1
        if ($this->form->getField('meta_description_overwrite')->isChecked()) {
477 1
            $this->form->getField('meta_description')->isFilled(BackendLanguage::err('FieldIsRequired'));
478 1
        }
479 1
480
        // meta keywords overwrite is checked
481
        if ($this->form->getField('meta_keywords_overwrite')->isChecked()) {
482 1
            $this->form->getField('meta_keywords')->isFilled(BackendLanguage::err('FieldIsRequired'));
483 1
        }
484 1
485 1
        // URL overwrite is checked
486 1
        if ($this->form->getField('url_overwrite')->isChecked()) {
487
            $this->form->getField('url')->isFilled(BackendLanguage::err('FieldIsRequired'));
488 1
            $url = \SpoonFilter::htmlspecialcharsDecode($this->form->getField('url')->getValue());
489 1
            $generatedUrl = $this->generateUrl($url);
490
491 1
            // check if urls are different
492 1
            if (CommonUri::getUrl($url) !== $generatedUrl) {
493
                $this->form->getField('url')->addError(
494 1
                    BackendLanguage::err('URLAlreadyExists')
495
                );
496
            }
497
        }
498
499
        // Canonical URL overwrite is checked
500
        if ($this->form->getField('canonical_url_overwrite')->isChecked()) {
501
            $this->form->getField('canonical_url')->isFilled(BackendLanguage::err('FieldIsRequired'));
502
        }
503
504
        // if the form was submitted correctly the data array should be populated
505
        if (!$this->form->isCorrect()) {
506
            return;
507
        }
508
509
        $this->data['keywords'] = $this->form->getField('meta_keywords_overwrite')->getActualValue(
510
            $this->form->getField('meta_keywords')->getValue(),
511
            $this->form->getField($this->baseFieldName)->getValue()
512
        );
513
        $this->data['keywords_overwrite'] = $this->form->getField('meta_keywords_overwrite')->isChecked();
514
        $this->data['description'] = $this->form->getField('meta_description_overwrite')->getActualValue(
515
            $this->form->getField('meta_description')->getValue(),
516
            $this->form->getField($this->baseFieldName)->getValue()
517
        );
518
        $this->data['description_overwrite'] = $this->form->getField('meta_description_overwrite')->isChecked();
519
        $this->data['title'] = $this->form->getField('page_title_overwrite')->getActualValue(
520
            $this->form->getField('page_title')->getValue(),
521
            $this->form->getField($this->baseFieldName)->getValue()
522
        );
523
        $this->data['title_overwrite'] = $this->form->getField('page_title_overwrite')->isChecked();
524
        $this->data['url'] = $this->generateUrl(
525
            $this->form->getField('url_overwrite')->getActualValue(
526
                \SpoonFilter::htmlspecialcharsDecode($this->form->getField('url')->getValue()),
527
                \SpoonFilter::htmlspecialcharsDecode($this->form->getField($this->baseFieldName)->getValue())
528
            )
529
        );
530
        $this->data['url_overwrite'] = $this->form->getField('url_overwrite')->isChecked();
531
532
        if ($this->form->getField('canonical_url_overwrite')->isChecked()) {
533
            $this->data['data']['canonical_url'] = $this->form->getField('canonical_url_overwrite')->getActualValue(
534
                \SpoonFilter::htmlspecialcharsDecode($this->form->getField('canonical_url')->getValue()),
535
                null
536
            );
537
            $this->data['data']['canonical_url_overwrite'] = true;
538
        } else {
539
            unset($this->data['data']['canonical_url']);
540
            unset($this->data['data']['canonical_url_overwrite']);
541
        }
542
543
        $this->data['custom'] = $this->custom && $this->form->getField('meta_custom')->isFilled()
544
            ? $this->form->getField('meta_custom')->getValue() : null;
545
        $this->data['seo_index'] = $this->form->getField('seo_index')->getValue();
546
        $this->data['seo_follow'] = $this->form->getField('seo_follow')->getValue();
547
548
        if ($this->data['seo_index'] === 'none') {
549
            unset($this->data['seo_index']);
550
        }
551
        if ($this->data['seo_follow'] === 'none') {
552
            unset($this->data['seo_follow']);
553
        }
554
    }
555
556
    public function getData(): array
557
    {
558
        return $this->data;
559
    }
560
561
    public function getMetaEntity(): MetaEntity
562
    {
563
        $this->validate();
564
565
        return MetaEntity::fromBackendMeta($this);
566
    }
567
}
568