LinkedIn::fetchPrimaryEmail()   A
last analyzed

Complexity

Conditions 5
Paths 3

Size

Total Lines 18
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 5
eloc 11
nc 3
nop 2
dl 0
loc 18
ccs 0
cts 7
cp 0
crap 30
rs 9.6111
c 2
b 0
f 0
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
    }
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
            'identity.fields',
105
            [
106
                '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
            'GET',
118
            'me',
119
            $query,
120
            $accessToken
121
        );
122
123 1
        $hydrator = new ArrayHydrator([
124
            'id'           => 'id',
125
            'emailAddress' => 'email',
126 1
            'firstName'    => static function ($value, User $user) {
127
                if ($value['localized']) {
128
                    $user->firstname = array_pop($value['localized']);
129
                }
130
            },
131 1
            'lastName'     => static function ($value, User $user) {
132
                if ($value['localized']) {
133
                    $user->lastname = array_pop($value['localized']);
134
                }
135
            },
136 1
            '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
            },
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