Passed
Push — master ( 3ec415...9f2f47 )
by Daniel
16:25
created

SilverbackApiComponentsExtension::load()   B

Complexity

Conditions 5
Paths 16

Size

Total Lines 71
Code Lines 49

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 46
CRAP Score 5.0018

Importance

Changes 0
Metric Value
cc 5
eloc 49
nc 16
nop 2
dl 0
loc 71
ccs 46
cts 48
cp 0.9583
crap 5.0018
rs 8.8016
c 0
b 0
f 0

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\EventListener\LogoutListener;
46
use Silverback\ApiComponentsBundle\Security\UserChecker;
47
use Silverback\ApiComponentsBundle\Security\Voter\RouteVoter;
48
use Silverback\ApiComponentsBundle\Serializer\Normalizer\MetadataNormalizer;
49
use Symfony\Component\Config\FileLocator;
50
use Symfony\Component\DependencyInjection\ContainerBuilder;
51
use Symfony\Component\DependencyInjection\Extension\Extension;
52
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
53
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
54
use Symfony\Component\DependencyInjection\Reference;
55
use Symfony\Component\Security\Http\Event\LogoutEvent;
56
57
/**
58
 * @author Daniel West <[email protected]>
59
 */
60
class SilverbackApiComponentsExtension extends Extension implements PrependExtensionInterface
61
{
62
    /**
63
     * @throws Exception
64
     */
65 1
    public function load(array $configs, ContainerBuilder $container): void
66
    {
67 1
        $configuration = new Configuration();
68 1
        $config = $this->processConfiguration($configuration, $configs);
69
70 1
        $this->loadServiceConfig($container);
71
72 1
        $definition = $container->getDefinition(TablePrefixExtension::class);
73 1
        $definition->setArgument('$prefix', $config['table_prefix']);
74
75 1
        $definition = $container->getDefinition(UserRepository::class);
76 1
        $definition->setArgument('$entityClass', $config['user']['class_name']);
77 1
        $definition->setArgument('$passwordRequestTimeout', $config['user']['password_reset']['request_timeout_seconds']);
78 1
        $definition->setArgument('$newEmailConfirmTimeout', $config['user']['new_email_confirmation']['request_timeout_seconds']);
79
80 1
        $definition = $container->getDefinition('silverback.security.jwt_event_listener');
81 1
        $definition->setArgument('$cookieProvider', new Reference('lexik_jwt_authentication.cookie_provider.' . $config['refresh_token']['cookie_name']));
82 1
        $container->setParameter('silverback.api_component.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_component.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
        if (class_exists(LogoutEvent::class)) {
97 1
            $definition = $container->getDefinition(LogoutListener::class);
98 1
            $definition->setArgument('$storage', new Reference($config['refresh_token']['handler_id']));
99
        } else {
100
            $definition = $container->getDefinition('silverback.security.logout_handler');
101
            $definition->setArgument('$storage', new Reference($config['refresh_token']['handler_id']));
102
        }
103
104 1
        $definition = $container->getDefinition('silverback.security.jwt_manager');
105 1
        $definition->setArgument('$userProvider', new Reference(sprintf('security.user.provider.concrete.%s', $config['refresh_token']['database_user_provider'])));
106 1
        $definition->setArgument('$storage', new Reference($config['refresh_token']['handler_id']));
107
108 1
        $definition = $container->getDefinition(PublishableStatusChecker::class);
109 1
        $definition->setArgument('$permission', $config['publishable']['permission']);
110
111 1
        $definition = $container->getDefinition(MetadataNormalizer::class);
112 1
        $definition->setArgument('$metadataKey', $config['metadata_key']);
113
114 1
        $this->setEmailVerificationArguments($container, $config['user']['email_verification'], $config['user']['password_reset']['repeat_ttl_seconds']);
115 1
        $this->setUserClassArguments($container, $config['user']['class_name']);
116 1
        $this->setMailerServiceArguments($container, $config);
117
118 1
        $imagineEnabled = $container->getParameter('api_component.imagine_enabled');
119 1
        $definition = $container->getDefinition(UploadableAnnotationReader::class);
120 1
        $definition->setArgument('$imagineBundleEnabled', $imagineEnabled);
121
122 1
        if ($imagineEnabled) {
123 1
            $definition = $container->getDefinition(UploadableFileManager::class);
124 1
            $definition->setArgument('$filterService', new Reference('liip_imagine.service.filter'));
125 1
            $definition->setArgument('$imagineCacheManager', new Reference('liip_imagine.cache.manager'));
126
127 1
            $definition = $container->getDefinition(MediaObjectFactory::class);
128 1
            $definition->setArgument('$filterService', new Reference('liip_imagine.service.filter'));
129
        }
130
131 1
        $definition = $container->getDefinition(RouteExtension::class);
132 1
        $definition->setArgument('$config', $config['route_security']);
133
134 1
        $definition = $container->getDefinition(RouteVoter::class);
135 1
        $definition->setArgument('$config', $config['route_security']);
136 1
    }
137
138 1
    private function setEmailVerificationArguments(ContainerBuilder $container, array $emailVerificationConfig, int $passwordRepeatTtl): void
139
    {
140 1
        $definition = $container->getDefinition(UserChecker::class);
141 1
        $definition->setArgument('$denyUnverifiedLogin', $emailVerificationConfig['deny_unverified_login']);
142
143 1
        $definition = $container->getDefinition(UserDataProcessor::class);
144 1
        $definition->setArgument('$initialEmailVerifiedState', $emailVerificationConfig['default_value']);
145 1
        $definition->setArgument('$verifyEmailOnRegister', $emailVerificationConfig['verify_on_register']);
146 1
        $definition->setArgument('$verifyEmailOnChange', $emailVerificationConfig['verify_on_change']);
147 1
        $definition->setArgument('$tokenTtl', $passwordRepeatTtl);
148 1
    }
149
150 1
    private function setUserClassArguments(ContainerBuilder $container, string $userClass): void
151
    {
152 1
        $definition = $container->getDefinition(UserFactory::class);
153 1
        $definition->setArgument('$userClass', $userClass);
154
155 1
        $definition = $container->getDefinition(ChangePasswordType::class);
156 1
        $definition->setArgument('$userClass', $userClass);
157
158 1
        $definition = $container->getDefinition(NewEmailAddressType::class);
159 1
        $definition->setArgument('$userClass', $userClass);
160
161 1
        $definition = $container->getDefinition(UserRegisterType::class);
162 1
        $definition->setArgument('$userClass', $userClass);
163
164 1
        $definition = $container->getDefinition(PasswordUpdateType::class);
165 1
        $definition->setArgument('$userClass', $userClass);
166 1
    }
167
168 1
    private function setMailerServiceArguments(ContainerBuilder $container, array $config): void
169
    {
170 1
        $definition = $container->getDefinition(UserMailer::class);
171 1
        $definition->setArgument(
172 1
            '$context',
173
            [
174 1
                'website_name' => $config['website_name'],
175
            ]
176
        );
177
178
        $mapping = [
179 1
            PasswordChangedEmailFactory::class => 'password_changed',
180
            UserEnabledEmailFactory::class => 'user_enabled',
181
            UsernameChangedEmailFactory::class => 'username_changed',
182
            WelcomeEmailFactory::class => 'welcome',
183
        ];
184 1
        foreach ($mapping as $class => $key) {
185 1
            $definition = $container->getDefinition($class);
186 1
            $definition->setArgument('$subject', $config['user']['emails'][$key]['subject']);
187 1
            $definition->setArgument('$enabled', $config['user']['emails'][$key]['enabled']);
188 1
            if (WelcomeEmailFactory::class === $class) {
189 1
                $definition->setArgument('$defaultRedirectPath', $config['user']['email_verification']['email']['default_redirect_path']);
190 1
                $definition->setArgument('$redirectPathQueryKey', $config['user']['email_verification']['email']['redirect_path_query']);
191
            }
192
        }
193
194
        $mapping = [
195 1
            VerifyEmailFactory::class => 'email_verification',
196
            ChangeEmailConfirmationEmailFactory::class => 'new_email_confirmation',
197
            PasswordResetEmailFactory::class => 'password_reset',
198
        ];
199 1
        foreach ($mapping as $class => $key) {
200 1
            $definition = $container->getDefinition($class);
201 1
            $definition->setArgument('$subject', $config['user'][$key]['email']['subject']);
202 1
            $definition->setArgument('$enabled', true);
203 1
            $definition->setArgument('$defaultRedirectPath', $config['user'][$key]['email']['default_redirect_path']);
204 1
            $definition->setArgument('$redirectPathQueryKey', $config['user'][$key]['email']['redirect_path_query']);
205
        }
206 1
    }
207
208
    /**
209
     * @throws Exception
210
     */
211 1
    private function loadServiceConfig(ContainerBuilder $container): void
212
    {
213 1
        $container->registerForAutoconfiguration(FormTypeInterface::class)
214 1
            ->addTag('silverback_api_components.form_type');
215
216 1
        $container->registerForAutoconfiguration(ComponentInterface::class)
217 1
            ->addTag('silverback_api_components.entity.component');
218
219 1
        $loader = new PhpFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config'));
220 1
        $loader->load('services.php');
221 1
        $loader->load('services_normalizers.php');
222 1
    }
223
224 1
    public function prepend(ContainerBuilder $container): void
225
    {
226 1
        $configs = $container->getExtensionConfig($this->getAlias());
227 1
        $configuration = new Configuration();
228 1
        $config = $this->processConfiguration($configuration, $configs);
229 1
        $this->prependApiAPlatformConfig($container, $config);
230 1
        $this->prependDoctrineConfiguration($container);
231 1
    }
232
233 1
    private function prependDoctrineConfiguration(ContainerBuilder $container): void
234
    {
235 1
        $container->prependExtensionConfig(
236 1
            'doctrine',
237
            [
238
                'dbal' => [
239
                    'types' => [
240 1
                        'uuid' => UuidType::class,
241
                    ],
242
                ],
243
            ]
244
        );
245 1
    }
246
247 1
    private function prependApiAPlatformConfig(ContainerBuilder $container, array $config): void
248
    {
249 1
        $srcBase = __DIR__ . '/..';
250 1
        $configBasePath = $srcBase . '/Resources/config/api_platform';
251
252 1
        $mappingPaths = [$srcBase . '/Entity/Core'];
253 1
        $mappingPaths[] = sprintf('%s/%s.xml', $configBasePath, 'uploadable');
254 1
        foreach ($config['enabled_components'] as $key => $enabled_component) {
255 1
            if (true === $enabled_component) {
256 1
                $mappingPaths[] = sprintf('%s/%s.xml', $configBasePath, $key);
257
            }
258
        }
259
260 1
        $websiteName = $config['website_name'];
261
262 1
        $container->prependExtensionConfig(
263 1
            'api_platform',
264
            [
265 1
                'title' => $websiteName,
266 1
                'description' => sprintf('API for %s', $websiteName),
267
                'collection' => [
268
                    'pagination' => [
269
                        'client_items_per_page' => true,
270
                        'items_per_page_parameter_name' => 'perPage',
271
                        'maximum_items_per_page' => 100,
272
                    ],
273
                ],
274
                'mapping' => [
275 1
                    'paths' => $mappingPaths,
276
                ],
277
                'swagger' => [
278
                    'api_keys' => [
279
                        'API Token' => [
280
                            'name' => 'X-AUTH-TOKEN',
281
                            'type' => 'header',
282
                        ],
283
                        'JWT (use prefix `Bearer`)' => [
284
                            'name' => 'Authorization',
285
                            'type' => 'header',
286
                        ],
287
                    ],
288
                ],
289
                'exception_to_status' => [
290
                    UnparseableRequestHeaderException::class => 400,
291
                    ApiPlatformAuthenticationException::class => 401,
292
                    UserDisabledException::class => 401,
293
                ],
294
            ]
295
        );
296 1
    }
297
}
298