Completed
Push — pull-request/8600 ( 367a7c )
by Kamil
56:28 queued 34:06
created

UserProvider::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 20
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 20
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 17
nc 1
nop 9

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
/*
4
 * This file is part of the Sylius package.
5
 *
6
 * (c) Paweł Jędrzejewski
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 Sylius\Bundle\CoreBundle\OAuth;
15
16
use Doctrine\Common\Persistence\ObjectManager;
17
use HWI\Bundle\OAuthBundle\Connect\AccountConnectorInterface;
18
use HWI\Bundle\OAuthBundle\OAuth\Response\UserResponseInterface;
19
use HWI\Bundle\OAuthBundle\Security\Core\User\OAuthAwareUserProviderInterface;
20
use Sylius\Bundle\UserBundle\Provider\UsernameOrEmailProvider as BaseUserProvider;
21
use Sylius\Component\Core\Model\CustomerInterface;
22
use Sylius\Component\Core\Model\ShopUserInterface as SyliusUserInterface;
23
use Sylius\Component\Core\Repository\CustomerRepositoryInterface;
24
use Sylius\Component\Resource\Factory\FactoryInterface;
25
use Sylius\Component\Resource\Repository\RepositoryInterface;
26
use Sylius\Component\User\Canonicalizer\CanonicalizerInterface;
27
use Sylius\Component\User\Model\UserOAuthInterface;
28
use Sylius\Component\User\Repository\UserRepositoryInterface;
29
use Symfony\Component\Security\Core\User\UserInterface;
30
31
/**
32
 * Loading and ad-hoc creation of a user by an OAuth sign-in provider account.
33
 *
34
 * @author Fabian Kiss <[email protected]>
35
 * @author Joseph Bielawski <[email protected]>
36
 * @author Łukasz Chruściel <[email protected]>
37
 */
38
class UserProvider extends BaseUserProvider implements AccountConnectorInterface, OAuthAwareUserProviderInterface
39
{
40
    /**
41
     * @var FactoryInterface
42
     */
43
    private $oauthFactory;
44
45
    /**
46
     * @var RepositoryInterface
47
     */
48
    private $oauthRepository;
49
50
    /**
51
     * @var FactoryInterface
52
     */
53
    private $customerFactory;
54
55
    /**
56
     * @var FactoryInterface
57
     */
58
    private $userFactory;
59
60
    /**
61
     * @var ObjectManager
62
     */
63
    private $userManager;
64
65
    /**
66
     * @var CustomerRepositoryInterface
67
     */
68
    private $customerRepository;
69
70
    /**
71
     * @param string $supportedUserClass
72
     * @param FactoryInterface $customerFactory
73
     * @param FactoryInterface $userFactory
74
     * @param UserRepositoryInterface $userRepository
75
     * @param FactoryInterface $oauthFactory
76
     * @param RepositoryInterface $oauthRepository
77
     * @param ObjectManager $userManager
78
     * @param CanonicalizerInterface $canonicalizer
79
     * @param CustomerRepositoryInterface $customerRepository
80
     */
81
    public function __construct(
82
        string $supportedUserClass,
83
        FactoryInterface $customerFactory,
84
        FactoryInterface $userFactory,
85
        UserRepositoryInterface $userRepository,
86
        FactoryInterface $oauthFactory,
87
        RepositoryInterface $oauthRepository,
88
        ObjectManager $userManager,
89
        CanonicalizerInterface $canonicalizer,
90
        CustomerRepositoryInterface $customerRepository
91
    ) {
92
        parent::__construct($supportedUserClass, $userRepository, $canonicalizer);
93
94
        $this->customerFactory = $customerFactory;
95
        $this->oauthFactory = $oauthFactory;
96
        $this->oauthRepository = $oauthRepository;
97
        $this->userFactory = $userFactory;
98
        $this->userManager = $userManager;
99
        $this->customerRepository = $customerRepository;
100
    }
101
102
    /**
103
     * {@inheritdoc}
104
     */
105
    public function loadUserByOAuthUserResponse(UserResponseInterface $response): UserInterface
106
    {
107
        $oauth = $this->oauthRepository->findOneBy([
108
            'provider' => $response->getResourceOwner()->getName(),
109
            'identifier' => $response->getUsername(),
110
        ]);
111
112
        if ($oauth instanceof UserOAuthInterface) {
113
            return $oauth->getUser();
114
        }
115
116
        if (null !== $response->getEmail()) {
117
            $user = $this->userRepository->findOneByEmail($response->getEmail());
118
            if (null !== $user) {
119
                return $this->updateUserByOAuthUserResponse($user, $response);
120
            }
121
        }
122
123
        return $this->createUserByOAuthUserResponse($response);
124
    }
125
126
    /**
127
     * {@inheritdoc}
128
     */
129
    public function connect(UserInterface $user, UserResponseInterface $response): void
130
    {
131
        $this->updateUserByOAuthUserResponse($user, $response);
132
    }
133
134
    /**
135
     * Ad-hoc creation of user.
136
     *
137
     * @param UserResponseInterface $response
138
     *
139
     * @return SyliusUserInterface
140
     */
141
    private function createUserByOAuthUserResponse(UserResponseInterface $response): SyliusUserInterface
142
    {
143
        /** @var SyliusUserInterface $user */
144
        $user = $this->userFactory->createNew();
145
146
        $canonicalEmail = $this->canonicalizer->canonicalize($response->getEmail());
147
148
        /** @var CustomerInterface $customer */
149
        $customer = $this->customerRepository->findOneBy(['emailCanonical' => $canonicalEmail]);
150
151
        if (null === $customer) {
152
            $customer = $this->customerFactory->createNew();
153
        }
154
155
        $user->setCustomer($customer);
156
157
        // set default values taken from OAuth sign-in provider account
158
        if (null !== $email = $response->getEmail()) {
159
            $customer->setEmail($email);
160
        }
161
162
        if (null !== $name = $response->getFirstName()) {
163
            $customer->setFirstName($name);
164
        } elseif (null !== $realName = $response->getRealName()) {
165
            $customer->setFirstName($realName);
166
        }
167
168
        if (null !== $lastName = $response->getLastName()) {
169
            $customer->setLastName($lastName);
170
        }
171
172
        if (!$user->getUsername()) {
173
            $user->setUsername($response->getEmail() ?: $response->getNickname());
174
        }
175
176
        // set random password to prevent issue with not nullable field & potential security hole
177
        $user->setPlainPassword(substr(sha1($response->getAccessToken()), 0, 10));
178
179
        $user->setEnabled(true);
180
181
        return $this->updateUserByOAuthUserResponse($user, $response);
182
    }
183
184
    /**
185
     * Attach OAuth sign-in provider account to existing user.
186
     *
187
     * @param UserInterface $user
188
     * @param UserResponseInterface $response
189
     *
190
     * @return UserInterface
191
     */
192
    private function updateUserByOAuthUserResponse(UserInterface $user, UserResponseInterface $response): UserInterface
193
    {
194
        $oauth = $this->oauthFactory->createNew();
195
        $oauth->setIdentifier($response->getUsername());
196
        $oauth->setProvider($response->getResourceOwner()->getName());
197
        $oauth->setAccessToken($response->getAccessToken());
198
        $oauth->setRefreshToken($response->getRefreshToken());
199
200
        /* @var $user SyliusUserInterface */
201
        $user->addOAuthAccount($oauth);
202
203
        $this->userManager->persist($user);
204
        $this->userManager->flush();
205
206
        return $user;
207
    }
208
}
209