Completed
Push — master ( 3420e2...77f2d3 )
by Alexis
01:43
created

UserServiceProvider::checkDependencies()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 21
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 21
rs 9.0534
cc 4
eloc 13
nc 4
nop 1
1
<?php
2
3
/*
4
 * This file is part of the awurth/silex-user package.
5
 *
6
 * (c) Alexis Wurth <[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
namespace AWurth\Silex\User\Provider;
13
14
use AWurth\Silex\User\Controller\AuthController;
15
use AWurth\Silex\User\Controller\RegistrationController;
16
use AWurth\Silex\User\EventListener\LastLoginListener;
17
use AWurth\Silex\User\Model\UserManager;
18
use AWurth\Silex\User\EventListener\AuthenticationListener;
19
use AWurth\Silex\User\EventListener\EmailConfirmationListener;
20
use AWurth\Silex\User\EventListener\FlashListener;
21
use AWurth\Silex\User\Mailer\TwigSwiftMailer;
22
use AWurth\Silex\User\Security\LoginManager;
23
use AWurth\Silex\User\Util\UserManipulator;
24
use LogicException;
25
use Pimple\Container;
26
use Pimple\ServiceProviderInterface;
27
use Silex\Api\BootableProviderInterface;
28
use Silex\Api\ControllerProviderInterface;
29
use Silex\Api\EventListenerProviderInterface;
30
use Silex\Application;
31
use Silex\ControllerCollection;
32
use Silex\ServiceControllerResolver;
33
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
34
use Symfony\Component\Translation\Loader\PhpFileLoader;
35
use Symfony\Component\Translation\Translator;
36
37
/**
38
 * User Service Provider.
39
 *
40
 * @author Alexis Wurth <[email protected]>
41
 */
42
class UserServiceProvider implements ServiceProviderInterface, BootableProviderInterface, ControllerProviderInterface, EventListenerProviderInterface
43
{
44
    /**
45
     * @var array
46
     */
47
    protected static $defaultOptions = [
48
        'use_routes' => true,
49
        'use_templates' => true,
50
        'use_translations' => true,
51
        'use_flash_notifications' => true,
52
        'use_last_login_listener' => true,
53
        'use_authentication_listener' => false,
54
        'registration.confirmation.enabled' => false,
55
        'registration.confirmation.from_email' => ''
56
    ];
57
58
    /**
59
     * {@inheritdoc}
60
     */
61
    public function register(Container $app)
62
    {
63
        $this->checkDependencies($app);
64
65
        $app['silex_user.options'] = [];
66
67
        // Services
68
        $app['silex_user.user_manager'] = function ($app) {
69
            $this->validateOptions($app);
70
71
            return new UserManager(
72
                $app[$app['silex_user.options']['object_manager']],
73
                $app['security.encoder_factory'],
74
                $app['silex_user.options']['user_class']
75
            );
76
        };
77
78
        $app['silex_user.login_manager'] = function ($app) {
79
            return new LoginManager(
80
                $app['security.token_storage'],
81
                $app['security.user_checker'],
82
                $app['security.session_strategy'],
83
                $app['request_stack']
84
            );
85
        };
86
87
        $app['silex_user.user_provider.username'] = function ($app) {
88
            return new UserProvider($app['silex_user.user_manager']);
89
        };
90
91
        $app['silex_user.user_provider.username_email'] = function ($app) {
92
            return new EmailUserProvider($app['silex_user.user_manager']);
93
        };
94
95
        $app['silex_user.mailer'] = function ($app) {
96
            if (isset($app['mailer']) && 'Swift_Mailer' === get_class($app['mailer'])) {
97
                $parameters = [
98
                    'from_email' => [
99
                        'confirmation' => $this->getOption($app, 'registration.confirmation.from_email')
100
                    ]
101
                ];
102
103
                return new TwigSwiftMailer($app['mailer'], $app['twig'], $app['url_generator'], $parameters);
104
            }
105
106
            return null;
107
        };
108
109
        $app['silex_user.util.user_manipulator'] = function ($app) {
110
            return new UserManipulator($app['silex_user.user_manager'], $app['dispatcher'], $app['request_stack']);
111
        };
112
113
        // Controllers
114
        $app['silex_user.auth.controller'] = function ($app) {
115
            return new AuthController($app);
116
        };
117
118
        $app['silex_user.registration.controller'] = function ($app) {
119
            return new RegistrationController($app);
120
        };
121
    }
122
123
    /**
124
     * {@inheritdoc}
125
     */
126
    public function boot(Application $app)
127
    {
128
        if (true === $this->getOption($app, 'use_templates')) {
129
            $app['twig.loader.filesystem']->addPath(dirname(__DIR__) . '/Resources/views/');
130
        }
131
132
        if (true === $this->getOption($app, 'use_translations')) {
133
            /** @var Translator $translator */
134
            $translator = $app['translator'];
135
            $translationsDir = dirname(__DIR__) . '/Resources/translations';
136
137
            $translator->addLoader('php', new PhpFileLoader());
138
139
            $translator->addResource('php', $translationsDir . '/silex_user.en.php', 'en', 'silex_user');
140
            $translator->addResource('php', $translationsDir . '/silex_user.fr.php', 'fr', 'silex_user');
141
            $translator->addResource('php', $translationsDir . '/validators.en.php', 'en', 'validators');
142
            $translator->addResource('php', $translationsDir . '/validators.fr.php', 'fr', 'validators');
143
        }
144
145
        if (true === $this->getOption($app, 'use_routes')) {
146
            $app->mount('/', $this->connect($app));
0 ignored issues
show
Documentation introduced by
$this->connect($app) is of type object<Silex\ControllerCollection>, but the function expects a callable.

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...
147
        }
148
    }
149
150
    /**
151
     * {@inheritdoc}
152
     */
153
    public function connect(Application $app)
154
    {
155
        /** @var ControllerCollection $controllers */
156
        $controllers = $app['controllers_factory'];
157
158
        $controllers->get('/login', 'silex_user.auth.controller:loginAction')
159
            ->bind('silex_user.login');
160
161
        $controllers->method('GET|POST')
162
            ->match('/login_check')
163
            ->bind('silex_user.login_check');
164
165
        $controllers->method('GET|POST')
166
            ->match('/logout')
167
            ->bind('silex_user.logout');
168
169
        $controllers->method('GET|POST')
170
            ->match('/register', 'silex_user.registration.controller:registerAction')
171
            ->bind('silex_user.register');
172
173
        $controllers->get('/register/confirmed', 'silex_user.registration.controller:confirmedAction')
174
            ->bind('silex_user.registration_confirmed');
175
176
        if (true === $this->getOption($app, 'registration.confirmation.enabled')) {
177
            $controllers->get('/register/check-email', 'silex_user.registration.controller:checkEmailAction')
178
                ->bind('silex_user.registration_check_email');
179
180
            $controllers->get('/register/confirm/{token}', 'silex_user.registration.controller:confirmAction')
181
                ->bind('silex_user.registration_confirm');
182
        }
183
184
        return $controllers;
185
    }
186
187
    /**
188
     * {@inheritdoc}
189
     */
190
    public function subscribe(Container $app, EventDispatcherInterface $dispatcher)
191
    {
192
        $app['silex_user.options'] = array_replace(self::$defaultOptions, $app['silex_user.options']);
193
194
        $this->validateOptions($app);
195
196
        if (true === $this->getOption($app, 'use_last_login_listener')) {
197
            $dispatcher->addSubscriber(new LastLoginListener($app['silex_user.user_manager']));
198
        }
199
200
        if (true === $this->getOption($app, 'use_authentication_listener')) {
201
            $dispatcher->addSubscriber(new AuthenticationListener($app['silex_user.login_manager'], $app['silex_user.options']['firewall_name']));
202
        }
203
204
        if (true === $this->getOption($app, 'use_flash_notifications')) {
205
            $dispatcher->addSubscriber(new FlashListener($app['session'], $app['translator']));
206
        }
207
208
        if (true === $this->getOption($app, 'registration.confirmation.enabled')) {
209
            if (null === $app['silex_user.mailer']) {
210
                throw new LogicException('You must configure a mailer to enable email notifications');
211
            }
212
213
            $dispatcher->addSubscriber(new EmailConfirmationListener($app['silex_user.mailer'], $app['url_generator'], $app['session']));
214
        }
215
    }
216
217
    /**
218
     * Checks if all required Service Providers are enabled.
219
     *
220
     * @param Container $app
221
     */
222
    protected function checkDependencies(Container $app)
223
    {
224
        $dependencies = [
225
            'twig' => 'TwigServiceProvider',
226
            'session' => 'SessionServiceProvider',
227
            'translator' => 'TranslationServiceProvider',
228
            'validator' => 'ValidatorServiceProvider',
229
            'form.factory' => 'FormServiceProvider',
230
            'security.token_storage' => 'SecurityServiceProvider'
231
        ];
232
233
        if (!$app['resolver'] instanceof ServiceControllerResolver) {
234
            throw new LogicException('You must register the ServiceControllerServiceProvider to use the UserServiceProvider');
235
        }
236
237
        foreach ($dependencies as $key => $provider) {
238
            if (!isset($app[$key])) {
239
                throw new LogicException(sprintf('You must register the %s to use the UserServiceProvider', $provider));
240
            }
241
        }
242
    }
243
244
    /**
245
     * Gets an option or its default value if it is not set.
246
     *
247
     * @param Container $app
248
     * @param string $name
249
     *
250
     * @return mixed
251
     */
252
    protected function getOption(Container $app, $name)
253
    {
254
        if (isset($app['silex_user.options'][$name])) {
255
            return $app['silex_user.options'][$name];
256
        } else {
257
            return self::$defaultOptions[$name];
258
        }
259
    }
260
261
    /**
262
     * Checks if options are set correctly.
263
     *
264
     * @param Container $app
265
     */
266
    protected function validateOptions(Container $app)
267
    {
268
        $requiredOptions = ['object_manager', 'user_class', 'firewall_name'];
269
270
        foreach ($requiredOptions as $option) {
271
            if (empty($app['silex_user.options'][$option])) {
272
                throw new LogicException(sprintf('The "%s" option must be set', $option));
273
            }
274
        }
275
276
        if (true === $this->getOption($app, 'registration.confirmation.enabled') && empty($this->getOption($app, 'registration.confirmation.from_email'))) {
277
            throw new LogicException('The "registration.confirmation.from_email" option must be set');
278
        }
279
    }
280
}
281