Lines 0.00% 0 / 406
Methods 0.00% 0 / 38
Classes 0.00% 0 / 1
Name Lines Methods CRAP
 setupMapping 0.00% 0 / 131 0.00% 0 / 1 2
 deleteReferencesFn 0.00% 0 / 9 0.00% 0 / 1 20
 preSetup 0.00% 0 / 8 0.00% 0 / 1 12
 deleteEntity 0.00% 0 / 5 0.00% 0 / 1 6
 clearEntity 0.00% 0 / 5 0.00% 0 / 1 6
 [BO\Zmsdldb\Importer\MySQL\Entity\Base] __construct 0.00% 0 / 10 0.00% 0 / 1 12
 [BO\Zmsdldb\Importer\MySQL\Entity\Base] entityNeedsUpdate 0.00% 0 / 8 0.00% 0 / 1 6
 [BO\Zmsdldb\Importer\MySQL\Entity\Base] setStatus 0.00% 0 / 1 0.00% 0 / 1 2
 [BO\Zmsdldb\Importer\MySQL\Entity\Base] getStatus 0.00% 0 / 1 0.00% 0 / 1 2
 [BO\Zmsdldb\Importer\MySQL\Entity\Base] getReferenceMapping 0.00% 0 / 5 0.00% 0 / 1 12
 [BO\Zmsdldb\Importer\MySQL\Entity\Base] postSetup 0.00% 0 / 1 0.00% 0 / 1 2
 [BO\Zmsdldb\Importer\MySQL\Entity\Base] preSetupFields 0.00% 0 / 1 0.00% 0 / 1 2
 [BO\Zmsdldb\Importer\MySQL\Entity\Base] postSetupFields 0.00% 0 / 1 0.00% 0 / 1 2
 [BO\Zmsdldb\Importer\MySQL\Entity\Base] setupFields 0.00% 0 / 12 0.00% 0 / 1 30
 [BO\Zmsdldb\Importer\MySQL\Entity\Base] getReferenceFields 0.00% 0 / 4 0.00% 0 / 1 6
 [BO\Zmsdldb\Importer\MySQL\Entity\Base] setupReferences 0.00% 0 / 39 0.00% 0 / 1 182
 [BO\Zmsdldb\Importer\MySQL\Entity\Base] __set 0.00% 0 / 9 0.00% 0 / 1 42
 [BO\Zmsdldb\Importer\MySQL\Entity\Base] addReference 0.00% 0 / 4 0.00% 0 / 1 12
 [BO\Zmsdldb\Importer\MySQL\Entity\Base] __get 0.00% 0 / 5 0.00% 0 / 1 12
 [BO\Zmsdldb\Importer\MySQL\Entity\Base] __isset 0.00% 0 / 1 0.00% 0 / 1 6
 [BO\Zmsdldb\Importer\MySQL\Entity\Base] __unset 0.00% 0 / 4 0.00% 0 / 1 12
 [BO\Zmsdldb\Importer\MySQL\Entity\Base] offsetExists 0.00% 0 / 1 0.00% 0 / 1 6
 [BO\Zmsdldb\Importer\MySQL\Entity\Base] offsetGet 0.00% 0 / 3 0.00% 0 / 1 6
 [BO\Zmsdldb\Importer\MySQL\Entity\Base] offsetSet 0.00% 0 / 4 0.00% 0 / 1 6
 [BO\Zmsdldb\Importer\MySQL\Entity\Base] offsetUnset 0.00% 0 / 4 0.00% 0 / 1 6
 [BO\Zmsdldb\Importer\MySQL\Entity\Base] count 0.00% 0 / 1 0.00% 0 / 1 2
 [BO\Zmsdldb\Importer\MySQL\Entity\Base] jsonSerialize 0.00% 0 / 1 0.00% 0 / 1 2
 [BO\Zmsdldb\Importer\MySQL\Entity\Base] getFields 0.00% 0 / 1 0.00% 0 / 1 2
 [BO\Zmsdldb\Importer\MySQL\Entity\Base] get 0.00% 0 / 21 0.00% 0 / 1 90
 [BO\Zmsdldb\Importer\MySQL\Entity\Base] arrayAccessByDotPerpareKeys 0.00% 0 / 10 0.00% 0 / 1 20
 [BO\Zmsdldb\Importer\MySQL\Entity\Base] save 0.00% 0 / 6 0.00% 0 / 1 12
 [BO\Zmsdldb\Importer\MySQL\Entity\Base] saveEntitiy 0.00% 0 / 15 0.00% 0 / 1 42
 [BO\Zmsdldb\Importer\MySQL\Entity\Base] saveReferences 0.00% 0 / 6 0.00% 0 / 1 20
 [BO\Zmsdldb\Importer\MySQL\Entity\Base] delete 0.00% 0 / 4 0.00% 0 / 1 6
 [BO\Zmsdldb\Importer\MySQL\Entity\Base] deleteReferences 0.00% 0 / 27 0.00% 0 / 1 156
 [BO\Zmsdldb\Importer\MySQL\Entity\Base] deleteWith 0.00% 0 / 10 0.00% 0 / 1 12
 [BO\Zmsdldb\Importer\MySQL\Entity\Base] clearEntityReferences 0.00% 0 / 22 0.00% 0 / 1 72
 [BO\Zmsdldb\Importer\MySQL\Entity\Base] getTableName 0.00% 0 / 6 0.00% 0 / 1 6
5class Topic extends Base
6{
7    protected array $fieldMapping = [
8        'id' => 'id',
9        'name' => 'name',
10        'meta.locale' => 'locale',
11        'path' => 'path',
12        'relation.navi' => 'navi',
13        'relation.root' => 'root',
14        'relation.rank' => 'rank',
15        '__RAW__' => 'data_json'
16    ];
17
18    /**
19     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
20     */
21    #[\Override]
22    protected function setupMapping(): void
23    {
24        $this->referanceMapping = [
25            'meta' => [
26                'class' => Meta::class,
27                'neededFields' => [
28                    'id' => 'object_id',
29                    'meta.locale' => 'locale'
30                ],
31                'addFields' => [
32                    'type' => static::getTableName()
33                ],
34                'deleteFields' => [
35                    'object_id' => $this->get('id'),
36                    'locale' => $this->get('meta.locale'),
37                    'type' => static::getTableName()
38                ],
39                'multiple' => false,
40                'clearFields' => [
41                    'type' => static::getTableName(),
42                    'locale' => $this->get('meta.locale')
43                ],
44            ],
45            'name' => [
46                'class' => Search::class,
47                'neededFields' => [
48                    'id' => 'object_id',
49                    'meta.locale' => 'locale',
50                    'name' => 'search_value'
51                ],
52                'addFields' => [
53                    'entity_type' => static::getTableName(),
54                    'search_type' => 'name'
55                ],
56                'multiple' => false,
57                'clearFields' => [
58                    'entity_type' => static::getTableName(),
59                    'locale' => $this->get('meta.locale')
60                ],
61                'deleteFields' => [
62                    'object_id' => $this->get('id'),
63                    'locale' => $this->get('meta.locale'),
64                    'entity_type' => static::getTableName()
65                ],
66                'selfAsArray' => true
67            ],
68            'meta.keywords' => [
69                'class' => Search::class,
70                'neededFields' => [
71                    'id' => 'object_id',
72                    'meta.locale' => 'locale',
73                    'meta.keywords' => 'search_value',
74                ],
75                'addFields' => [
76                    'entity_type' => static::getTableName(),
77                    'search_type' => 'keywords'
78                ],
79                'deleteFields' => [
80                    'object_id' => $this->get('id'),
81                    'locale' => $this->get('meta.locale'),
82                    'entity_type' => static::getTableName()
83                ],
84                'multiple' => false,
85                'clearFields' => [
86                    'entity_type' => static::getTableName(),
87                    'locale' => $this->get('meta.locale')
88                ],
89                'selfAsArray' => true
90            ],
91            'meta.titles' => [
92                'class' => Search::class,
93                'neededFields' => [
94                    'id' => 'object_id',
95                    'meta.locale' => 'locale',
96                    'meta.titles' => 'search_value'
97                ],
98                'addFields' => [
99                    'entity_type' => static::getTableName(),
100                    'search_type' => 'titles'
101                ],
102                'deleteFields' => [
103                    'object_id' => $this->get('id'),
104                    'locale' => $this->get('locale'),
105                    'entity_type' => static::getTableName()
106                ],
107                'multiple' => false,
108                'clearFields' => [
109                    'entity_type' => static::getTableName(),
110                    'locale' => $this->get('locale')
111                ],
112                'selfAsArray' => true
113            ],
114            'links' => [
115                'class' => TopicLinks::class,
116                'neededFields' => ['id' => 'topic_id', 'meta.locale' => 'locale'],
117                'addFields' => ['locale' => $this->get('meta.locale')],
118                'delete' => false,
119                'deleteFunction' => function (\BO\Zmsdldb\Importer\MySQL\Entity\Topic $topic): bool {
120                    return static::deleteReferencesFn(
121                        $topic,
122                        \BO\Zmsdldb\Importer\MySQL\Entity\TopicLinks::getTableName(),
123                        'topic_id'
124                    );
125                },
126                'clearFields' => [
127                    'locale' => $this->get('meta.locale')
128                ]
129            ],
130            'relation.services' => [
131                'class' => TopicService::class,
132                'neededFields' => ['id' => 'topic_id'],
133                'addFields' => [],
134                'deleteFunction' => function (\BO\Zmsdldb\Importer\MySQL\Entity\Topic $topic): bool {
135                    return static::deleteReferencesFn(
136                        $topic,
137                        \BO\Zmsdldb\Importer\MySQL\Entity\TopicService::getTableName(),
138                        'topic_id'
139                    );
140                }
141            ],
142            'relation.childs' => [
143                'class' => TopicCluster::class,
144                'neededFields' => ['id' => 'parent_id'],
145                'addFields' => [],
146                'deleteFunction' => function (\BO\Zmsdldb\Importer\MySQL\Entity\Topic $topic): bool {
147                    return static::deleteReferencesFn(
148                        $topic,
149                        \BO\Zmsdldb\Importer\MySQL\Entity\TopicCluster::getTableName(),
150                        'parent_id'
151                    );
152                }
153            ]
154        ];
155    }
156
157    protected static function deleteReferencesFn(
158        \BO\Zmsdldb\Importer\MySQL\Entity\Topic $topic,
159        string $tableName,
160        string $whereField
161    ): bool {
162        $topicId = $topic->get('id');
163        try {
164            $sql = "DELETE FROM " . $tableName . " WHERE " . $whereField . " = ?";
165            $stm = $topic->getPDOAccess()->prepare($sql);
166
167            $stm->execute([$topicId]);
168            if ($stm && 0 < $stm->rowCount()) {
169                return true;
170            }
171            return false;
172        } catch (\Exception $e) {
173            throw $e;
174        }
175    }
176
177    #[\Override]
178    public function preSetup(): void
179    {
180        try {
181            $this->setStatus(static::STATUS_OLD);
182            if ($this->entityNeedsUpdate()) {
183                $this->setStatus(static::STATUS_NEW);
184                $this->setupFields();
185                $this->deleteEntity();
186                $this->deleteReferences();
187            }
188        } catch (\Exception $e) {
189            throw $e;
190        }
191    }
192
193    #[\Override]
194    public function deleteEntity(): void
195    {
196        try {
197            $this->deleteWith(
198                array_combine(['id', 'locale'], array_values($this->get(['id', 'meta.locale'])))
199            );
200        } catch (\Exception $e) {
201            throw $e;
202        }
203    }
204
205    #[\Override]
206    public function clearEntity(array $addWhere = []): void
207    {
208        try {
209            $this->deleteWith(
210                ['locale' => $this->get('meta.locale')]
211            );
212        } catch (\Exception $e) {
213            throw $e;
214        }
215    }
216}

Inherited from BO\Zmsdldb\Importer\MySQL\Entity\Base

45    public function __construct(PDOAccess $mySqlAccess, array $dataRaw = [], bool $setup = true)
46    {
47        try {
48            $this->pdoAccess = $mySqlAccess;
49            $this->dataRaw = $dataRaw;
50
51            if (true === $setup) {
52                $this->setupMapping();
53
54                $this->preSetup();
55
56                $this->setupFields();
57
58                $this->setupReferences();
59
60                $this->postSetup();
61            }
62        } catch (\Exception $e) {
63            throw $e;
64        }
65    }
67    protected function entityNeedsUpdate(): bool
68    {
69        $fields = $this->get(['id', 'meta.locale', 'meta.hash']);
70        $hash = $fields['meta.hash'] ?? '';
71
72        return $this->itemNeedsUpdate(
73            (int) ($fields['id'] ?? 0),
74            (string) ($fields['meta.locale'] ?? ''),
75            is_scalar($hash) ? (string) $hash : '',
76            static::getTableName()
77        );
78    }
80    public function setStatus(int $status = Base::STATUS_NEW): void
81    {
82        $this->status = $status;
83    }
85    public function getStatus(): int
86    {
87        return $this->status;
88    }
90    public function getReferenceMapping(bool $setup = false): array
91    {
92        try {
93            if (true === $setup) {
94                $this->setupMapping();
95            }
96
97            return $this->referanceMapping;
98        } catch (\Exception $e) {
99            throw $e;
100        }
101    }
111    public function postSetup(): void
112    {
113    }
115    public function preSetupFields(): void
116    {
117    }
119    public function postSetupFields(): void
120    {
121    }
123    final public function setupFields(): void
124    {
125        try {
126            if (false === $this->setupFields) {
127                return;
128            }
129            $this->preSetupFields();
130
131            $values = $this->get(array_keys(array_filter($this->fieldMapping)));
132            foreach ($values as $key => $value) {
133                if (!is_string($key)) {
134                    continue;
135                }
136                $this->__set($key, $value);
137            }
138            $this->postSetupFields();
139            $this->setupFields = false;
140        } catch (\Exception $e) {
141            throw $e;
142        }
143    }
145    protected function getReferenceFields(): array
146    {
147        $referenceFields = array_flip(array_keys(array_filter($this->referanceMapping)));
148
149        foreach (array_keys($referenceFields) as $name) {
150            $referenceFields[$name] = $this->get($name);
151        }
152        return $referenceFields;
153    }
155    final public function setupReferences(): void
156    {
157        try {
158            if (false === $this->setupReferences) {
159                return;
160            }
161            $values = $this->getReferenceFields();
162
163            foreach ($values as $name => $references) {
164                $referenceEntityClass = $this->referanceMapping[$name]['class'];
165                if (!is_string($referenceEntityClass)) {
166                    throw new \InvalidArgumentException('Invalid reference entity class');
167                }
168                /** @var class-string<Base> $referenceEntityClass */
169                $addFields = [];
170
171                foreach (($this->referanceMapping[$name]['neededFields'] ?? []) as $sourceKey => $destinationKey) {
172                    $addFields[$destinationKey] = $this->get($sourceKey);
173                }
174                $isMultiple = $this->referanceMapping[$name]['multiple'] ?? true;
175
176                if (false === $isMultiple) {
177                    $references = [$references];
178                }
179
180                $position = 0;
181                foreach (($references ?? []) as $reference) {
182                    foreach ($this->referanceMapping[$name]['addFields'] as $key => $value) {
183                        if (is_callable($value)) {
184                            $addFields[$key] = call_user_func_array($value, [$position, $name, $reference]);
185                        } else {
186                            $addFields[$key] = $value;
187                        }
188                    }
189                    if (true === ($this->referanceMapping[$name]['selfAsArray'] ?? false)) {
190                        $reference = [
191                            $name => $reference
192                        ];
193                    }
194                    if (!is_array($reference)) {
195                        $reference = [];
196                    }
197                    /** @psalm-suppress UnsafeInstantiation */
198                    $referencesInstance = new $referenceEntityClass(
199                        $this->getPDOAccess(),
200                        array_merge(
201                            $reference,
202                            $addFields
203                        )
204                    );
205                    if (!$referencesInstance instanceof Base) {
206                        throw new \InvalidArgumentException($referenceEntityClass . ' must extend ' . Base::class);
207                    }
208
209                    $this->addReference($name, $referencesInstance);
210                    $position++;
211                }
212            }
213            $this->setupReferences = false;
214        } catch (\Exception $e) {
215            throw $e;
216        }
217    }
219    final public function __set(string $name, mixed $value): void
220    {
221        if (array_key_exists($name, $this->fieldMapping)) {
222            $name = $this->fieldMapping[$name];
223            if (is_bool($value)) {
224                $value = (int)$value;
225            } elseif (false !== stripos($name, '_json')) {
226                $value = json_encode($value);
227            }
228            $this->fields[$name] = $value;
229        } elseif (array_key_exists($name, $this->referanceMapping) && $value instanceof Base) {
230            $this->addReference($name, $value);
231        }
232    }
234    public function addReference(string $name, Base $reference): void
235    {
236        if (array_key_exists($name, $this->referanceMapping)) {
237            if (!isset($this->references[$name])) {
238                $this->references[$name] = new EntityCollection();
239            }
240            $this->references[$name][] = $reference;
241        }
242    }
244    final public function __get(string $name): mixed
245    {
246        if (array_key_exists($name, $this->fields)) {
247            return $this->fields[$name];
248        }
249        if (array_key_exists($name, $this->references)) {
250            return $this->references[$name];
251        }
252        throw new \InvalidArgumentException(__METHOD__ . " {$name} has not been set!");
253    }
255    final public function __isset(string $name): bool
256    {
257        return array_key_exists($name, $this->fields) || array_key_exists($name, $this->references);
258    }
260    final public function __unset(string $name): void
261    {
262        if (array_key_exists($name, $this->fields)) {
263            unset($this->fields[$name]);
264        }
265        if (array_key_exists($name, $this->references)) {
266            unset($this->references[$name]);
267        }
268    }
271    final public function offsetExists($offset): bool
272    {
273        return is_string($offset) && $this->__isset($offset);
274    }
277    final public function offsetGet($offset): mixed
278    {
279        if (!is_string($offset)) {
280            throw new \InvalidArgumentException(__METHOD__ . ' offset must be a string');
281        }
282        return $this->__get($offset);
283    }
286    final public function offsetSet($offset, $value): Base
287    {
288        if (!is_string($offset)) {
289            throw new \InvalidArgumentException(__METHOD__ . ' offset must be a string');
290        }
291        $this->__set($offset, $value);
292        return $this;
293    }
296    final public function offsetUnset($offset): Base
297    {
298        if (!is_string($offset)) {
299            throw new \InvalidArgumentException(__METHOD__ . ' offset must be a string');
300        }
301        $this->__unset($offset);
302        return $this;
303    }
306    final public function count(): int
307    {
308        return count($this->fields);
309    }
312    public function jsonSerialize(): mixed
313    {
314        return $this->fields;
315    }
317    public function getFields(): array
318    {
319        return $this->fields;
320    }
322    public function get(null|array|string $key = null, mixed $default = null): mixed
323    {
324        if (null === $key) {
325            return $this->dataRaw;
326        }
327        $keys = $key;
328        if (!is_array($keys)) {
329            $keys = [$keys];
330        }
331        $values = [];
332
333        foreach ($keys as $key) {
334            if ('__RAW__' == $key) {
335                $values[$key] = $this->dataRaw;
336                continue;
337            }
338            $levels = static::arrayAccessByDotPerpareKeys($key);
339
340            $value = $default;
341
342            $current = $this->dataRaw;
343            $levelsCount = count($levels);
344            for ($i = 0; $i < $levelsCount; ++$i) {
345                if (!is_array($current) || !array_key_exists($levels[$i], $current)) {
346                    continue;
347                }
348                $current = $current[$levels[$i]];
349                $value = $current;
350            }
351            $values[$key] = ($value);
352        }
353        return 1 == count($keys) ? $values[$keys[0]] : $values;
354    }
356    protected static function arrayAccessByDotPerpareKeys(?string $key = null): array
357    {
358        if (null === $key) {
359            return [];
360        }
361        $keys = explode('.', $key);
362        $keys = array_filter($keys, 'strlen');
363        $keys = array_map(static function (string $segment): int|string {
364            if (is_numeric($segment) && !str_contains($segment, '.')) {
365                return (int) $segment;
366            }
367            return $segment;
368        }, $keys);
369
370        return $keys;
371    }
373    public function save(): void
374    {
375        try {
376            if (static::STATUS_NEW !== $this->getStatus()) {
377                return;
378            }
379            $this->saveEntitiy();
380            $this->saveReferences();
381        } catch (\Exception $e) {
382            throw $e;
383        }
384    }
386    final public function saveEntitiy(): void
387    {
388        try {
389            if (static::STATUS_NEW !== $this->getStatus()) {
390                return;
391            }
392            if (!empty($this->fields)) {
393                $sql = 'REPLACE INTO ' . static::getTableName() . ' ';
394                $sql .= '(`' . implode('`, `', array_keys($this->fields)) . '`) ';
395
396                $questionMarks = array_fill(0, count($this->fields), '?');
397                $sql .= 'VALUES (' . implode(', ', $questionMarks) . ') ';
398
399                $stm = $this->getPDOAccess()->prepare($sql);
400
401                $stm->execute(array_values($this->fields));
402
403                if ($stm && 0 < $stm->rowCount()) {
404                    return;
405                }
406                throw new \Exception('Could not save entity');
407            }
408            throw new \Exception('Could not save entity, fields are empty');
409        } catch (\Exception $e) {
410            throw $e;
411        }
412    }
414    final public function saveReferences(): void
415    {
416        try {
417            if (static::STATUS_NEW !== $this->getStatus()) {
418                return;
419            }
420            foreach ($this->references as $referencesCollection) {
421                $referencesCollection->saveEntities();
422            }
423        } catch (\Exception $e) {
424            throw $e;
425        }
426    }
429    public function delete(): void
430    {
431        try {
432            $this->deleteEntity();
433            $this->deleteReferences();
434        } catch (\Exception $e) {
435            throw $e;
436        }
437    }
441    public function deleteReferences(): void
442    {
443        try {
444            foreach ($this->referanceMapping as $name => $mappingData) {
445                if (isset($mappingData['deleteFunction']) && is_callable($mappingData['deleteFunction'])) {
446                    call_user_func_array($mappingData['deleteFunction'], [$this, $name, $mappingData]);
447                    continue;
448                }
449                if (array_key_exists('delete', $mappingData) && false === $mappingData['delete']) {
450                    continue;
451                }
452                if (!array_key_exists('deleteFields', $mappingData) || empty($mappingData['deleteFields'])) {
453                    throw new \Exception(static::class . ' missing $deleteFields in reference mapping');
454                }
455                $addFields = [];
456                $referenceEntityClass = $mappingData['class'];
457                if (!is_string($referenceEntityClass)) {
458                    throw new \InvalidArgumentException('Invalid reference entity class');
459                }
460                /** @var class-string<Base> $referenceEntityClass */
461                foreach ($mappingData['deleteFields'] as $sourceKey => $val) {
462                    $addFields[$sourceKey] = $val;
463                }
464
465                /** @psalm-suppress UnsafeInstantiation */
466                $referencesInstance = new $referenceEntityClass(
467                    $this->getPDOAccess(),
468                    $addFields,
469                    false
470                );
471                if (!$referencesInstance instanceof Base) {
472                    throw new \InvalidArgumentException($referenceEntityClass . ' must extend ' . Base::class);
473                }
474                $referencesInstance->setupFields();
475
476                $referencesInstance->deleteWith(
477                    array_intersect_key($referencesInstance->getFields(), $addFields)
478                );
479            }
480        } catch (\Exception $e) {
481            throw $e;
482        }
483    }
485    final public function deleteWith(array $fields): void
486    {
487        try {
488            $sql = "DELETE FROM " . static::getTableName();
489            if (!empty($fields)) {
490                $where = array_map(function (int|string $field): string {
491                    return $field . ' = ?';
492                }, array_keys($fields));
493                $sql .= " WHERE " . implode(' AND ', $where);
494            }
495
496            $stm = $this->getPDOAccess()->prepare($sql);
497            $stm->execute(array_values($fields));
498        } catch (\Exception $e) {
499            throw $e;
500        }
501    }
512    public function clearEntityReferences(): void
513    {
514        try {
515            foreach ($this->getReferenceMapping(true) as $name => $mappingData) {
516                $referenceEntityClass = $mappingData['class'];
517                if (!is_string($referenceEntityClass)) {
518                    throw new \InvalidArgumentException('Invalid reference entity class');
519                }
520                /** @var class-string<Base> $referenceEntityClass */
521                $clearFields = [];
522                $position = 0;
523                foreach (($mappingData['clearFields'] ?? []) as $key => $value) {
524                    if (is_callable($value)) {
525                        $clearFields[$key] = call_user_func_array($value, [$position++, $name, null]);
526                    } else {
527                        $clearFields[$key] = $value;
528                    }
529                }
530
531                /** @psalm-suppress UnsafeInstantiation */
532                $referencesInstance = new $referenceEntityClass(
533                    $this->getPDOAccess(),
534                    [],
535                    false
536                );
537                if (!$referencesInstance instanceof Base) {
538                    throw new \InvalidArgumentException($referenceEntityClass . ' must extend ' . Base::class);
539                }
540                if (!empty($clearFields)) {
541                    $referencesInstance->deleteWith($clearFields);
542                } else {
543                    $referencesInstance->clearEntity();
544                }
545            }
546        } catch (\Exception $e) {
547            throw $e;
548        }
549    }
551    public static function getTableName(): string
552    {
553        $classNameWithNs = explode("\\", static::class);
554        $className = end($classNameWithNs);
555        $table = defined('static::TABLENAME')
556            ? constant('static::TABLENAME')
557            : preg_replace('/(?<!^)[A-Z]/', '_$0', $className);
558
559        return strtolower((string) $table);
560    }