Passed
Push — master ( 7276f5...3cc058 )
by Daniel
09:58 queued 02:47
created

SilverbackApiComponentsExtension::load()   B

Complexity

Conditions 5
Paths 16

Size

Total Lines 74
Code Lines 52

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 48
CRAP Score 5.005

Importance

Changes 0
Metric Value
cc 5
eloc 52
c 0
b 0
f 0
nc 16
nop 2
dl 0
loc 74
ccs 48
cts 51
cp 0.9412
crap 5.005
rs 8.7361

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