Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
36 / 36
100.00% covered (success)
100.00%
4 / 4
CRAP
100.00% covered (success)
100.00%
1 / 1
ModuleBuilderWebController
100.00% covered (success)
100.00%
35 / 35
100.00% covered (success)
100.00%
4 / 4
6
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
 actionNew
100.00% covered (success)
100.00%
16 / 16
100.00% covered (success)
100.00%
1 / 1
2
 actionEdit
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
1 / 1
2
 htmlResponse
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
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\ModuleBuilder\Presentation\Web;
8
9defined('AMMONLY_APP') || exit('Direct script access is forbidden.');
10
11use App\Core\Engine\Domain\Model\PermissionContext;
12use App\Core\ModuleBuilder\Application\Service\ModuleBuilderServiceInterface;
13use Nyholm\Psr7\Factory\Psr17Factory;
14use Psr\Http\Message\ResponseInterface;
15use Twig\Environment as TwigEnvironment;
16
17/**
18 * Web Controller rendering the interactive Module & Field Builder wizard views.
19 *
20 * @package App\Core\ModuleBuilder\Presentation\Web
21 */
22final readonly class ModuleBuilderWebController
23{
24    private const string HTML_CONTENT_TYPE = 'text/html; charset=UTF-8';
25
26    /**
27     * @param ModuleBuilderServiceInterface $builderService Module builder service.
28     * @param TwigEnvironment               $twig           Twig template engine.
29     * @param Psr17Factory                  $psr17          PSR-17 response factory.
30     * @param string                        $appProfile     Active application profile.
31     */
32    public function __construct(
33        private ModuleBuilderServiceInterface $builderService,
34        private TwigEnvironment $twig,
35        private Psr17Factory $psr17,
36        private string $appProfile = 'admin'
37    ) {
38    }
39
40    /**
41     * GET /system/modules/builder/new
42     */
43    public function actionNew(PermissionContext $context): ResponseInterface
44    {
45        try {
46            $metadata = $this->builderService->getBuilderMetadata($context);
47            $systemApiToken = \App\Shared\Infrastructure\Config\ApiAuthConfigLoader::getSystemApiToken();
48
49            $html = $this->twig->render('module_builder/builder_layout.twig', [
50                'mode' => 'new',
51                'module_id' => null,
52                'metadata' => $metadata,
53                'existing_schema' => null,
54                'app_profile' => $this->appProfile,
55                'system_api_token' => $systemApiToken,
56            ]);
57
58            return $this->htmlResponse($html);
59        } catch (\Throwable $e) {
60            $response = $this->psr17->createResponse(500)
61                ->withHeader('Content-Type', self::HTML_CONTENT_TYPE);
62            $response->getBody()->write(htmlspecialchars($e->getMessage(), ENT_QUOTES, 'UTF-8'));
63
64            return $response;
65        }
66    }
67
68    /**
69     * GET /system/modules/{id}/builder
70     */
71    public function actionEdit(
72        int $id,
73        PermissionContext $context
74    ): ResponseInterface {
75        try {
76            $schema = $this->builderService->getModuleDefinition($id, $context);
77            $metadata = $this->builderService->getBuilderMetadata($context);
78            $systemApiToken = \App\Shared\Infrastructure\Config\ApiAuthConfigLoader::getSystemApiToken();
79
80            $html = $this->twig->render('module_builder/builder_layout.twig', [
81                'mode' => 'edit',
82                'module_id' => $id,
83                'metadata' => $metadata,
84                'existing_schema' => $schema->toArray(),
85                'app_profile' => $this->appProfile,
86                'system_api_token' => $systemApiToken,
87            ]);
88
89            return $this->htmlResponse($html);
90        } catch (\Throwable) {
91            return $this->psr17->createResponse(404);
92        }
93    }
94
95    /**
96     * Helper creating standardized HTML response.
97     */
98    private function htmlResponse(string $html, int $status = 200): ResponseInterface
99    {
100        $response = $this->psr17->createResponse($status)
101            ->withHeader('Content-Type', self::HTML_CONTENT_TYPE);
102        $response->getBody()->write($html);
103
104        return $response;
105    }
106}