Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
28.77% covered (danger)
28.77%
61 / 212
8.33% covered (danger)
8.33%
2 / 24
CRAP
0.00% covered (danger)
0.00%
0 / 1
ApiController
28.77% covered (danger)
28.77%
61 / 212
8.33% covered (danger)
8.33%
2 / 24
1689.08
0.00% covered (danger)
0.00%
0 / 1
 apiCookieConsent
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
56
 apiPageCreate
57.14% covered (warning)
57.14%
4 / 7
0.00% covered (danger)
0.00%
0 / 1
2.31
 validatePageCreate
80.00% covered (warning)
80.00%
4 / 5
0.00% covered (danger)
0.00%
0 / 1
3.07
 createPageFromRequest
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
2
 apiPageL11nCreate
57.14% covered (warning)
57.14%
4 / 7
0.00% covered (danger)
0.00%
0 / 1
2.31
 validatePageL11nCreate
80.00% covered (warning)
80.00%
4 / 5
0.00% covered (danger)
0.00%
0 / 1
3.07
 createPageL11nFromRequest
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
2
 parseCmsKeys
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 apiApplicationInstall
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
1 / 1
4
 uploadApplication
90.48% covered (success)
90.48%
19 / 21
0.00% covered (danger)
0.00%
0 / 1
5.02
 validateApplicationInstall
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 apiApplicationTemplateUpdate
22.22% covered (danger)
22.22%
4 / 18
0.00% covered (danger)
0.00%
0 / 1
30.05
 validateApplicationTemplateUpdate
75.00% covered (warning)
75.00%
3 / 4
0.00% covered (danger)
0.00%
0 / 1
2.06
 apiApplicationFilesList
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
6
 apiPageUpdate
0.00% covered (danger)
0.00%
0 / 24
0.00% covered (danger)
0.00%
0 / 1
30
 updatePageFromRequest
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 validatePageUpdate
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 apiPageDelete
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
6
 validatePageDelete
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 apiPageL11nUpdate
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
6
 updatePageL11nFromRequest
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
12
 validatePageL11nUpdate
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 apiPageL11nDelete
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
6
 validatePageL11nDelete
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2
3/**
4 * Jingga
5 *
6 * PHP Version 8.1
7 *
8 * @package   Modules\CMS
9 * @copyright Dennis Eichhorn
10 * @license   OMS License 2.0
11 * @version   1.0.0
12 * @link      https://jingga.app
13 */
14declare(strict_types=1);
15
16namespace Modules\CMS\Controller;
17
18use Modules\Admin\Models\App;
19use Modules\Admin\Models\AppMapper;
20use Modules\CMS\Models\Page;
21use Modules\CMS\Models\PageL11nMapper;
22use Modules\CMS\Models\PageMapper;
23use Modules\Media\Models\UploadFile;
24use Modules\Media\Models\UploadStatus;
25use phpOMS\Localization\BaseStringL11n;
26use phpOMS\Message\Http\RequestStatusCode;
27use phpOMS\Message\RequestAbstract;
28use phpOMS\Message\ResponseAbstract;
29use phpOMS\Model\Message\FormValidation;
30use phpOMS\System\File\Local\Directory;
31use phpOMS\Utils\IO\Zip\Zip;
32use phpOMS\Utils\MbStringUtils;
33
34/**
35 * Api controller for the CMS module.
36 *
37 * @package Modules\CMS
38 * @license OMS License 2.0
39 * @link    https://jingga.app
40 * @since   1.0.0
41 */
42final class ApiController extends Controller
43{
44    /**
45     * Api method to handle cookie consent settings
46     *
47     * @param RequestAbstract  $request  Request
48     * @param ResponseAbstract $response Response
49     * @param array            $data     Generic data
50     *
51     * @return void
52     *
53     * @api
54     *
55     * @since 1.0.0
56     */
57    public function apiCookieConsent(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void
58    {
59        $cookieContent = \file_get_contents(__DIR__ . '/../../../Web/' . ($request->getDataString('app') ?? $this->app->appName) . '/cookie_consent.json');
60        if ($cookieContent === false) {
61            $response->header->status = RequestStatusCode::R_400;
62
63            return;
64        }
65
66        $cookieRules = \json_decode($cookieContent, true);
67        if (!\is_array($cookieRules)) {
68            $response->header->status = RequestStatusCode::R_400;
69
70            return;
71        }
72
73        $userSettings = $request->getDataJson('cookie_consent_rules');
74        $this->app->cookieJar->set('cookie_consent', \json_encode($userSettings), 86400);
75
76        foreach ($userSettings as $rule) {
77            if (isset($cookieRules[$rule])) {
78                foreach ($rule['values'] as $key => $value) {
79                    if (!empty($value)) {
80                        $this->app->cookieJar->set($key, $value);
81                    }
82                }
83            }
84        }
85
86        $this->app->cookieJar->save();
87    }
88
89    /**
90     * Api method to create a page
91     *
92     * @param RequestAbstract  $request  Request
93     * @param ResponseAbstract $response Response
94     * @param array            $data     Generic data
95     *
96     * @return void
97     *
98     * @api
99     *
100     * @since 1.0.0
101     */
102    public function apiPageCreate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void
103    {
104        if (!empty($val = $this->validatePageCreate($request))) {
105            $response->header->status = RequestStatusCode::R_400;
106            $this->createInvalidCreateResponse($request, $response, $val);
107
108            return;
109        }
110
111        $application = $this->createPageFromRequest($request);
112        $this->createModel($request->header->account, $application, PageMapper::class, 'page', $request->getOrigin());
113        $this->createStandardCreateResponse($request, $response, $application);
114    }
115
116    /**
117     * Validate page create request
118     *
119     * @param RequestAbstract $request Request
120     *
121     * @return array<string, bool>
122     *
123     * @since 1.0.0
124     */
125    private function validatePageCreate(RequestAbstract $request) : array
126    {
127        $val = [];
128        if (($val['name'] = !$request->hasData('name'))
129            || ($val['app'] = !$request->hasData('app'))
130        ) {
131            return $val;
132        }
133
134        return [];
135    }
136
137    /**
138     * Method to create page from request.
139     *
140     * @param RequestAbstract $request Request
141     *
142     * @return Page
143     *
144     * @since 1.0.0
145     */
146    private function createPageFromRequest(RequestAbstract $request) : Page
147    {
148        $page           = new Page();
149        $page->name     = $request->getDataString('name') ?? '';
150        $page->app      = $request->getDataInt('app') ?? 2;
151        $page->template = $request->getDataString('template') ?? '';
152
153        return $page;
154    }
155
156    /**
157     * Api method to create a page
158     *
159     * @param RequestAbstract  $request  Request
160     * @param ResponseAbstract $response Response
161     * @param array            $data     Generic data
162     *
163     * @return void
164     *
165     * @api
166     *
167     * @since 1.0.0
168     */
169    public function apiPageL11nCreate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void
170    {
171        if (!empty($val = $this->validatePageL11nCreate($request))) {
172            $response->header->status = RequestStatusCode::R_400;
173            $this->createInvalidCreateResponse($request, $response, $val);
174
175            return;
176        }
177
178        $l11nPage = $this->createPageL11nFromRequest($request);
179        $this->createModel($request->header->account, $l11nPage, PageL11nMapper::class, 'page_l11n', $request->getOrigin());
180        $this->createStandardCreateResponse($request, $response, $l11nPage);
181    }
182
183    /**
184     * Validate page l11n create request
185     *
186     * @param RequestAbstract $request Request
187     *
188     * @return array<string, bool>
189     *
190     * @since 1.0.0
191     */
192    private function validatePageL11nCreate(RequestAbstract $request) : array
193    {
194        $val = [];
195        if (($val['name'] = !$request->hasData('name'))
196            || ($val['page'] = !$request->hasData('page'))
197        ) {
198            return $val;
199        }
200
201        return [];
202    }
203
204    /**
205     * Method to create page localization from request.
206     *
207     * @param RequestAbstract $request Request
208     *
209     * @return BaseStringL11n
210     *
211     * @since 1.0.0
212     */
213    private function createPageL11nFromRequest(RequestAbstract $request) : BaseStringL11n
214    {
215        $pageL11n      = new BaseStringL11n();
216        $pageL11n->ref = $request->getDataInt('page') ?? 0;
217        $pageL11n->setLanguage(
218            $request->getDataString('language') ?? $request->header->l11n->language
219        );
220        $pageL11n->name = $request->getDataString('name') ?? '';
221
222        /** @var Page $page */
223        $page = PageMapper::get()
224            ->where('id', $request->getDataInt('page') ?? 0)
225            ->execute();
226
227        /** @var App $app */
228        $app = AppMapper::get()
229            ->where('id', $page->app)
230            ->execute();
231
232        $pageL11n->content = $this->parseCmsKeys($request->getDataString('content') ?? '', $app);
233
234        return $pageL11n;
235    }
236
237    /**
238     * Searches and replaces well-defined keywords
239     *
240     * @param string $content     Content to search
241     * @param App    $application Application model
242     *
243     * @return string
244     *
245     * @since 1.0.0
246     */
247    private function parseCmsKeys(string $content, App $application) : string
248    {
249        if ($content === '') {
250            return '';
251        }
252
253        return \str_replace('{APPNAME}', $application->name, $content);
254    }
255
256    /**
257     * Api method to install a application
258     *
259     * @param RequestAbstract  $request  Request
260     * @param ResponseAbstract $response Response
261     * @param array            $data     Generic data
262     *
263     * @return void
264     *
265     * @api
266     *
267     * @since 1.0.0
268     */
269    public function apiApplicationInstall(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void
270    {
271        if (!empty($val = $this->validateApplicationInstall($request))) {
272            $response->data[$request->uri->__toString()] = new FormValidation($val);
273            $response->header->status                    = RequestStatusCode::R_400;
274
275            return;
276        }
277
278        $app = self::uploadApplication($request);
279        if (empty($app) || $app === '-1') {
280            // @codeCoverageIgnoreStart
281            $response->set($request->uri->__toString(), new FormValidation());
282            $response->header->status = RequestStatusCode::R_400;
283
284            return;
285            // @codeCoverageIgnoreEnd
286        }
287
288        $request->setData('appSrc', 'Modules/CMS/tmp/' . $app);
289        $request->setData('appDest', 'Web/' . $app);
290        $request->setData('appName', $app);
291        $request->setData('default_unit', $request->getDataInt('default_int'));
292        $request->setData('theme', $request->getDataString('theme') ?? 'Default', true);
293        $this->app->moduleManager->get('Admin')->apiInstallApplication($request, $response);
294        $this->app->moduleManager->get('Admin')->apiApplicationCreate($request, $response);
295
296        Directory::delete(__DIR__ . '/../tmp');
297    }
298
299    /**
300     * Upload the application archiv
301     *
302     * @param RequestAbstract $request Request
303     *
304     * @return string
305     *
306     * @since 1.0.0
307     */
308    public static function uploadApplication(RequestAbstract $request) : string
309    {
310        Directory::delete(__DIR__ . '/../tmp');
311        if (!\is_dir(__DIR__ . '/../tmp')) {
312            \mkdir(__DIR__ . '/../tmp');
313        }
314
315        $upload                   = new UploadFile();
316        $upload->outputDir        = __DIR__ . '/../tmp';
317        $upload->preserveFileName = true;
318
319        $status = $upload->upload($request->files);
320        $status = \array_values($status);
321
322        if ($status[0]['status'] !== UploadStatus::OK) {
323            return ''; // @codeCoverageIgnore
324        }
325
326        $app = MbStringUtils::mb_ucfirst(
327            \mb_strtolower(
328                $request->getDataString('name') ?? \basename($status[0]['filename'], '.zip')
329            )
330        );
331
332        // cannot create existing application name
333        if (\is_dir(__DIR__ . '/../../../' . $app)
334            || \is_dir(__DIR__ . '/../../../Web/' . $app)
335        ) {
336            \unlink(__DIR__ . '/../tmp/' . $status[0]['filename']);
337
338            return '-1';
339        }
340
341        Zip::unpack(__DIR__ . '/../tmp/' . $status[0]['filename'], __DIR__ . '/../tmp/' . $app);
342        \unlink(__DIR__ . '/../tmp/' . $status[0]['filename']);
343
344        return $app;
345    }
346
347    /**
348     * Validate application install request
349     *
350     * @param RequestAbstract $request Request
351     *
352     * @return array<string, bool> Returns the validation array of the request
353     *
354     * @since 1.0.0
355     */
356    private function validateApplicationInstall(RequestAbstract $request) : array
357    {
358        $val = [];
359        if (($val['name'] = !$request->hasData('name'))
360            || ($val['files'] = empty($request->files))
361        ) {
362            return $val;
363        }
364
365        return [];
366    }
367
368    /**
369     * Api method to update a template
370     *
371     * @param RequestAbstract  $request  Request
372     * @param ResponseAbstract $response Response
373     * @param array            $data     Generic data
374     *
375     * @return void
376     *
377     * @api
378     *
379     * @since 1.0.0
380     */
381    public function apiApplicationTemplateUpdate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void
382    {
383        if (!empty($val = $this->validateApplicationTemplateUpdate($request))) {
384            $response->data[$request->uri->__toString()] = new FormValidation($val);
385            $response->header->status                    = RequestStatusCode::R_400;
386
387            return;
388        }
389
390        /** @var App $app */
391        $app = AppMapper::get()->where('id', $request->getData('id'))->execute();
392
393        $webPath  = \realpath(__DIR__ . '/../../../Web/');
394        $basePath = \realpath(__DIR__ . '/../../../Web/' . MbStringUtils::mb_ucfirst(\mb_strtolower($app->name)) . '/tpl/');
395
396        if ($basePath === false
397            || $webPath === false
398            || ($path = \realpath($basePath . '/' . $request->getDatA('tpl'))) === false
399            || \stripos($path, $webPath) !== 0
400        ) {
401            return;
402        }
403
404        \file_put_contents($path, $request->getData('content'));
405
406        if ($request->hasData('name')) {
407            $old = $path;
408            $new = $basePath . '/' . $request->getData('name') . '.tpl.php';
409            \rename($old, $new);
410        }
411
412        $this->createStandardCreateResponse($request, $response, $request->getData('content'));
413    }
414
415    /**
416     * Validate application template update request
417     *
418     * @param RequestAbstract $request Request
419     *
420     * @return array<string, bool> Returns the validation array of the request
421     *
422     * @since 1.0.0
423     */
424    private function validateApplicationTemplateUpdate(RequestAbstract $request) : array
425    {
426        $val = [];
427        if (($val['content'] = !$request->hasData('content'))) {
428            return $val;
429        }
430
431        return [];
432    }
433
434    /**
435     * Api method to list files of a application
436     *
437     * @param RequestAbstract  $request  Request
438     * @param ResponseAbstract $response Response
439     * @param array            $data     Generic data
440     *
441     * @return void
442     *
443     * @api
444     *
445     * @since 1.0.0
446     */
447    public function apiApplicationFilesList(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void
448    {
449        /** @var App $app */
450        $app  = AppMapper::get()->where('id', (int) $request->getData('id'))->execute();
451        $path = $request->getDataString('path') ?? '/';
452
453        $content = \scandir(__DIR__ . '/../../../Web/' . MbStringUtils::mb_ucfirst(\mb_strtolower($app->name)) . $path);
454
455        if ($content === false) {
456            $content = [];
457        }
458
459        $this->createStandardReturnResponse($request, $response, $content);
460    }
461
462    /**
463     * Api method to update Page
464     *
465     * @param RequestAbstract  $request  Request
466     * @param ResponseAbstract $response Response
467     * @param array            $data     Generic data
468     *
469     * @return void
470     *
471     * @api
472     *
473     * @since 1.0.0
474     */
475    public function apiPageUpdate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void
476    {
477        if (!empty($val = $this->validatePageUpdate($request))) {
478            $response->header->status = RequestStatusCode::R_400;
479            $this->createInvalidUpdateResponse($request, $response, $val);
480
481            return;
482        }
483
484        /** @var \Modules\CMS\Models\Page $old */
485        $old = PageMapper::get()->where('id', (int) $request->getData('id'))->execute();
486        $new = $this->updatePageFromRequest($request, clone $old);
487
488        $this->updateModel($request->header->account, $old, $new, PageMapper::class, 'page', $request->getOrigin());
489
490        if (!$request->hasData('content')) {
491            $this->createStandardUpdateResponse($request, $response, $new);
492
493            return;
494        }
495
496        /** @var \phpOMS\Localization\BaseStringL11n[] $l11ns */
497        $l11ns = PageL11nMapper::getAll()
498            ->where('ref', (int) $request->getData('id'))
499            ->where('language', $request->getDataString('language') ?? $request->header->l11n->language)
500            ->execute();
501
502        if (empty($l11ns)) {
503            $this->createInvalidUpdateResponse($request, $response, []);
504
505            return;
506        }
507
508        $request->setData('page', (int) $request->getData('id'), true);
509
510        $contents = $request->getDataJson('content');
511        foreach ($contents as $content) {
512            // @todo: fix this, the next line is wrong. I need to also pass an id array to know to which id the content belongs
513            $request->setData('id', \reset($l11ns)->id, true);
514
515            $request->setData('content', $content, true);
516            $this->apiPageL11nUpdate($request, $response, $data);
517        }
518
519        $this->createStandardUpdateResponse($request, $response, $new);
520    }
521
522    /**
523     * Method to update Page from request.
524     *
525     * @param RequestAbstract $request Request
526     * @param Page            $new     Model to modify
527     *
528     * @return Page
529     *
530     * @todo: implement
531     *
532     * @since 1.0.0
533     */
534    public function updatePageFromRequest(RequestAbstract $request, Page $new) : Page
535    {
536        $new->name     = $request->getDataString('name') ?? $new->name;
537        $new->app      = $request->getDataInt('app') ?? $new->app;
538        $new->template = $request->getDataString('template') ?? $new->template;
539
540        return $new;
541    }
542
543    /**
544     * Validate Page update request
545     *
546     * @param RequestAbstract $request Request
547     *
548     * @return array<string, bool>
549     *
550     * @todo: implement
551     *
552     * @since 1.0.0
553     */
554    private function validatePageUpdate(RequestAbstract $request) : array
555    {
556        $val = [];
557        if (($val['id'] = !$request->hasData('id'))) {
558            return $val;
559        }
560
561        return [];
562    }
563
564    /**
565     * Api method to delete Page
566     *
567     * @param RequestAbstract  $request  Request
568     * @param ResponseAbstract $response Response
569     * @param array            $data     Generic data
570     *
571     * @return void
572     *
573     * @api
574     *
575     * @since 1.0.0
576     */
577    public function apiPageDelete(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void
578    {
579        if (!empty($val = $this->validatePageDelete($request))) {
580            $response->header->status = RequestStatusCode::R_400;
581            $this->createInvalidDeleteResponse($request, $response, $val);
582
583            return;
584        }
585
586        /** @var \Modules\CMS\Models\Page $page */
587        $page = PageMapper::get()->where('id', (int) $request->getData('id'))->execute();
588        $this->deleteModel($request->header->account, $page, PageMapper::class, 'page', $request->getOrigin());
589        $this->createStandardDeleteResponse($request, $response, $page);
590    }
591
592    /**
593     * Validate Page delete request
594     *
595     * @param RequestAbstract $request Request
596     *
597     * @return array<string, bool>
598     *
599     * @todo: implement
600     *
601     * @since 1.0.0
602     */
603    private function validatePageDelete(RequestAbstract $request) : array
604    {
605        $val = [];
606        if (($val['id'] = !$request->hasData('id'))) {
607            return $val;
608        }
609
610        return [];
611    }
612
613    /**
614     * Api method to update PageL11n
615     *
616     * @param RequestAbstract  $request  Request
617     * @param ResponseAbstract $response Response
618     * @param array            $data     Generic data
619     *
620     * @return void
621     *
622     * @api
623     *
624     * @since 1.0.0
625     */
626    public function apiPageL11nUpdate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void
627    {
628        if (!empty($val = $this->validatePageL11nUpdate($request))) {
629            $response->header->status = RequestStatusCode::R_400;
630            $this->createInvalidUpdateResponse($request, $response, $val);
631
632            return;
633        }
634
635        /** @var BaseStringL11n $old */
636        $old = PageL11nMapper::get()->where('id', (int) $request->getData('id'))->execute();
637        $new = $this->updatePageL11nFromRequest($request, clone $old);
638
639        $this->updateModel($request->header->account, $old, $new, PageL11nMapper::class, 'page_l11n', $request->getOrigin());
640        $this->createStandardUpdateResponse($request, $response, $new);
641    }
642
643    /**
644     * Method to update PageL11n from request.
645     *
646     * @param RequestAbstract $request Request
647     * @param BaseStringL11n  $new     Model to modify
648     *
649     * @return BaseStringL11n
650     *
651     * @todo: implement
652     *
653     * @since 1.0.0
654     */
655    public function updatePageL11nFromRequest(RequestAbstract $request, BaseStringL11n $new) : BaseStringL11n
656    {
657        $new->ref = $request->getDataInt('page') ?? $new->ref;
658        $new->setLanguage(
659            $request->getDataString('language') ?? $new->language
660        );
661        $new->name = $request->getDataString('name') ?? $new->name;
662
663        /** @var Page $page */
664        $page = PageMapper::get()
665            ->where('id', $request->getDataInt('page') ?? 0)
666            ->execute();
667
668        /** @var App $app */
669        $app = $page->id !== 0 ? AppMapper::get()
670            ->where('id', $page->app)
671            ->execute()
672            : null;
673
674        $new->content = $request->hasData('content')
675            ? $this->parseCmsKeys($request->getDataString('content') ?? '', $app)
676            : $new->content;
677
678        return $new;
679    }
680
681    /**
682     * Validate PageL11n update request
683     *
684     * @param RequestAbstract $request Request
685     *
686     * @return array<string, bool>
687     *
688     * @todo: implement
689     *
690     * @since 1.0.0
691     */
692    private function validatePageL11nUpdate(RequestAbstract $request) : array
693    {
694        $val = [];
695        if (($val['id'] = !$request->hasData('id'))) {
696            return $val;
697        }
698
699        return [];
700    }
701
702    /**
703     * Api method to delete PageL11n
704     *
705     * @param RequestAbstract  $request  Request
706     * @param ResponseAbstract $response Response
707     * @param array            $data     Generic data
708     *
709     * @return void
710     *
711     * @api
712     *
713     * @since 1.0.0
714     */
715    public function apiPageL11nDelete(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void
716    {
717        if (!empty($val = $this->validatePageL11nDelete($request))) {
718            $response->header->status = RequestStatusCode::R_400;
719            $this->createInvalidDeleteResponse($request, $response, $val);
720
721            return;
722        }
723
724        /** @var BaseStringL11n $pageL11n */
725        $pageL11n = PageL11nMapper::get()->where('id', (int) $request->getData('id'))->execute();
726        $this->deleteModel($request->header->account, $pageL11n, PageL11nMapper::class, 'page_l11n', $request->getOrigin());
727        $this->createStandardDeleteResponse($request, $response, $pageL11n);
728    }
729
730    /**
731     * Validate PageL11n delete request
732     *
733     * @param RequestAbstract $request Request
734     *
735     * @return array<string, bool>
736     *
737     * @todo: implement
738     *
739     * @since 1.0.0
740     */
741    private function validatePageL11nDelete(RequestAbstract $request) : array
742    {
743        $val = [];
744        if (($val['id'] = !$request->hasData('id'))) {
745            return $val;
746        }
747
748        return [];
749    }
750}