Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
82.17% covered (warning)
82.17%
106 / 129
57.14% covered (warning)
57.14%
4 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
HostController
82.17% covered (warning)
82.17%
106 / 129
57.14% covered (warning)
57.14%
4 / 7
37.80
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 index
100.00% covered (success)
100.00%
45 / 45
100.00% covered (success)
100.00%
1 / 1
2
 view
70.59% covered (warning)
70.59%
24 / 34
0.00% covered (danger)
0.00%
0 / 1
8.25
 create
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 update
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
4
 delete
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
6
 formatHostRow
76.00% covered (warning)
76.00%
19 / 25
0.00% covered (danger)
0.00%
0 / 1
18.11
1<?php
2
3declare(strict_types=1);
4
5namespace App\Web\Controller;
6
7use App\Domain\Host\Repository\HostApiConfigRepository;
8use App\Domain\Host\Repository\HostDbConfigRepository;
9use App\Domain\Host\Repository\HostRecordRepository;
10use App\Domain\Host\Service\HostConnectionCheckerInterface;
11use App\Domain\Shared\Query\GridQuerySpecification;
12use App\Infrastructure\Shared\Query\GridQueryBuilder;
13use App\Shared\Host\TablePrefixResolver;
14use App\Shared\UI\ListView\ListViewData;
15use Psr\Http\Message\ResponseInterface;
16use Psr\Http\Message\ServerRequestInterface;
17use Yiisoft\Yii\View\Renderer\WebViewRenderer;
18
19 class HostController
20{
21    private const VIEW_INDEX = '//host/index.twig';
22    private const STATUS_NO_CONFIG = '⚪ Brak konfig.';
23
24    public function __construct(private WebViewRenderer $viewRenderer)
25    {
26        $this->viewRenderer = $viewRenderer->withControllerName('host');
27    }
28
29    public function index(
30        ServerRequestInterface $request,
31        HostRecordRepository $repository,
32        HostApiConfigRepository $apiRepo,
33        HostDbConfigRepository $dbRepo,
34        HostConnectionCheckerInterface $checker,
35        GridQueryBuilder $queryBuilder,
36        TablePrefixResolver $prefixResolver
37    ): ResponseInterface {
38        $allowedColumns = [
39            'name' => 'name',
40            'label' => 'label',
41            'db_prefix' => 'db_prefix',
42            'type' => 'type',
43            'url' => 'url',
44            'created_at' => 'created_at',
45        ];
46
47        /** @var array<string, mixed> $queryParams */
48        $queryParams = $request->getQueryParams();
49        $spec = new GridQuerySpecification($queryParams, $allowedColumns, 'created_at', 'DESC');
50        $targetTable = $prefixResolver->resolve('hosts_records');
51        $queryResult = $queryBuilder->fetchData($targetTable, $spec, 'created_at', 'DESC');
52
53        $rawRows = $queryResult['items'];
54        $items = [];
55        foreach ($rawRows as $row) {
56            /** @var array<string, mixed> $row */
57            $items[] = $this->formatHostRow($row, $apiRepo, $dbRepo, $checker);
58        }
59
60        $totalItems = $queryResult['totalCount'];
61
62        $listView = new ListViewData(
63            items: $items,
64            columns: [
65                'name' => 'Nazwa',
66                'label' => 'Etykieta',
67                'db_prefix' => 'Prefix Bazy (Klient)',
68                'type' => 'Typ',
69                'url' => 'Adres URL',
70                'db_status' => 'Baza danych (Status)',
71                'api_status' => 'API (Status)',
72                'created_at' => 'Utworzono',
73            ],
74            currentPage: $spec->getPage(),
75            pageSize: $spec->getPageSize(),
76            totalItems: $totalItems,
77            sortField: $spec->getSortField(),
78            sortDirection: $spec->getSortDirection(),
79            filterParams: $spec->getFilters(),
80            viewRoute: 'host/view',
81            updateRoute: 'host/update',
82            deleteRoute: 'host/delete',
83            tableExists: (bool) ($queryResult['tableExists'] ?? true),
84            tableName: (string) ($queryResult['tableName'] ?? $targetTable)
85        );
86
87        return $this->viewRenderer->render(self::VIEW_INDEX, [
88            'listView' => $listView,
89            'title' => 'Zarządzanie Hostami',
90        ]);
91    }
92
93    public function view(
94        ServerRequestInterface $request,
95        HostRecordRepository $repository,
96        HostApiConfigRepository $apiRepo,
97        HostDbConfigRepository $dbRepo,
98        HostConnectionCheckerInterface $checker
99    ): ResponseInterface {
100        /** @var array<string, mixed> $params */
101        $params = $request->getQueryParams();
102        $id = is_string($params['id'] ?? null) ? (string) $params['id'] : '';
103        $host = $repository->findById($id);
104
105        if ($host === null) {
106            return $this->viewRenderer->render(self::VIEW_INDEX, [
107                'title' => 'Host nie znaleziony',
108                'error' => 'Podany host nie istnieje.',
109            ]);
110        }
111
112        $dbConfig = $dbRepo->findByHostId($host->getId());
113        $apiConfig = $apiRepo->findByHostId($host->getId());
114
115        $dbStatusHtml = self::STATUS_NO_CONFIG;
116        if ($dbConfig !== null) {
117            $dbStatusHtml = $checker->checkDbConnection($dbConfig)
118                ? '<span class="badge bg-success-subtle text-success-emphasis rounded-pill px-2.5 py-1 fs-7">🟢 OK</span>'
119                : '<span class="badge bg-danger-subtle text-danger-emphasis rounded-pill px-2.5 py-1 fs-7">🔴 Błąd</span>';
120        }
121
122        $apiStatusHtml = self::STATUS_NO_CONFIG;
123        if ($apiConfig !== null) {
124            $apiStatusHtml = $checker->checkApiConnection($apiConfig)
125                ? '<span class="badge bg-success-subtle text-success-emphasis rounded-pill px-2.5 py-1 fs-7">🟢 OK</span>'
126                : '<span class="badge bg-danger-subtle text-danger-emphasis rounded-pill px-2.5 py-1 fs-7">🔴 Błąd</span>';
127        }
128
129        return $this->viewRenderer->render('//host/view.twig', [
130            'host' => [
131                'id' => $host->getId(),
132                'name' => $host->getName(),
133                'label' => $host->getLabel(),
134                'db_prefix' => $host->getDbPrefix(),
135                'type' => $host->getType(),
136                'url' => $host->getUrl(),
137            ],
138            'dbStatus' => $dbStatusHtml,
139            'apiStatus' => $apiStatusHtml,
140            'createdAt' => date('Y-m-d H:i:s', $host->getCreatedAt()),
141            'title' => 'Podgląd Hosta: ' . $host->getName(),
142        ]);
143    }
144
145    public function create(ServerRequestInterface $request): ResponseInterface
146    {
147        $_ = $request->getQueryParams();
148        return $this->viewRenderer->render('//host/create.twig', [
149            'title' => 'Dodaj Nowy Host',
150        ]);
151    }
152
153    public function update(
154        ServerRequestInterface $request,
155        HostRecordRepository $repository
156    ): ResponseInterface {
157        /** @var array<string, mixed> $params */
158        $params = $request->getQueryParams();
159        $id = is_string($params['id'] ?? null) ? (string) $params['id'] : '';
160        $host = $repository->findById($id);
161
162        return $this->viewRenderer->render('//host/update.twig', [
163            'host' => $host !== null ? [
164                'id' => $host->getId(),
165                'name' => $host->getName(),
166                'label' => $host->getLabel(),
167                'db_prefix' => $host->getDbPrefix(),
168                'type' => $host->getType(),
169                'url' => $host->getUrl(),
170            ] : null,
171            'title' => 'Edycja Hosta: ' . ($host !== null ? $host->getName() : ''),
172        ]);
173    }
174
175    public function delete(
176        ServerRequestInterface $request,
177        HostRecordRepository $repository
178    ): ResponseInterface {
179        /** @var array<string, mixed> $params */
180        $params = $request->getQueryParams();
181        $id = is_string($params['id'] ?? null) ? (string) $params['id'] : '';
182        $repository->delete($id);
183
184        return $this->viewRenderer->render(self::VIEW_INDEX, [
185            'title' => 'Zarządzanie Hostami',
186            'success' => 'Host został usunięty.',
187        ]);
188    }
189
190    /**
191     * @param array<string, mixed> $row
192     * @return array<string, mixed>
193     */
194    private function formatHostRow(
195        array $row,
196        HostApiConfigRepository $apiRepo,
197        HostDbConfigRepository $dbRepo,
198        HostConnectionCheckerInterface $checker
199    ): array {
200        $hostId = is_string($row['id'] ?? null) ? (string) $row['id'] : '';
201        $dbConfig = $dbRepo->findByHostId($hostId);
202        $apiConfig = $apiRepo->findByHostId($hostId);
203
204        $dbStatusHtml = self::STATUS_NO_CONFIG;
205        if ($dbConfig !== null) {
206            $dbStatusHtml = $checker->checkDbConnection($dbConfig)
207                ? '<span class="badge bg-success">🟢 OK</span>'
208                : '<span class="badge bg-danger">🔴 Błąd</span>';
209        }
210
211        $apiStatusHtml = self::STATUS_NO_CONFIG;
212        if ($apiConfig !== null) {
213            $apiStatusHtml = $checker->checkApiConnection($apiConfig)
214                ? '<span class="badge bg-success">🟢 OK</span>'
215                : '<span class="badge bg-danger">🔴 Błąd</span>';
216        }
217
218        $createdAt = isset($row['created_at']) && is_numeric($row['created_at']) ? (int) $row['created_at'] : time();
219
220        return [
221            'id' => $hostId,
222            'name' => is_string($row['name'] ?? null) ? (string) $row['name'] : '',
223            'label' => isset($row['label']) && is_string($row['label']) ? $row['label'] : '-',
224            'db_prefix' => isset($row['db_prefix']) && is_string($row['db_prefix']) ? $row['db_prefix'] : 'c01',
225            'type' => is_string($row['type'] ?? null) ? (string) $row['type'] : '',
226            'url' => is_string($row['url'] ?? null) ? (string) $row['url'] : '',
227            'db_status' => $dbStatusHtml,
228            'api_status' => $apiStatusHtml,
229            'created_at' => date('Y-m-d H:i:s', $createdAt),
230        ];
231    }
232}