Passed
Push — master ( 017734...6e92fd )
by Daniel
06:25
created

SilverbackApiComponentsExtension::load()   B

Complexity

Conditions 5
Paths 16

Size

Total Lines 77
Code Lines 54

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 50
CRAP Score 5.0045

Importance

Changes 0
Metric Value
cc 5
eloc 54
c 0
b 0
f 0
nc 16
nop 2
dl 0
loc 77
ccs 50
cts 53
cp 0.9434
crap 5.0045
rs 8.6925

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/*
4
 * This file is part of the Silverback API Components Bundle Project
5
 *
6
 * (c) Daniel West <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Silverback\ApiComponentsBundle\DependencyInjection;
15
16
use Exception;
17
use Ramsey\Uuid\Doctrine\UuidType;
18
use Silverback\ApiComponentsBundle\AnnotationReader\UploadableAnnotationReader;
19
use Silverback\ApiComponentsBundle\Doctrine\Extension\ORM\RouteExtension;
20
use Silverback\ApiComponentsBundle\Doctrine\Extension\ORM\TablePrefixExtension;
21
use Silverback\ApiComponentsBundle\Entity\Core\ComponentInterface;
22
use Silverback\ApiComponentsBundle\Exception\ApiPlatformAuthenticationException;
23
use Silverback\ApiComponentsBundle\Exception\UnparseableRequestHeaderException;
24
use Silverback\ApiComponentsBundle\Exception\UserDisabledException;
25
use Silverback\ApiComponentsBundle\Factory\Uploadable\MediaObjectFactory;
26
use Silverback\ApiComponentsBundle\Factory\User\Mailer\ChangeEmailConfirmationEmailFactory;
27
use Silverback\ApiComponentsBundle\Factory\User\Mailer\PasswordChangedEmailFactory;
28
use Silverback\ApiComponentsBundle\Factory\User\Mailer\PasswordResetEmailFactory;
29
use Silverback\ApiComponentsBundle\Factory\User\Mailer\UserEnabledEmailFactory;
30
use Silverback\ApiComponentsBundle\Factory\User\Mailer\UsernameChangedEmailFactory;
31
use Silverback\ApiComponentsBundle\Factory\User\Mailer\VerifyEmailFactory;
32
use Silverback\ApiComponentsBundle\Factory\User\Mailer\WelcomeEmailFactory;
33
use Silverback\ApiComponentsBundle\Factory\User\UserFactory;
34
use Silverback\ApiComponentsBundle\Form\FormTypeInterface;
35
use Silverback\ApiComponentsBundle\Form\Type\User\ChangePasswordType;
36
use Silverback\ApiComponentsBundle\Form\Type\User\NewEmailAddressType;
37
use Silverback\ApiComponentsBundle\Form\Type\User\PasswordUpdateType;
38
use Silverback\ApiComponentsBundle\Form\Type\User\UserRegisterType;
39
use Silverback\ApiComponentsBundle\Helper\Publishable\PublishableStatusChecker;
40
use Silverback\ApiComponentsBundle\Helper\Uploadable\UploadableFileManager;
41
use Silverback\ApiComponentsBundle\Helper\User\UserDataProcessor;
42
use Silverback\ApiComponentsBundle\Helper\User\UserMailer;
43
use Silverback\ApiComponentsBundle\Repository\Core\RefreshTokenRepository;
44
use Silverback\ApiComponentsBundle\Repository\User\UserRepository;
45
use Silverback\ApiComponentsBundle\Security\UserChecker;
46
use Silverback\ApiComponentsBundle\Security\Voter\RouteVoter;
47
use Silverback\ApiComponentsBundle\Serializer\Normalizer\MetadataNormalizer;
48
use Symfony\Component\Config\FileLocator;
49
use Symfony\Component\DependencyInjection\ContainerBuilder;
50
use Symfony\Component\DependencyInjection\Extension\Extension;
51
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
52
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
53
use Symfony\Component\DependencyInjection\Reference;
54
use Symfony\Component\Security\Http\Event\LogoutEvent;
55
56
/**
57
 * @author Daniel West <[email protected]>
58
 */
59
class SilverbackApiComponentsExtension extends Extension implements PrependExtensionInterface
60
{
61
    /**
62
     * @throws Exception
63
     */
64 1
    public function load(array $configs, ContainerBuilder $container): void
65
    {
66 1
        $configuration = new Configuration();
67 1
        $config = $this->processConfiguration($configuration, $configs);
68
69 1
        $this->loadServiceConfig($container);
70
71 1
        $definition = $container->getDefinition(TablePrefixExtension::class);
72 1
        $definition->setArgument('$prefix', $config['table_prefix']);
73
74 1
        $definition = $container->getDefinition(UserRepository::class);
75 1
        $definition->setArgument('$entityClass', $config['user']['class_name']);
76 1
        $definition->setArgument('$passwordRequestTimeout', $config['user']['password_reset']['request_timeout_seconds']);
77 1
        $definition->setArgument('$newEmailConfirmTimeout', $config['user']['new_email_confirmation']['request_timeout_seconds']);
78
79 1
        $cookieProvider = new Reference('lexik_jwt_authentication.cookie_provider.' . $config['refresh_token']['cookie_name']);
80 1
        $definition = $container->getDefinition('silverback.security.jwt_event_listener');
81 1
        $definition->setArgument('$cookieProvider', $cookieProvider);
82 1
        $container->setParameter('silverback.api_components.refresh_token.ttl', (int) $config['refresh_token']['ttl']);
83
84 1
        if (!empty($config['refresh_token']['options'])) {
85 1
            $definition = $container->getDefinition($config['refresh_token']['handler_id']);
86 1
            $definition->setArgument('$options', $config['refresh_token']['options']);
87
        }
88
89 1
        if ('silverback.api_components.refresh_token.storage.doctrine' === $config['refresh_token']['handler_id']) {
90
            $container
91 1
                ->register(RefreshTokenRepository::class)
92 1
                ->setArguments([new Reference('doctrine'), $config['refresh_token']['options']['class']])
93 1
                ->addTag('doctrine.repository_service');
94
        }
95
96 1
        $definition = $container->getDefinition('silverback.command.refresh_tokens_expire');
97 1
        $definition->setArgument('$storage', new Reference($config['refresh_token']['handler_id']));
98
99 1
        if (class_exists(LogoutEvent::class)) {
100 1
            $definition = $container->getDefinition('silverback.security.logout_listener');
101 1
            $definition->setArgument('$storage', new Reference($config['refresh_token']['handler_id']));
102 1
            $definition->setArgument('$cookieProvider', $cookieProvider);
103
        } else {
104
            $definition = $container->getDefinition('silverback.security.logout_handler');
105
            $definition->setArgument('$storage', new Reference($config['refresh_token']['handler_id']));
106
            $definition->setArgument('$cookieProvider', $cookieProvider);
107
        }
108
109 1
        $definition = $container->getDefinition('silverback.security.jwt_manager');
110 1
        $definition->setArgument('$userProvider', new Reference(sprintf('security.user.provider.concrete.%s', $config['refresh_token']['database_user_provider'])));
111 1
        $definition->setArgument('$storage', new Reference($config['refresh_token']['handler_id']));
112
113 1
        $definition = $container->getDefinition(PublishableStatusChecker::class);
114 1
        $definition->setArgument('$permission', $config['publishable']['permission']);
115
116 1
        $definition = $container->getDefinition(MetadataNormalizer::class);
117 1
        $definition->setArgument('$metadataKey', $config['metadata_key']);
118
119 1
        $this->setEmailVerificationArguments($container, $config['user']['email_verification'], $config['user']['password_reset']['repeat_ttl_seconds']);
120 1
        $this->setUserClassArguments($container, $config['user']['class_name']);
121 1
        $this->setMailerServiceArguments($container, $config);
122
123 1
        $imagineEnabled = $container->getParameter('api_components.imagine_enabled');
124 1
        $definition = $container->getDefinition(UploadableAnnotationReader::class);
125 1
        $definition->setArgument('$imagineBundleEnabled', $imagineEnabled);
126
127 1
        if ($imagineEnabled) {
128 1
            $definition = $container->getDefinition(UploadableFileManager::class);
129 1
            $definition->setArgument('$filterService', new Reference('liip_imagine.service.filter'));
130 1
            $definition->setArgument('$imagineCacheManager', new Reference('liip_imagine.cache.manager'));
131
132 1
            $definition = $container->getDefinition(MediaObjectFactory::class);
133 1
            $definition->setArgument('$filterService', new Reference('liip_imagine.service.filter'));
134
        }
135
136 1
        $definition = $container->getDefinition(RouteExtension::class);
137 1
        $definition->setArgument('$config', $config['route_security']);
138
139 1
        $definition = $container->getDefinition(RouteVoter::class);
140 1
        $definition->setArgument('$config', $config['route_security']);
141 1
    }
142
143 1
    private function setEmailVerificationArguments(ContainerBuilder $container, array $emailVerificationConfig, int $passwordRepeatTtl): void
144
    {
145 1
        $definition = $container->getDefinition(UserChecker::class);
146 1
        $definition->setArgument('$denyUnverifiedLogin', $emailVerificationConfig['deny_unverified_login']);
147
148 1
        $definition = $container->getDefinition(UserDataProcessor::class);
149 1
        $definition->setArgument('$initialEmailVerifiedState', $emailVerificationConfig['default_value']);
150 1
        $definition->setArgument('$verifyEmailOnRegister', $emailVerificationConfig['verify_on_register']);
151 1
        $definition->setArgument('$verifyEmailOnChange', $emailVerificationConfig['verify_on_change']);
152 1
        $definition->setArgument('$tokenTtl', $passwordRepeatTtl);
153 1
    }
154
155 1
    private function setUserClassArguments(ContainerBuilder $container, string $userClass): void
156
    {
157 1
        $definition = $container->getDefinition(UserFactory::class);
158 1
        $definition->setArgument('$userClass', $userClass);
159
160 1
        $definition = $container->getDefinition(ChangePasswordType::class);
161 1
        $definition->setArgument('$userClass', $userClass);
162
163 1
        $definition = $container->getDefinition(NewEmailAddressType::class);
164 1
        $definition->setArgument('$userClass', $userClass);
165
166 1
        $definition = $container->getDefinition(UserRegisterType::class);
167 1
        $definition->setArgument('$userClass', $userClass);
168
169 1
        $definition = $container->getDefinition(PasswordUpdateType::class);
170 1
        $definition->setArgument('$userClass', $userClass);
171 1
    }
172
173 1
    private function setMailerServiceArguments(ContainerBuilder $container, array $config): void
174
    {
175 1
        $definition = $container->getDefinition(UserMailer::class);
176 1
        $definition->setArgument(
177 1
            '$context',
178
            [
179 1
                'website_name' => $config['website_name'],
180
            ]
181
        );
182
183
        $mapping = [
184 1
            PasswordChangedEmailFactory::class => 'password_changed',
185
            UserEnabledEmailFactory::class => 'user_enabled',
186
            UsernameChangedEmailFactory::class => 'username_changed',
187
            WelcomeEmailFactory::class => 'welcome',
188
        ];
189 1
        foreach ($mapping as $class => $key) {
190 1
            $definition = $container->getDefinition($class);
191 1
            $definition->setArgument('$subject', $config['user']['emails'][$key]['subject']);
192 1
            $definition->setArgument('$enabled', $config['user']['emails'][$key]['enabled']);
193 1
            if (WelcomeEmailFactory::class === $class) {
194 1
                $definition->setArgument('$defaultRedirectPath', $config['user']['email_verification']['email']['default_redirect_path']);
195 1
                $definition->setArgument('$redirectPathQueryKey', $config['user']['email_verification']['email']['redirect_path_query']);
196
            }
197
        }
198
199
        $mapping = [
200 1
            VerifyEmailFactory::class => 'email_verification',
201
            ChangeEmailConfirmationEmailFactory::class => 'new_email_confirmation',
202
            PasswordResetEmailFactory::class => 'password_reset',
203
        ];
204 1
        foreach ($mapping as $class => $key) {
205 1
            $definition = $container->getDefinition($class);
206 1
            $definition->setArgument('$subject', $config['user'][$key]['email']['subject']);
207 1
            $definition->setArgument('$enabled', true);
208 1
            $definition->setArgument('$defaultRedirectPath', $config['user'][$key]['email']['default_redirect_path']);
209 1
            $definition->setArgument('$redirectPathQueryKey', $config['user'][$key]['email']['redirect_path_query']);
210
        }
211 1
    }
212
213
    /**
214
     * @throws Exception
215
     */
216 1
    private function loadServiceConfig(ContainerBuilder $container): void
217
    {
218 1
        $container->registerForAutoconfiguration(FormTypeInterface::class)
219 1
            ->addTag('silverback_api_components.form_type');
220
221 1
        $container->registerForAutoconfiguration(ComponentInterface::class)
222 1
            ->addTag('silverback_api_components.entity.component');
223
224 1
        $loader = new PhpFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config'));
225 1
        $loader->load('services.php');
226 1
        $loader->load('services_normalizers.php');
227 1
    }
228
229 1
    public function prepend(ContainerBuilder $container): void
230
    {
231 1
        $configs = $container->getExtensionConfig($this->getAlias());
232 1
        $configuration = new Configuration();
233 1
        $config = $this->processConfiguration($configuration, $configs);
234 1
        $this->prependApiAPlatformConfig($container, $config);
235 1
        $this->prependDoctrineConfiguration($container);
236 1
    }
237
238 1
    private function prependDoctrineConfiguration(ContainerBuilder $container): void
239
    {
240 1
        $container->prependExtensionConfig(
241 1
            'doctrine',
242
            [
243
                'dbal' => [
244
                    'types' => [
245 1
                        'uuid' => UuidType::class,
246
                    ],
247
                ],
248
            ]
249
        );
250 1
    }
251
252 1
    private function prependApiAPlatformConfig(ContainerBuilder $container, array $config): void
253
    {
254 1
        $srcBase = __DIR__ . '/..';
255 1
        $configBasePath = $srcBase . '/Resources/config/api_platform';
256
257 1
        $mappingPaths = [$srcBase . '/Entity/Core'];
258 1
        $mappingPaths[] = sprintf('%s/%s.xml', $configBasePath, 'uploadable');
259 1
        foreach ($config['enabled_components'] as $key => $enabled_component) {
260 1
            if (true === $enabled_component) {
261 1
                $mappingPaths[] = sprintf('%s/%s.xml', $configBasePath, $key);
262
            }
263
        }
264
265 1
        $websiteName = $config['website_name'];
266
267 1
        $container->prependExtensionConfig(
268 1
            'api_platform',
269
            [
270 1
                'title' => $websiteName,
271 1
                'description' => sprintf('API for %s', $websiteName),
272
                'collection' => [
273
                    'pagination' => [
274
                        'client_items_per_page' => true,
275
                        'items_per_page_parameter_name' => 'perPage',
276
                        'maximum_items_per_page' => 100,
277
                    ],
278
                ],
279
                'mapping' => [
280 1
                    'paths' => $mappingPaths,
281
                ],
282
                'swagger' => [
283
                    'api_keys' => [
284
                        'API Token' => [
285
                            'name' => 'X-AUTH-TOKEN',
286
                            'type' => 'header',
287
                        ],
288
                        'JWT (use prefix `Bearer`)' => [
289
                            'name' => 'Authorization',
290
                            'type' => 'header',
291
                        ],
292
                    ],
293
                ],
294
                'exception_to_status' => [
295
                    UnparseableRequestHeaderException::class => 400,
296
                    ApiPlatformAuthenticationException::class => 401,
297
                    UserDisabledException::class => 401,
298
                ],
299
            ]
300
        );
301 1
    }
302
}
303