Completed
Pull Request — master (#35)
by
unknown
02:02
created

Bootstrap::initUrlRoutes()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 17
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 2.004

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 17
ccs 9
cts 10
cp 0.9
rs 9.4285
cc 2
eloc 10
nc 2
nop 1
crap 2.004
1
<?php
2
3
/*
4
 * This file is part of the 2amigos/yii2-usuario project.
5
 *
6
 * (c) 2amigOS! <http://2amigos.us/>
7
 *
8
 * For the full copyright and license information, please view
9
 * the LICENSE file that was distributed with this source code.
10
 */
11
12
namespace Da\User;
13
14
use Da\User\Component\AuthDbManagerComponent;
15
use Da\User\Contracts\AuthManagerInterface;
16
use Da\User\Helper\ClassMapHelper;
17
use Da\User\Model\User;
18
use Da\User\Validator\TimeZoneValidator;
19
use Yii;
20
use yii\authclient\Collection;
21
use yii\base\Application;
22
use yii\base\BootstrapInterface;
23
use yii\base\Exception;
24
use yii\console\Application as ConsoleApplication;
25
use yii\i18n\PhpMessageSource;
26
use yii\web\Application as WebApplication;
27
28
/**
29
 * Bootstrap class of the yii2-usuario extension. Configures container services, initializes translations,
30
 * builds class map, and does the other setup actions participating in the application bootstrap process.
31
 */
32
class Bootstrap implements BootstrapInterface
33
{
34
    /**
35
     * {@inheritdoc}
36
     */
37 10
    public function bootstrap($app)
38
    {
39 10
        if ($app->hasModule('user') && $app->getModule('user') instanceof Module) {
40 10
            $map = $this->buildClassMap($app->getModule('user')->classMap);
41 10
            $this->initContainer($app, $map);
42 10
            $this->initTranslations($app);
43 10
            $this->initMailServiceConfiguration($app, $app->getModule('user'));
44
45 10
            if ($app instanceof WebApplication) {
46 10
                $this->initControllerNamespace($app);
47 10
                $this->initUrlRoutes($app);
48 10
                $this->initAuthCollection($app);
49 10
                $this->initAuthManager($app);
50
            } else {
51
                /* @var $app ConsoleApplication */
52
                $this->initConsoleCommands($app);
53
                $this->initAuthManager($app);
54
            }
55
        }
56 10
    }
57
58
    /**
59
     * Initialize container with module classes.
60
     *
61
     * @param \yii\base\Application $app
62
     * @param array                 $map the previously built class map list
63
     */
64 10
    protected function initContainer($app, $map)
65
    {
66 10
        $di = Yii::$container;
67
        try {
68
            // events
69 10
            $di->set(Event\FormEvent::class);
70 10
            $di->set(Event\ProfileEvent::class);
71 10
            $di->set(Event\ResetPasswordEvent::class);
72 10
            $di->set(Event\SocialNetworkAuthEvent::class);
73 10
            $di->set(Event\SocialNetworkConnectEvent::class);
74 10
            $di->set(Event\UserEvent::class);
75
76
            // forms
77 10
            $di->set(Form\LoginForm::class);
78 10
            $di->set(Form\RecoveryForm::class);
79 10
            $di->set(Form\RegistrationForm::class);
80 10
            $di->set(Form\ResendForm::class);
81 10
            $di->set(Form\SettingsForm::class);
82
83
            // helpers
84 10
            $di->set(Helper\AuthHelper::class);
85 10
            $di->set(Helper\GravatarHelper::class);
86 10
            $di->set(Helper\SecurityHelper::class);
87 10
            $di->set(Helper\TimezoneHelper::class);
88
89
            // services
90 10
            $di->set(Service\AccountConfirmationService::class);
91 10
            $di->set(Service\EmailChangeService::class);
92 10
            $di->set(Service\PasswordRecoveryService::class);
93 10
            $di->set(Service\ResendConfirmationService::class);
94 10
            $di->set(Service\ResetPasswordService::class);
95 10
            $di->set(Service\SocialNetworkAccountConnectService::class);
96 10
            $di->set(Service\SocialNetworkAuthenticateService::class);
97 10
            $di->set(Service\UserBlockService::class);
98 10
            $di->set(Service\UserCreateService::class);
99 10
            $di->set(Service\UserRegisterService::class);
100 10
            $di->set(Service\UserConfirmationService::class);
101 10
            $di->set(Service\AuthItemEditionService::class);
102 10
            $di->set(Service\UpdateAuthAssignmentsService::class);
103 10
            $di->set(Service\SwitchIdentityService::class);
104
105
            // email change strategy
106 10
            $di->set(Strategy\DefaultEmailChangeStrategy::class);
107 10
            $di->set(Strategy\InsecureEmailChangeStrategy::class);
108 10
            $di->set(Strategy\SecureEmailChangeStrategy::class);
109
110
            // validators
111 10
            $di->set(Validator\AjaxRequestModelValidator::class);
112 10
            $di->set(TimeZoneValidator::class);
113
114
            // class map models + query classes
115 10
            $modelClassMap = [];
116 10
            foreach ($map as $class => $definition) {
117 10
                $di->set($class, $definition);
118 10
                $model = is_array($definition) ? $definition['class'] : $definition;
119 10
                $name = (substr($class, strrpos($class, '\\') + 1));
120 10
                $modelClassMap[$class] = $model;
121 10
                if (in_array($name, ['User', 'Profile', 'Token', 'SocialNetworkAccount'])) {
122 10
                    $di->set(
123 10
                        "Da\\User\\Query\\{$name}Query",
124 10
                        function () use ($model) {
125 10
                            return $model::find();
126 10
                        }
127
                    );
128
                }
129
            }
130 10
            $di->setSingleton(ClassMapHelper::class, ClassMapHelper::class, [$modelClassMap]);
131
132
            // search classes
133 10
            if (!$di->has(Search\UserSearch::class)) {
134
                $di->set(Search\UserSearch::class, [$di->get(Query\UserQuery::class)]);
135
            }
136 10
            if (!$di->has(Search\PermissionSearch::class)) {
137
                $di->set(Search\PermissionSearch::class);
138
            }
139 10
            if (!$di->has(Search\RoleSearch::class)) {
140
                $di->set(Search\RoleSearch::class);
141
            }
142
143 10
            if ($app instanceof WebApplication) {
144
                // override Yii
145 10
                $di->set(
146 10
                    'yii\web\User',
147
                    [
148 10
                        'enableAutoLogin' => true,
149
                        'loginUrl' => ['/user/security/login'],
150 10
                        'identityClass' => $di->get(ClassMapHelper::class)->get(User::class),
151
                    ]
152
                );
153
            }
154
        } catch (Exception $e) {
155
            die($e);
156
        }
157 10
    }
158
159
    /**
160
     * Registers module translation messages.
161
     *
162
     * @param Application $app
163
     */
164 10
    protected function initTranslations(Application $app)
165
    {
166 10
        if (!isset($app->get('i18n')->translations['usuario*'])) {
167
            /** @var Module $module */
168
            $module = $app->getModule('user');
169
170
            $app->get('i18n')->translations['usuario*'] = $module->i18nTranslationConfig;
171
        }
172 10
    }
173
174
    /**
175
     * Ensures the auth manager is the one provided by the library.
176
     *
177
     * @param Application $app
178
     */
179 10
    protected function initAuthManager(Application $app)
180
    {
181 10
        if (!($app->getAuthManager() instanceof AuthManagerInterface)) {
182 10
            $app->set(
183 10
                'authManager',
184
                [
185 10
                    'class' => AuthDbManagerComponent::class,
186
                ]
187
            );
188
        }
189 10
    }
190
191
    /**
192
     * Initializes web url routes (rules in Yii2).
193
     *
194
     * @param WebApplication $app
195
     */
196 10
    protected function initUrlRoutes(WebApplication $app)
197
    {
198
        /** @var $module Module */
199 10
        $module = $app->getModule('user');
200
        $config = [
201 10
            'class' => 'yii\web\GroupUrlRule',
202 10
            'prefix' => $module->prefix,
203 10
            'rules' => $module->routes,
204
        ];
205
206 10
        if ($module->prefix !== 'user') {
207
            $config['routePrefix'] = 'user';
208
        }
209
210 10
        $rule = Yii::createObject($config);
211 10
        $app->getUrlManager()->addRules([$rule], false);
212 10
    }
213
214
    /**
215
     * Ensures required mail parameters needed for the mail service.
216
     *
217
     * @param Application             $app
218
     * @param Module|\yii\base\Module $module
219
     */
220 10
    protected function initMailServiceConfiguration(Application $app, Module $module)
221
    {
222
        $defaults = [
223 10
            'fromEmail' => '[email protected]',
224 10
            'welcomeMailSubject' => Yii::t('usuario', 'Welcome to {0}', $app->name),
0 ignored issues
show
Documentation introduced by
$app->name is of type string, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
225 10
            'confirmationMailSubject' => Yii::t('usuario', 'Confirm account on {0}', $app->name),
0 ignored issues
show
Documentation introduced by
$app->name is of type string, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
226 10
            'reconfirmationMailSubject' => Yii::t('usuario', 'Confirm email change on {0}', $app->name),
0 ignored issues
show
Documentation introduced by
$app->name is of type string, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
227 10
            'recoveryMailSubject' => Yii::t('usuario', 'Complete password reset on {0}', $app->name),
0 ignored issues
show
Documentation introduced by
$app->name is of type string, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
228
        ];
229
230 10
        $module->mailParams = array_merge($defaults, $module->mailParams);
231 10
    }
232
233
    /**
234
     * Ensures the authCollection component is configured.
235
     *
236
     * @param WebApplication $app
237
     */
238 10
    protected function initAuthCollection(WebApplication $app)
239
    {
240 10
        if (!$app->has('authClientCollection')) {
241 10
            $app->set('authClientCollection', Collection::class);
242
        }
243 10
    }
244
245
    /**
246
     * Registers console commands to main app.
247
     *
248
     * @param ConsoleApplication $app
249
     */
250
    protected function initConsoleCommands(ConsoleApplication $app)
251
    {
252
        $app->getModule('user')->controllerNamespace = 'Da\User\Command';
253
    }
254
255
    /**
256
     * Registers controllers.
257
     *
258
     * @param WebApplication $app
259
     */
260 10
    protected function initControllerNamespace(WebApplication $app)
261
    {
262 10
        $app->getModule('user')->controllerNamespace = 'Da\User\Controller';
263 10
        $app->getModule('user')->setViewPath('@Da/User/resources/views');
264 10
    }
265
266
    /**
267
     * Builds class map according to user configuration.
268
     *
269
     * @param array $userClassMap user configuration on the module
270
     *
271
     * @return array
272
     */
273 10
    protected function buildClassMap(array $userClassMap)
274
    {
275 10
        $map = [];
276
277
        $defaults = [
278
            // --- models
279 10
            'User' => 'Da\User\Model\User',
280
            'SocialNetworkAccount' => 'Da\User\Model\SocialNetworkAccount',
281
            'Profile' => 'Da\User\Model\Profile',
282
            'Token' => 'Da\User\Model\Token',
283
            'Assignment' => 'Da\User\Model\Assignment',
284
            'Permission' => 'Da\User\Model\Permission',
285
            'Role' => 'Da\User\Model\Role',
286
            // --- search
287
            'UserSearch' => 'Da\User\Search\UserSearch',
288
            'PermissionSearch' => 'Da\User\Search\PermissionSearch',
289
            'RoleSearch' => 'Da\User\Search\RoleSearch',
290
            // --- forms
291
            'RegistrationForm' => 'Da\User\Form\RegistrationForm',
292
            'ResendForm' => 'Da\User\Form\ResendForm',
293
            'LoginForm' => 'Da\User\Form\LoginForm',
294
            'SettingsForm' => 'Da\User\Form\SettingsForm',
295
            'RecoveryForm' => 'Da\User\Form\RecoveryForm',
296
        ];
297
298
        $routes = [
299 10
            'Da\User\Model' => [
300
                'User',
301
                'SocialNetworkAccount',
302
                'Profile',
303
                'Token',
304
                'Assignment',
305
                'Permission',
306
                'Role',
307
            ],
308
            'Da\User\Search' => [
309
                'UserSearch',
310
                'PermissionSearch',
311
                'RoleSearch',
312
            ],
313
            'Da\User\Form' => [
314
                'RegistrationForm',
315
                'ResendForm',
316
                'LoginForm',
317
                'SettingsForm',
318
                'RecoveryForm',
319
            ],
320
        ];
321
322 10
        $mapping = array_merge($defaults, $userClassMap);
323
324 10
        foreach ($mapping as $name => $definition) {
325 10
            $map[$this->getRoute($routes, $name) . "\\$name"] = $definition;
326
        }
327
328 10
        return $map;
329
    }
330
331
    /**
332
     * Returns the parent class name route of a short class name.
333
     *
334
     * @param array  $routes class name routes
335
     * @param string $name
336
     *
337
     * @throws Exception
338
     * @return int|string
339
     *
340
     */
341 10
    protected function getRoute(array $routes, $name)
342
    {
343 10
        foreach ($routes as $route => $names) {
344 10
            if (in_array($name, $names)) {
345 10
                return $route;
346
            }
347
        }
348
        throw new Exception("Unknown configuration class name '{$name}'");
349
    }
350
}
351