Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
98.28% covered (success)
98.28%
114 / 116
83.33% covered (warning)
83.33%
5 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
SymfonyTestingKernel
98.28% covered (success)
98.28%
114 / 116
83.33% covered (warning)
83.33%
5 / 6
13
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 getCacheDir
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
2
 registerBundles
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
3
 getDefaultTwigTemplate
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 __wakeup
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 registerContainerConfiguration
100.00% covered (success)
100.00%
85 / 85
100.00% covered (success)
100.00%
1 / 1
4
1<?php
2namespace Apie\IntegrationTests\Applications\Symfony;
3
4use Apie\AiInstructor\AiClient;
5use Apie\ApieBundle\ApieBundle;
6use Apie\ApieBundle\Security\ApieUserAuthenticator;
7use Apie\ApieBundle\Security\ApieUserProvider;
8use Apie\Core\Other\FileWriterInterface;
9use Apie\Core\Other\MockFileWriter;
10use Apie\IntegrationTests\Applications\MockFactory;
11use Doctrine\Bundle\DoctrineBundle\DoctrineBundle;
12use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
13use Symfony\Bundle\MonologBundle\MonologBundle;
14use Symfony\Bundle\SecurityBundle\SecurityBundle;
15use Symfony\Bundle\TwigBundle\TwigBundle;
16use Symfony\Component\Config\Loader\LoaderInterface;
17use Symfony\Component\DependencyInjection\ContainerBuilder;
18use Symfony\Component\DependencyInjection\Definition;
19use Symfony\Component\HttpKernel\Kernel;
20use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
21
22class SymfonyTestingKernel extends Kernel
23{
24    /**
25     * @param array<string, mixed> $apieConfig
26     */
27    public function __construct(
28        private array $apieConfig = [],
29        private readonly bool $includeTwigBundle = false,
30        private readonly bool $includeSecurityBundle = true
31    ) {
32        $this->apieConfig['enable_security'] ??= $this->includeSecurityBundle;
33        if (!$this->includeTwigBundle) {
34            $this->apieConfig['cms'] ??= [];
35            $this->apieConfig['cms']['error_template'] = __DIR__ . '/../../../fixtures/symfony/templates/error.html';
36        }
37        parent::__construct('test', true);
38    }
39
40    public function getCacheDir(): string
41    {
42        return sys_get_temp_dir()
43            . '/cache/'
44            . md5(
45                json_encode(
46                    [
47                    $this->apieConfig,
48                    $this->includeTwigBundle,
49                    $this->includeSecurityBundle,
50                    getenv('PHPUNIT_LOG_INTEGRATION_OUTPUT') ? 1 : 0
51                ]
52                )
53            );
54    }
55    
56    public function registerBundles(): iterable
57    {
58        $res = [
59            new FrameworkBundle(), // this is needed to have a functional http_kernel service.
60            new ApieBundle(),
61            new MonologBundle(), // some errors are discarded for response, but still logged.
62            new DoctrineBundle(), // maybe make this optional as the bundle also works without
63        ];
64        if ($this->includeTwigBundle) {
65            $res[] = new TwigBundle();
66        }
67        if ($this->includeSecurityBundle) {
68            $res[] = new SecurityBundle();
69        }
70        return $res;
71    }
72
73    private function getDefaultTwigTemplate(): string
74    {
75        return __DIR__ . '/../../../fixtures/symfony/templates';
76    }
77
78    public function __wakeup(): void
79    {
80        $this->__construct($this->apieConfig, $this->includeTwigBundle, $this->includeSecurityBundle);
81        parent::__wakeup();
82    }
83
84    public function registerContainerConfiguration(LoaderInterface $loader): void
85    {
86        $loader->load(function (ContainerBuilder $container) {
87            $container->addDefinitions([
88                InMemoryPersistentSessionStorageFactory::class => new Definition(InMemoryPersistentSessionStorageFactory::class),
89                FileWriterInterface::class => (new Definition(MockFileWriter::class))->setPublic(true),
90                AiClient::class => (new Definition(AiClient::class))
91                    ->setFactory([MockFactory::class, 'createMockAiClient'])
92                    ->setPublic(true),
93            ]);
94            $container->loadFromExtension('apie', $this->apieConfig);
95            $container->loadFromExtension('doctrine', ['orm' => ['auto_mapping' => true], 'dbal' => []]);
96            $container->loadFromExtension('monolog', [
97                'handlers' => [
98                    'file_log' => [
99                        'type' => 'stream',
100                        'path' => $this->getCacheDir() . 'log',
101                        'level' => getenv('PHPUNIT_LOG_INTEGRATION_OUTPUT') ? 'debug' : 'error',
102                    ]
103                ]
104            ]);
105            $container->loadFromExtension(
106                'framework',
107                [
108                    'http_method_override' => false,
109                    'secret' => '123456',
110                    'session' => [
111                        'enabled' => true,
112                        'storage_factory_id' => InMemoryPersistentSessionStorageFactory::class,
113                        'handler_id' => 'session.handler.native_file',
114                        'use_cookies' => true,
115                        'cookie_secure' => 'auto',
116                        'cookie_samesite' => 'lax',
117                    ],
118                    'php_errors' => [
119                        'log' => false,
120                    ],
121                    'router' => [
122                        'resource' => '.',
123                        'type' => 'apie'
124                    ],
125                    'uid' => [
126                        'default_uuid_version' => 7,
127                        'time_based_uuid_version' => 7,
128                    ],
129                    'csrf_protection' => false,
130                    'handle_all_throwables' => true,
131                ]
132            );
133            if ($this->includeTwigBundle) {
134                $container->loadFromExtension(
135                    'twig',
136                    [
137                        'default_path' => $this->getDefaultTwigTemplate(),
138                    ]
139                );
140            }
141            if ($this->includeSecurityBundle) {
142                $container->loadFromExtension(
143                    'security',
144                    [
145                        'password_hashers' => [
146                            PasswordAuthenticatedUserInterface::class => [
147                                'algorithm' => 'auto',
148                                'cost' => 4,
149                                'time_cost' => 3,
150                                'memory_cost' => 10,
151                            ],
152                        ],
153                        'providers' => [
154                            'apie_user' => [
155                                'id' => ApieUserProvider::class
156                            ]
157                        ],
158                        'firewalls' => [
159                            'dev' => [
160                                'pattern' =>  '^/(_(profiler|wdt)|css|images|js)/',
161                                'security' => false,
162                            ],
163                            'main' => [
164                                'lazy' => true,
165                                'provider' => 'apie_user',
166                                'custom_authenticators' => [ApieUserAuthenticator::class]
167                            ],
168                        ]
169                    ]
170                );
171            }
172        });
173    }
174}