Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
54.76% covered (warning)
54.76%
115 / 210
50.00% covered (danger)
50.00%
14 / 28
CRAP
0.00% covered (danger)
0.00%
0 / 1
ModuleAbstract
54.76% covered (warning)
54.76%
115 / 210
50.00% covered (danger)
50.00%
14 / 28
223.23
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
30
 getLocalization
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 addReceiving
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getReceiving
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getProviding
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getName
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getDependencies
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 fillJsonResponse
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
1
 createStandardCreateResponse
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 createStandardUpdateResponse
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 createStandardDeleteResponse
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 createStandardRemoveResponse
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 createStandardReturnResponse
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 createStandardAddResponse
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 createInvalidCreateResponse
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 createInvalidUpdateResponse
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 createInvalidDeleteResponse
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 createInvalidRemoveResponse
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 createInvalidReturnResponse
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 createInvalidAddResponse
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 createInvalidPermissionResponse
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 fillJsonRawResponse
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 createModel
100.00% covered (success)
100.00%
17 / 17
100.00% covered (success)
100.00%
1 / 1
3
 createModels
100.00% covered (success)
100.00%
18 / 18
100.00% covered (success)
100.00%
1 / 1
4
 updateModel
100.00% covered (success)
100.00%
17 / 17
100.00% covered (success)
100.00%
1 / 1
3
 deleteModel
100.00% covered (success)
100.00%
17 / 17
100.00% covered (success)
100.00%
1 / 1
3
 createModelRelation
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
1 / 1
2
 deleteModelRelation
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2/**
3 * Jingga
4 *
5 * PHP Version 8.1
6 *
7 * @package   phpOMS\Module
8 * @copyright Dennis Eichhorn
9 * @license   OMS License 2.0
10 * @version   1.0.0
11 * @link      https://jingga.app
12 */
13declare(strict_types=1);
14
15namespace phpOMS\Module;
16
17use phpOMS\Application\ApplicationAbstract;
18use phpOMS\Message\NotificationLevel;
19use phpOMS\Message\RequestAbstract;
20use phpOMS\Message\ResponseAbstract;
21use phpOMS\System\MimeType;
22use phpOMS\Utils\StringUtils;
23
24/**
25 * Module abstraction class.
26 *
27 * @method __call(string $name, array $arguments)
28 *
29 * @package phpOMS\Module
30 * @license OMS License 2.0
31 * @link    https://jingga.app
32 * @since   1.0.0
33 */
34abstract class ModuleAbstract
35{
36    /**
37     * Module name.
38     *
39     * @var string
40     * @since 1.0.0
41     */
42    public const NAME = '';
43
44    /**
45     * Module path.
46     *
47     * @var string
48     * @since 1.0.0
49     */
50    public const PATH = __DIR__ . '/../../Modules/';
51
52    /**
53     * Module version.
54     *
55     * @var string
56     * @since 1.0.0
57     */
58    public const VERSION = '1.0.0';
59
60    /**
61     * Module id.
62     *
63     * @var int
64     * @since 1.0.0
65     */
66    public const ID = 0;
67
68    /**
69     * Receiving modules from?
70     *
71     * @var string[]
72     * @since 1.0.0
73     */
74    public static array $providing = [];
75
76    /**
77     * Dependencies.
78     *
79     * @var string[]
80     * @since 1.0.0
81     */
82    public static array $dependencies = [];
83
84    /**
85     * Receiving modules from?
86     *
87     * @var string[]
88     * @since 1.0.0
89     */
90    public array $receiving = [];
91
92    /**
93     * Application instance.
94     *
95     * @var ApplicationAbstract
96     * @since 1.0.0
97     */
98    protected ApplicationAbstract $app;
99
100    /**
101     * Is module active.
102     *
103     * @var bool
104     * @since 1.0.0
105     */
106    public bool $active = true;
107
108    /**
109     * Auditor for logging.
110     *
111     * @var null|ModuleAbstract
112     * @since 1.0.0
113     */
114    public static ?ModuleAbstract $auditor = null;
115
116    /**
117     * Constructor.
118     *
119     * @param null|ApplicationAbstract $app Application instance
120     *
121     * @since 1.0.0
122     */
123    public function __construct(ApplicationAbstract $app = null)
124    {
125        $this->app = $app ?? new class() extends ApplicationAbstract {};
126
127        if (self::$auditor === null && static::ID !== 1006200000) {
128            /** @phpstan-ignore-next-line */
129            self::$auditor = $this->app->moduleManager?->get('Auditor', 'Api');
130            self::$auditor = self::$auditor === null || self::$auditor::ID === 0 ? null : self::$auditor;
131        }
132    }
133
134    /**
135     * Get language files.
136     *
137     * @param string $language    Language key
138     * @param string $destination Application destination (e.g. Backend)
139     *
140     * @return array<string, array<string, string>>
141     *
142     * @since 1.0.0
143     */
144    public static function getLocalization(string $language, string $destination) : array
145    {
146        $lang = [];
147        if (\is_file($oldPath = \rtrim(static::PATH, '/') . '/Theme/' . $destination . '/Lang/' . $language . '.lang.php')) {
148            /** @noinspection PhpIncludeInspection */
149            return include $oldPath;
150        }
151
152        return $lang;
153    }
154
155    /**
156     * Add modules this module receives from
157     *
158     * @param string $module Module name
159     *
160     * @return void
161     *
162     * @since 1.0.0
163     */
164    public function addReceiving(string $module) : void
165    {
166        $this->receiving[] = $module;
167    }
168
169    /**
170     * Get modules this module is receiving from
171     *
172     * @return string[]
173     *
174     * @since 1.0.0
175     */
176    public function getReceiving() : array
177    {
178        /** @noinspection PhpUndefinedFieldInspection */
179        return $this->receiving;
180    }
181
182    /**
183     * Get modules this module is providing for
184     *
185     * @return string[]
186     *
187     * @since 1.0.0
188     */
189    public function getProviding() : array
190    {
191        /** @noinspection PhpUndefinedFieldInspection */
192        return static::$providing;
193    }
194
195    /**
196     * Get the name of the module
197     *
198     * @return string
199     *
200     * @since 1.0.0
201     */
202    public function getName() : string
203    {
204        /** @noinspection PhpUndefinedFieldInspection */
205        return static::NAME;
206    }
207
208    /**
209     * Get module dependencies
210     *
211     * @return string[]
212     *
213     * @since 1.0.0
214     */
215    public function getDependencies() : array
216    {
217        /** @noinspection PhpUndefinedFieldInspection */
218        return static::$dependencies;
219    }
220
221    /**
222     * Fills the response object
223     *
224     * The response object contains the following data:
225     *
226     *  * status = Response status
227     *  * title = Response title (e.g. for frontend reporting)
228     *  * message = Response message (e.g. for frontend reporting)
229     *  * response = Response object (e.g. for validation/frontend reporting/form validation)
230     *
231     * @param RequestAbstract  $request  Request
232     * @param ResponseAbstract $response Response
233     * @param string           $status   Response status
234     * @param string           $title    Response title
235     * @param string           $message  Response message
236     * @param mixed            $obj      Response object
237     *
238     * @return void
239     *
240     * @since 1.0.0
241     */
242    protected function fillJsonResponse(
243        RequestAbstract $request,
244        ResponseAbstract $response,
245        string $status,
246        string $title,
247        string $message,
248        mixed $obj
249    ) : void
250    {
251        $response->header->set('Content-Type', MimeType::M_JSON . '; charset=utf-8', true);
252        $response->data[$request->uri->__toString()] = [
253            'status'   => $status,
254            'title'    => $title,
255            'message'  => $message,
256            'response' => $obj,
257        ];
258    }
259
260    /**
261     * Create standard model create response.
262     *
263     * The response object contains the following data:
264     *
265     *  * status = Response status
266     *  * title = Response title (e.g. for frontend reporting)
267     *  * message = Response message (e.g. for frontend reporting)
268     *  * response = Response object (e.g. for validation/frontend reporting/form validation)
269     *
270     * @param RequestAbstract  $request  Request
271     * @param ResponseAbstract $response Response
272     * @param mixed            $obj      Response object
273     *
274     * @return void
275     *
276     * @since 1.0.0
277     */
278    public function createStandardCreateResponse(
279        RequestAbstract $request,
280        ResponseAbstract $response,
281        mixed $obj
282    ) : void
283    {
284        $response->header->set('Content-Type', MimeType::M_JSON . '; charset=utf-8', true);
285        $response->data[$request->uri->__toString()] = [
286            'status'   => NotificationLevel::OK,
287            'title'    => '',
288            'message'  => $this->app->l11nManager->getText($response->header->l11n->language, '0', '0', 'SuccessfulCreate'),
289            'response' => $obj,
290        ];
291    }
292
293    /**
294     * Create standard model update response.
295     *
296     * The response object contains the following data:
297     *
298     *  * status = Response status
299     *  * title = Response title (e.g. for frontend reporting)
300     *  * message = Response message (e.g. for frontend reporting)
301     *  * response = Response object (e.g. for validation/frontend reporting/form validation)
302     *
303     * @param RequestAbstract  $request  Request
304     * @param ResponseAbstract $response Response
305     * @param mixed            $obj      Response object
306     *
307     * @return void
308     *
309     * @since 1.0.0
310     */
311    public function createStandardUpdateResponse(
312        RequestAbstract $request,
313        ResponseAbstract $response,
314        mixed $obj
315    ) : void
316    {
317        $response->header->set('Content-Type', MimeType::M_JSON . '; charset=utf-8', true);
318        $response->data[$request->uri->__toString()] = [
319            'status'   => NotificationLevel::OK,
320            'title'    => '',
321            'message'  => $this->app->l11nManager->getText($response->header->l11n->language, '0', '0', 'SuccessfulUpdate'),
322            'response' => $obj,
323        ];
324    }
325
326    /**
327     * Create standard model delete response.
328     *
329     * The response object contains the following data:
330     *
331     *  * status = Response status
332     *  * title = Response title (e.g. for frontend reporting)
333     *  * message = Response message (e.g. for frontend reporting)
334     *  * response = Response object (e.g. for validation/frontend reporting/form validation)
335     *
336     * @param RequestAbstract  $request  Request
337     * @param ResponseAbstract $response Response
338     * @param mixed            $obj      Response object
339     *
340     * @return void
341     *
342     * @since 1.0.0
343     */
344    public function createStandardDeleteResponse(
345        RequestAbstract $request,
346        ResponseAbstract $response,
347        mixed $obj
348    ) : void
349    {
350        $response->header->set('Content-Type', MimeType::M_JSON . '; charset=utf-8', true);
351        $response->data[$request->uri->__toString()] = [
352            'status'   => NotificationLevel::OK,
353            'title'    => '',
354            'message'  => $this->app->l11nManager->getText($response->header->l11n->language, '0', '0', 'SuccessfulDelete'),
355            'response' => $obj,
356        ];
357    }
358
359    /**
360     * Create standard model remove response.
361     *
362     * The response object contains the following data:
363     *
364     *  * status = Response status
365     *  * title = Response title (e.g. for frontend reporting)
366     *  * message = Response message (e.g. for frontend reporting)
367     *  * response = Response object (e.g. for validation/frontend reporting/form validation)
368     *
369     * @param RequestAbstract  $request  Request
370     * @param ResponseAbstract $response Response
371     * @param mixed            $obj      Response object
372     *
373     * @return void
374     *
375     * @since 1.0.0
376     */
377    public function createStandardRemoveResponse(
378        RequestAbstract $request,
379        ResponseAbstract $response,
380        mixed $obj
381    ) : void
382    {
383        $response->header->set('Content-Type', MimeType::M_JSON . '; charset=utf-8', true);
384        $response->data[$request->uri->__toString()] = [
385            'status'   => NotificationLevel::OK,
386            'title'    => '',
387            'message'  => $this->app->l11nManager->getText($response->header->l11n->language, '0', '0', 'SuccessfulRemove'),
388            'response' => $obj,
389        ];
390    }
391
392    /**
393     * Create standard model return response.
394     *
395     * The response object contains the following data:
396     *
397     *  * status = Response status
398     *  * title = Response title (e.g. for frontend reporting)
399     *  * message = Response message (e.g. for frontend reporting)
400     *  * response = Response object (e.g. for validation/frontend reporting/form validation)
401     *
402     * @param RequestAbstract  $request  Request
403     * @param ResponseAbstract $response Response
404     * @param mixed            $obj      Response object
405     *
406     * @return void
407     *
408     * @since 1.0.0
409     */
410    public function createStandardReturnResponse(
411        RequestAbstract $request,
412        ResponseAbstract $response,
413        mixed $obj
414    ) : void
415    {
416        $response->header->set('Content-Type', MimeType::M_JSON . '; charset=utf-8', true);
417        $response->data[$request->uri->__toString()] = [
418            'status'   => NotificationLevel::OK,
419            'title'    => '',
420            'message'  => $this->app->l11nManager->getText($response->header->l11n->language, '0', '0', 'SuccessfulReturn'),
421            'response' => $obj,
422        ];
423    }
424
425    /**
426     * Create standard model relation add response.
427     *
428     * The response object contains the following data:
429     *
430     *  * status = Response status
431     *  * title = Response title (e.g. for frontend reporting)
432     *  * message = Response message (e.g. for frontend reporting)
433     *  * response = Response object (e.g. for validation/frontend reporting/form validation)
434     *
435     * @param RequestAbstract  $request  Request
436     * @param ResponseAbstract $response Response
437     * @param mixed            $obj      Response object
438     *
439     * @return void
440     *
441     * @since 1.0.0
442     */
443    public function createStandardAddResponse(
444        RequestAbstract $request,
445        ResponseAbstract $response,
446        mixed $obj
447    ) : void
448    {
449        $response->header->set('Content-Type', MimeType::M_JSON . '; charset=utf-8', true);
450        $response->data[$request->uri->__toString()] = [
451            'status'   => NotificationLevel::OK,
452            'title'    => '',
453            'message'  => $this->app->l11nManager->getText($response->header->l11n->language, '0', '0', 'SuccessfulAdd'),
454            'response' => $obj,
455        ];
456    }
457
458    /**
459     * Create invalid model create response.
460     *
461     * The response object contains the following data:
462     *
463     *  * status = Response status
464     *  * title = Response title (e.g. for frontend reporting)
465     *  * message = Response message (e.g. for frontend reporting)
466     *  * response = Response object (e.g. for validation/frontend reporting/form validation)
467     *
468     * @param RequestAbstract  $request  Request
469     * @param ResponseAbstract $response Response
470     * @param mixed            $obj      Response object
471     *
472     * @return void
473     *
474     * @since 1.0.0
475     */
476    public function createInvalidCreateResponse(
477        RequestAbstract $request,
478        ResponseAbstract $response,
479        mixed $obj
480    ) : void
481    {
482        $response->header->set('Content-Type', MimeType::M_JSON . '; charset=utf-8', true);
483        $response->data[$request->uri->__toString()] = [
484            'status'   => NotificationLevel::WARNING,
485            'title'    => '',
486            'message'  => $this->app->l11nManager->getText($response->header->l11n->language, '0', '0', 'InvalidCreate'),
487            'response' => $obj,
488        ];
489    }
490
491    /**
492     * Create invalid model update response.
493     *
494     * The response object contains the following data:
495     *
496     *  * status = Response status
497     *  * title = Response title (e.g. for frontend reporting)
498     *  * message = Response message (e.g. for frontend reporting)
499     *  * response = Response object (e.g. for validation/frontend reporting/form validation)
500     *
501     * @param RequestAbstract  $request  Request
502     * @param ResponseAbstract $response Response
503     * @param mixed            $obj      Response object
504     *
505     * @return void
506     *
507     * @since 1.0.0
508     */
509    public function createInvalidUpdateResponse(
510        RequestAbstract $request,
511        ResponseAbstract $response,
512        mixed $obj
513    ) : void
514    {
515        $response->header->set('Content-Type', MimeType::M_JSON . '; charset=utf-8', true);
516        $response->data[$request->uri->__toString()] = [
517            'status'   => NotificationLevel::WARNING,
518            'title'    => '',
519            'message'  => $this->app->l11nManager->getText($response->header->l11n->language, '0', '0', 'InvalidUpdate'),
520            'response' => $obj,
521        ];
522    }
523
524    /**
525     * Create invalid model delete response.
526     *
527     * The response object contains the following data:
528     *
529     *  * status = Response status
530     *  * title = Response title (e.g. for frontend reporting)
531     *  * message = Response message (e.g. for frontend reporting)
532     *  * response = Response object (e.g. for validation/frontend reporting/form validation)
533     *
534     * @param RequestAbstract  $request  Request
535     * @param ResponseAbstract $response Response
536     * @param mixed            $obj      Response object
537     *
538     * @return void
539     *
540     * @since 1.0.0
541     */
542    public function createInvalidDeleteResponse(
543        RequestAbstract $request,
544        ResponseAbstract $response,
545        mixed $obj
546    ) : void
547    {
548        // @todo: consider to set different status code? (also for other createInvalid() functions)
549        $response->header->set('Content-Type', MimeType::M_JSON . '; charset=utf-8', true);
550        $response->data[$request->uri->__toString()] = [
551            'status'   => NotificationLevel::WARNING,
552            'title'    => '',
553            'message'  => $this->app->l11nManager->getText($response->header->l11n->language, '0', '0', 'InvalidDelete'),
554            'response' => $obj,
555        ];
556    }
557
558    /**
559     * Create invalid model relation remove response.
560     *
561     * The response object contains the following data:
562     *
563     *  * status = Response status
564     *  * title = Response title (e.g. for frontend reporting)
565     *  * message = Response message (e.g. for frontend reporting)
566     *  * response = Response object (e.g. for validation/frontend reporting/form validation)
567     *
568     * @param RequestAbstract  $request  Request
569     * @param ResponseAbstract $response Response
570     * @param mixed            $obj      Response object
571     *
572     * @return void
573     *
574     * @since 1.0.0
575     */
576    public function createInvalidRemoveResponse(
577        RequestAbstract $request,
578        ResponseAbstract $response,
579        mixed $obj
580    ) : void
581    {
582        $response->header->set('Content-Type', MimeType::M_JSON . '; charset=utf-8', true);
583        $response->data[$request->uri->__toString()] = [
584            'status'   => NotificationLevel::WARNING,
585            'title'    => '',
586            'message'  => $this->app->l11nManager->getText($response->header->l11n->language, '0', '0', 'InvalidRemove'),
587            'response' => $obj,
588        ];
589    }
590
591    /**
592     * Create invalid model return response.
593     *
594     * The response object contains the following data:
595     *
596     *  * status = Response status
597     *  * title = Response title (e.g. for frontend reporting)
598     *  * message = Response message (e.g. for frontend reporting)
599     *  * response = Response object (e.g. for validation/frontend reporting/form validation)
600     *
601     * @param RequestAbstract  $request  Request
602     * @param ResponseAbstract $response Response
603     * @param mixed            $obj      Response object
604     *
605     * @return void
606     *
607     * @since 1.0.0
608     */
609    public function createInvalidReturnResponse(
610        RequestAbstract $request,
611        ResponseAbstract $response,
612        mixed $obj
613    ) : void
614    {
615        $response->header->set('Content-Type', MimeType::M_JSON . '; charset=utf-8', true);
616        $response->data[$request->uri->__toString()] = [
617            'status'   => NotificationLevel::WARNING,
618            'title'    => '',
619            'message'  => $this->app->l11nManager->getText($response->header->l11n->language, '0', '0', 'InvalidReturn'),
620            'response' => $obj,
621        ];
622    }
623
624    /**
625     * Create invalid model relation create response.
626     *
627     * The response object contains the following data:
628     *
629     *  * status = Response status
630     *  * title = Response title (e.g. for frontend reporting)
631     *  * message = Response message (e.g. for frontend reporting)
632     *  * response = Response object (e.g. for validation/frontend reporting/form validation)
633     *
634     * @param RequestAbstract  $request  Request
635     * @param ResponseAbstract $response Response
636     * @param mixed            $obj      Response object
637     *
638     * @return void
639     *
640     * @since 1.0.0
641     */
642    public function createInvalidAddResponse(
643        RequestAbstract $request,
644        ResponseAbstract $response,
645        mixed $obj
646    ) : void
647    {
648        $response->header->set('Content-Type', MimeType::M_JSON . '; charset=utf-8', true);
649        $response->data[$request->uri->__toString()] = [
650            'status'   => NotificationLevel::WARNING,
651            'title'    => '',
652            'message'  => $this->app->l11nManager->getText($response->header->l11n->language, '0', '0', 'InvalidAdd'),
653            'response' => $obj,
654        ];
655    }
656
657    /**
658     * Create invalid model permission response.
659     *
660     * The response object contains the following data:
661     *
662     *  * status = Response status
663     *  * title = Response title (e.g. for frontend reporting)
664     *  * message = Response message (e.g. for frontend reporting)
665     *  * response = Response object (e.g. for validation/frontend reporting/form validation)
666     *
667     * @param RequestAbstract  $request  Request
668     * @param ResponseAbstract $response Response
669     * @param mixed            $obj      Response object
670     *
671     * @return void
672     *
673     * @since 1.0.0
674     */
675    public function createInvalidPermissionResponse(
676        RequestAbstract $request,
677        ResponseAbstract $response,
678        mixed $obj
679    ) : void
680    {
681        $response->header->set('Content-Type', MimeType::M_JSON . '; charset=utf-8', true);
682        $response->data[$request->uri->__toString()] = [
683            'status'   => NotificationLevel::WARNING,
684            'title'    => '',
685            'message'  => $this->app->l11nManager->getText($response->header->l11n->language, '0', '0', 'InvalidPermission'),
686            'response' => $obj,
687        ];
688    }
689
690    /**
691     * Fills the response object
692     *
693     * @param RequestAbstract  $request  Request
694     * @param ResponseAbstract $response Response
695     * @param mixed            $obj      Response object
696     *
697     * @return void
698     *
699     * @since 1.0.0
700     */
701    protected function fillJsonRawResponse(RequestAbstract $request, ResponseAbstract $response, mixed $obj) : void
702    {
703        $response->header->set('Content-Type', MimeType::M_JSON . '; charset=utf-8', true);
704        $response->data[$request->uri->__toString()] = $obj;
705    }
706
707    /**
708     * Create a model
709     *
710     *  1. Execute pre DB interaction event
711     *  2. Create model in DB
712     *  3. Execute post DB interaction event (e.g. generates an audit log)
713     *
714     * @param int               $account Account id
715     * @param mixed             $obj     Response object
716     * @param string | \Closure $mapper  Object mapper
717     * @param string            $trigger Trigger for the event manager
718     * @param string            $ip      Ip
719     *
720     * @return void
721     *
722     * @todo find a way to offload this to the cli in a different process (same for other similar functions)
723     *
724     * @since 1.0.0
725     */
726    protected function createModel(int $account, mixed $obj, string | \Closure $mapper, string $trigger, string $ip) : void
727    {
728        $trigger = static::NAME . '-' . $trigger . '-create';
729
730        $this->app->eventManager->triggerSimilar('PRE:Module:' . $trigger, '', $obj);
731        $id = 0;
732
733        if (\is_string($mapper)) {
734            $id = $mapper::create()->execute($obj);
735        } else {
736            $mapper();
737        }
738
739        $data = [
740            $account,
741            null, $obj,
742            StringUtils::intHash(\is_string($mapper) ? $mapper : \get_class($mapper)), $trigger,
743            static::NAME,
744            (string) $id,
745            null,
746            $ip,
747        ];
748
749        /** @phpstan-ignore-next-line */
750        self::$auditor?->eventLogCreate(...$data);
751        $this->app->eventManager->triggerSimilar('POST:Module:' . $trigger, '', $data);
752    }
753
754    /**
755     * Create a model
756     *
757     *  1. Execute pre DB interaction event
758     *  2. Create model in DB
759     *  3. Execute post DB interaction event (e.g. generates an audit log)
760     *
761     * @param int               $account Account id
762     * @param array             $objs    Response object
763     * @param string | \Closure $mapper  Object mapper
764     * @param string            $trigger Trigger for the event manager
765     * @param string            $ip      Ip
766     *
767     * @return void
768     *
769     * @since 1.0.0
770     */
771    protected function createModels(int $account, array $objs, string | \Closure $mapper, string $trigger, string $ip) : void
772    {
773        $trigger = static::NAME . '-' . $trigger . '-create';
774
775        foreach ($objs as $obj) {
776            $this->app->eventManager->triggerSimilar('PRE:Module:' . $trigger, '', $obj);
777            $id = 0;
778
779            if (\is_string($mapper)) {
780                $id = $mapper::create()->execute($obj);
781            } else {
782                $mapper();
783            }
784
785            $data = [
786                $account,
787                null, $obj,
788                StringUtils::intHash(\is_string($mapper) ? $mapper : \get_class($mapper)), $trigger,
789                static::NAME,
790                (string) $id,
791                null,
792                $ip,
793            ];
794
795            /** @phpstan-ignore-next-line */
796            self::$auditor?->eventLogCreate(...$data);
797            $this->app->eventManager->triggerSimilar('POST:Module:' . $trigger, '', $data);
798        }
799    }
800
801    /**
802     * Update a model
803     *
804     *  1. Execute pre DB interaction event
805     *  2. Update model in DB
806     *  3. Execute post DB interaction event (e.g. generates an audit log)
807     *
808     * @param int               $account Account id
809     * @param mixed             $old     Response object old
810     * @param mixed             $new     Response object new
811     * @param string | \Closure $mapper  Object mapper
812     * @param string            $trigger Trigger for the event manager
813     * @param string            $ip      Ip
814     *
815     * @return void
816     *
817     * @since 1.0.0
818     */
819    protected function updateModel(int $account, mixed $old, mixed $new, string | \Closure $mapper, string $trigger, string $ip) : void
820    {
821        $trigger = static::NAME . '-' . $trigger . '-update';
822
823        $this->app->eventManager->triggerSimilar('PRE:Module:' . $trigger, '', $old);
824        $id = 0;
825
826        if (\is_string($mapper)) {
827            $id = $mapper::update()->execute($new);
828        } else {
829            $mapper();
830        }
831
832        $data = [
833            $account,
834            $old, $new,
835            StringUtils::intHash(\is_string($mapper) ? $mapper : \get_class($mapper)), $trigger,
836            static::NAME,
837            (string) $id,
838            null,
839            $ip,
840        ];
841
842        /** @phpstan-ignore-next-line */
843        self::$auditor?->eventLogUpdate(...$data);
844        $this->app->eventManager->triggerSimilar('POST:Module:' . $trigger, '', $data);
845    }
846
847    /**
848     * Delete a model
849     *
850     *  1. Execute pre DB interaction event
851     *  2. Delete model in DB
852     *  3. Execute post DB interaction event (e.g. generates an audit log)
853     *
854     * @param int               $account Account id
855     * @param mixed             $obj     Response object
856     * @param string | \Closure $mapper  Object mapper
857     * @param string            $trigger Trigger for the event manager
858     * @param string            $ip      Ip
859     *
860     * @return void
861     *
862     * @since 1.0.0
863     */
864    protected function deleteModel(int $account, mixed $obj, string | \Closure $mapper, string $trigger, string $ip) : void
865    {
866        $trigger = static::NAME . '-' . $trigger . '-delete';
867
868        $this->app->eventManager->triggerSimilar('PRE:Module:' . $trigger, '', $obj);
869        $id = 0;
870
871        if (\is_string($mapper)) {
872            $id = $mapper::delete()->execute($obj);
873        } else {
874            $mapper();
875        }
876
877        $data = [
878            $account,
879            $obj,  null,
880            StringUtils::intHash(\is_string($mapper) ? $mapper : \get_class($mapper)), $trigger,
881            static::NAME,
882            (string) $id,
883            null,
884            $ip,
885        ];
886
887        /** @phpstan-ignore-next-line */
888        self::$auditor?->eventLogDelete(...$data);
889        $this->app->eventManager->triggerSimilar('POST:Module:' . $trigger, '', $data);
890    }
891
892    /**
893     * Create a model relation
894     *
895     *  1. Execute pre DB interaction event
896     *  2. Create model relation in DB
897     *  3. Execute post DB interaction event (e.g. generates an audit log)
898     *
899     * @param int    $account Account id
900     * @param mixed  $rel1    Object relation1 (parent object)
901     * @param mixed  $rel2    Object relation2
902     * @param string $mapper  Object mapper
903     * @param string $field   Relation field
904     * @param string $trigger Trigger for the event manager
905     * @param string $ip      Ip
906     *
907     * @return void
908     *
909     * @since 1.0.0
910     */
911    protected function createModelRelation(
912        int $account,
913        mixed $rel1,
914        mixed $rel2,
915        string $mapper,
916        string $field,
917        string $trigger,
918        string $ip
919    ) : void
920    {
921        $trigger = static::NAME . '-' . $trigger . '-relation-create';
922
923        $this->app->eventManager->triggerSimilar('PRE:Module:' . $trigger, '', $rel1);
924        $mapper::writer()->createRelationTable($field, \is_array($rel2) ? $rel2 : [$rel2], $rel1);
925
926        $data = [
927            $account,
928            '', [$rel1 => $rel2],
929            StringUtils::intHash($mapper), $trigger,
930            static::NAME,
931            null,
932            null,
933            $ip,
934        ];
935
936        /** @phpstan-ignore-next-line */
937        self::$auditor?->eventLogRelationCreate(...$data);
938        $this->app->eventManager->triggerSimilar('POST:Module:' . $trigger, '', $data);
939    }
940
941    /**
942     * Delete a model relation
943     *
944     *  1. Execute pre DB interaction event
945     *  2. Delete model in DB
946     *  3. Execute post DB interaction event (e.g. generates an audit log)
947     *
948     * @param int    $account Account id
949     * @param mixed  $rel1    Object relation1
950     * @param mixed  $rel2    Object relation2
951     * @param string $mapper  Object mapper
952     * @param string $field   Relation field
953     * @param string $trigger Trigger for the event manager
954     * @param string $ip      Ip
955     *
956     * @return void
957     *
958     * @since 1.0.0
959     */
960    protected function deleteModelRelation(int $account, mixed $rel1, mixed $rel2, string $mapper, string $field, string $trigger, string $ip) : void
961    {
962        $trigger = static::NAME . '-' . $trigger . '-relation-delete';
963
964        $this->app->eventManager->triggerSimilar('PRE:Module:' . $trigger, '', $rel1);
965        $mapper::remover()->deleteRelationTable($field, \is_array($rel2) ? $rel2 : [$rel2], $rel1);
966
967        $data = [
968            $account,
969            [$rel1 => $rel2], '',
970            StringUtils::intHash($mapper), $trigger,
971            static::NAME,
972            null,
973            null,
974            $ip,
975        ];
976
977        /** @phpstan-ignore-next-line */
978        self::$auditor?->eventLogRelationDelete(...$data);
979        $this->app->eventManager->triggerSimilar('POST:Module:' . $trigger, '', $data);
980    }
981}