Completed
Push — master ( e79dfa...ffecda )
by Benjamin
02:16
created

OAuthUserProvider::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 5
rs 9.4285
cc 1
eloc 3
nc 1
nop 3
1
<?php
2
3
namespace Alpixel\Bundle\UserBundle\Provider;
4
5
use Cocur\Slugify\Slugify;
6
use FOS\UserBundle\Model\UserInterface as FOSUserInterface;
7
use HWI\Bundle\OAuthBundle\OAuth\Response\UserResponseInterface;
8
use HWI\Bundle\OAuthBundle\Security\Core\User\FOSUBUserProvider;
9
use HWI\Bundle\OAuthBundle\Security\Core\User\OAuthAwareUserProviderInterface;
10
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
11
use Symfony\Component\Security\Core\User\UserInterface;
12
use Alpixel\Bundle\UserBundle\Event\UserEvent;
13
use FOS\UserBundle\Doctrine\UserManager;
14
use FOS\UserBundle\Model\UserManagerInterface;
15
use Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher;
16
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
17
use Symfony\Component\HttpFoundation\RequestStack;
18
19
class OAuthUserProvider extends FOSUBUserProvider implements OAuthAwareUserProviderInterface
20
{
21
22
    protected $dispatcher;
23
    protected $request;
24
25
    /**
26
     * Constructor.
27
     *
28
     * @param UserManagerInterface $userManager FOSUB user provider.
29
     * @param array                $properties  Property mapping.
30
     */
31
    public function __construct(UserManagerInterface $userManager, array $properties, EventDispatcherInterface $dispatcher)
32
    {
33
        parent::__construct($userManager, $properties);
34
        $this->dispatcher = $dispatcher;
35
    }
36
37
    public function setRequest(RequestStack $request_stack)
38
    {
39
        $this->request = $request_stack->getCurrentRequest();
40
    }
41
42
    /**
43
     * {@inheritDoc}
44
     */
45
    public function loadUserByOAuthUserResponse(UserResponseInterface $response)
46
    {
47
        try {
48
            return parent::loadUserByOAuthUserResponse($response);
49
        } catch (UsernameNotFoundException $e) {
50
            $email = $response->getEmail();
51
52
            if (!empty($email)) {
53
                if (null === $user = $this->userManager->findUserByEmail($email)) {
54
                    return $this->createUserByOAuthUserResponse($response);
55
                }
56
57
                return $this->updateUserByOAuthUserResponse($user, $response);
58
            }
59
            throw new UsernameNotFoundException();
60
        }
61
    }
62
    /**
63
     * {@inheritDoc}
64
     */
65
    public function connect(UserInterface $user, UserResponseInterface $response)
66
    {
67
        $providerName = $response->getResourceOwner()->getName();
68
        $uniqueId = $response->getUsername();
69
        $user->addOAuthAccount($providerName, $uniqueId);
0 ignored issues
show
Bug introduced by
The method addOAuthAccount() does not seem to exist on object<Symfony\Component...ore\User\UserInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
70
        $this->userManager->updateUser($user);
71
    }
72
73
    /**
74
     * Ad-hoc creation of user.
75
     *
76
     * @param UserResponseInterface $response
77
     *
78
     * @return User
79
     */
80
    protected function createUserByOAuthUserResponse(UserResponseInterface $response)
81
    {
82
        $user = $this->userManager->createUser();
83
        $this->updateUserByOAuthUserResponse($user, $response);
84
85
        $data = $response->getResponse();
86
87
        $slugify  = new Slugify();
88
        $nickname = $slugify->slugify($data['first_name']);
89
90
        // set default values taken from OAuth sign-in provider account
91
        //$user->setBirthdate(new \DateTime($data['birthday']));
0 ignored issues
show
Unused Code Comprehensibility introduced by
80% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
92
        $user->setFirstname($data['first_name']);
93
        $user->setLastname($data['last_name']);
94
95
        if (null !== $email = $response->getEmail()) {
96
            $user->setEmail($email);
97
        }
98
99
        $originalNickname = $nickname;
100
        while (null !== $this->userManager->findUserByUsername($nickname)) {
101
            $nickname = $originalNickname.rand(0, 5000);
102
        }
103
104
        $user->setUsername($nickname);
105
        $user->setEnabled(true);
106
107
        $event = new UserEvent($user, $this->request);
0 ignored issues
show
Bug introduced by
It seems like $this->request can be null; however, __construct() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
108
        $this->dispatcher->dispatch("user.registration.done", $event);
109
110
        return $user;
111
    }
112
113
    /**
114
     * Attach OAuth sign-in provider account to existing user.
115
     *
116
     * @param FOSUserInterface      $user
117
     * @param UserResponseInterface $response
118
     *
119
     * @return FOSUserInterface
120
     */
121
    protected function updateUserByOAuthUserResponse(FOSUserInterface $user, UserResponseInterface $response)
122
    {
123
        $providerName = $response->getResourceOwner()->getName();
124
        $providerNameSetter = 'set'.ucfirst($providerName).'Id';
125
        $user->$providerNameSetter($response->getUsername());
126
        if (!$user->getPassword()) {
127
            // generate unique token
128
            $secret = md5(uniqid(rand(), true));
129
            $user->setPassword($secret);
130
        }
131
132
        return $user;
133
    }
134
}
135