LinkedIn::getIdentity()   B
last analyzed

Complexity

Conditions 9
Paths 4

Size

Total Lines 59
Code Lines 34

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 19
CRAP Score 12.994

Importance

Changes 5
Bugs 0 Features 0
Metric Value
cc 9
eloc 34
c 5
b 0
f 0
nc 4
nop 1
dl 0
loc 59
ccs 19
cts 30
cp 0.6333
crap 12.994
rs 8.0555

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
 * SocialConnect project
4
 * @author: Patsura Dmitry https://github.com/ovr <[email protected]>
5
 * @author: Bogdan Popa https://github.com/icex <[email protected]>
6
 */
7
declare(strict_types=1);
8
9
namespace SocialConnect\OAuth2\Provider;
10
11
use SocialConnect\Common\ArrayHydrator;
12
use SocialConnect\Provider\AccessTokenInterface;
13
use SocialConnect\Common\Entity\User;
14
15
class LinkedIn extends \SocialConnect\OAuth2\AbstractProvider
16
{
17
    const NAME = 'linkedin';
18
19
    /**
20
     * @var array
21
     */
22
    protected $options = [
23
        /**
24
         * It's needed additional API call to fetch email, by default it's disabled
25
         */
26
        'fetch_emails' => false
27
    ];
28
29
    /**
30
     * {@inheritdoc}
31
     */
32 4
    public function getBaseUri()
33
    {
34 4
        return 'https://api.linkedin.com/v2/';
35
    }
36
37
    /**
38
     * {@inheritdoc}
39
     */
40 2
    public function getAuthorizeUri()
41
    {
42 2
        return 'https://www.linkedin.com/oauth/v2/authorization';
43
    }
44
45
    /**
46
     * {@inheritdoc}
47
     */
48 2
    public function getRequestTokenUri()
49
    {
50 2
        return 'https://www.linkedin.com/oauth/v2/accessToken';
51
    }
52
53
    /**
54
     * {@inheritdoc}
55
     */
56 3
    public function getName()
57
    {
58 3
        return self::NAME;
59
    }
60
61
    /**
62
     * {@inheritDoc}
63
     */
64 3
    public function prepareRequest(string $method, string $uri, array &$headers, array &$query, AccessTokenInterface $accessToken = null): void
65
    {
66 3
        $headers['Content-Type'] = 'application/json';
67
68 3
        if ($accessToken) {
69 3
            $headers['Authorization'] = "Bearer {$accessToken->getToken()}";
70
        }
71 3
    }
72
73
    protected function fetchPrimaryEmail(AccessTokenInterface $accessToken, User $user)
74
    {
75
        $response = $this->request(
76
            'GET',
77
            'emailAddress',
78
            [
79
                'q' => 'members',
80
                'projection' => '(elements*(primary,type,handle~))'
81
            ],
82
            $accessToken
83
        );
84
85
        if (isset($response['elements'])) {
86
            $element = array_shift($response['elements']);
87
            if ($element && isset($element['handle~']) && isset($element['handle~']['emailAddress'])) {
88
                $user->email = $element['handle~']['emailAddress'];
89
                // Tested on my user, I've got two emails and linkedin return only primary and it's verified
90
                $user->emailVerified = true;
91
            }
92
        }
93
    }
94
95
    /**
96
     * {@inheritdoc}
97
     */
98 3
    public function getIdentity(AccessTokenInterface $accessToken)
99
    {
100 3
        $query = [];
101
102
        // @link https://docs.microsoft.com/en-us/linkedin/shared/integrations/people/profile-api?context=linkedin/consumer/context
103 3
        $fields = $this->getArrayOption(
104 3
            'identity.fields',
105
            [
106 3
                'id',
107
                'firstName',
108
                'lastName',
109
                'profilePicture(displayImage~:playableStreams)',
110
            ]
111
        );
112 3
        if ($fields) {
113 3
            $query['projection'] = '(' . implode(',', $fields) . ')';
114
        }
115
116 3
        $response = $this->request(
117 3
            'GET',
118 3
            'me',
119
            $query,
120
            $accessToken
121
        );
122
123 1
        $hydrator = new ArrayHydrator([
124 1
            'id'           => 'id',
125 1
            'emailAddress' => 'email',
126
            'firstName'    => static function ($value, User $user) {
127
                if ($value['localized']) {
128
                    $user->firstname = array_pop($value['localized']);
129
                }
130 1
            },
131
            'lastName'     => static function ($value, User $user) {
132
                if ($value['localized']) {
133
                    $user->lastname = array_pop($value['localized']);
134
                }
135 1
            },
136
            'profilePicture'     => static function ($value, User $user) {
137
                if (isset($value['displayImage~']) && isset($value['displayImage~']['elements'])) {
138
                    $biggestElement = array_shift($value['displayImage~']['elements']);
139
                    if (isset($biggestElement['identifiers'])) {
140
                        $biggestElementIdentifier = array_pop($biggestElement['identifiers']);
141
                        if (isset($biggestElementIdentifier['identifier'])) {
142
                            $user->pictureURL = $biggestElementIdentifier['identifier'];
143
                        }
144
                    }
145
                }
146 1
            },
147
        ]);
148
149
        /** @var User $identity */
150 1
        $identity = $hydrator->hydrate(new User(), $response);
151
152 1
        if ($this->getBoolOption('fetch_emails', false)) {
153
            $this->fetchPrimaryEmail($accessToken, $identity);
154
        }
155
156 1
        return $identity;
157
    }
158
}
159