Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
51 / 51
100.00% covered (success)
100.00%
3 / 3
CRAP
100.00% covered (success)
100.00%
1 / 1
ModuleMetadataHydrator
100.00% covered (success)
100.00%
50 / 50
100.00% covered (success)
100.00%
3 / 3
19
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 hydrateFromRow
100.00% covered (success)
100.00%
42 / 42
100.00% covered (success)
100.00%
1 / 1
13
 resolveAllowedHosts
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
5
1<?php
2
3declare(strict_types=1);
4
5/** @license For full copyright and license information, please see the LICENSE.md file. */
6
7namespace App\Core\Engine\Domain\Model\Support;
8
9defined('AMMONLY_APP') || exit('Direct script access is forbidden.');
10
11use App\Core\Engine\Domain\Model\ModuleMetadata;
12
13/**
14 * Module Metadata Hydrator.
15 *
16 * Hydrates immutable ModuleMetadata value objects from raw database row arrays.
17 *
18 * @package App\Core\Engine\Domain\Model\Support
19 */
20final readonly class ModuleMetadataHydrator
21{
22    private ModuleExtensionTabCatalog $tabCatalog;
23
24    /**
25     * ModuleMetadataHydrator constructor.
26     *
27     * @param ModuleExtensionTabCatalog|null $tabCatalog Extension tab catalog helper.
28     */
29    public function __construct(
30        ?ModuleExtensionTabCatalog $tabCatalog = null,
31    ) {
32        $this->tabCatalog = $tabCatalog ?? new ModuleExtensionTabCatalog();
33    }
34
35    /**
36     * Creates a ModuleMetadata instance from a raw database row array.
37     *
38     * @param array<string, mixed> $row Raw database row.
39     * @return ModuleMetadata Hydrated ModuleMetadata value object.
40     */
41    public function hydrateFromRow(array $row): ModuleMetadata
42    {
43        $iconClass = isset($row['icon_class']) && (string) $row['icon_class'] !== ''
44            ? (string) $row['icon_class']
45            : ModuleMetadata::DEFAULT_ICON;
46
47        $name = (string) $row['name'];
48        $type = (string) $row['type'];
49
50        return new ModuleMetadata(
51            id:                     (int) $row['id'],
52            type:                   $type,
53            name:                   $name,
54            label:                  (string) ($row['label'] ?? ''),
55            routeUrl:               (string) ($row['route_url'] ?? ''),
56            apiEndpoint:            (string) ($row['api_endpoint'] ?? ''),
57            iconClass:              $iconClass,
58            version:                (string) ($row['version'] ?? '1.0.0'),
59            isActive:               isset($row['is_active']) ? (bool) $row['is_active'] : true,
60            description:            (string) ($row['description']  ?? ''),
61            tableName:              (string) ($row['table_name']   ?? ''),
62            tableAlias:             (string) ($row['table_alias']  ?? ''),
63            primaryKey:             (string) ($row['primary_key']  ?? 'id'),
64            hasList:                isset($row['has_list']) ? (bool) $row['has_list'] : true,
65            hasGrid:                isset($row['has_grid']) ? (bool) $row['has_grid'] : true,
66            hasCalendar:            isset($row['has_calendar']) ? (bool) $row['has_calendar'] : false,
67            hasKanban:              isset($row['has_kanban'])
68                ? (bool) $row['has_kanban']
69                : in_array($name, ['projects', 'project_stages', 'project_tasks', 'tickets'], true),
70            kanbanFieldName:        isset($row['kanban_field_name']) && (string) $row['kanban_field_name'] !== ''
71                ? (string) $row['kanban_field_name']
72                : null,
73            hasGantt:               isset($row['has_gantt'])
74                ? (bool) $row['has_gantt']
75                : ($name === 'projects'),
76            hasInventory:           isset($row['has_inventory']) ? (bool) $row['has_inventory'] : false,
77            defaultView:            (string) ($row['default_view'] ?? 'list'),
78            defaultCreateMode:      (string) ($row['default_create_mode'] ?? 'standard'),
79            createPresentationMode: (string) ($row['create_presentation_mode'] ?? 'drawer'),
80            extensionTabs:          $this->tabCatalog->resolveTabs(
81                $name,
82                $type,
83                isset($row['has_inventory']) && (bool) $row['has_inventory']
84            ),
85            allowedHosts:           $this->resolveAllowedHosts($row['allowed_hosts'] ?? null),
86        );
87    }
88
89    /**
90     * Resolves allowed hosts array from raw value.
91     *
92     * @param mixed $rawHosts Raw allowed hosts payload.
93     * @return array<int|string> Allowed hosts array.
94     */
95    public function resolveAllowedHosts(mixed $rawHosts): array
96    {
97        if (is_array($rawHosts)) {
98            return $rawHosts;
99        }
100
101        if (is_string($rawHosts) && $rawHosts !== '') {
102            $decoded = json_decode($rawHosts, true);
103            if (is_array($decoded)) {
104                return $decoded;
105            }
106        }
107
108        return [1];
109    }
110}