Completed
Push — master ( 9ab7a4...7b2d5d )
by Дмитрий
02:51
created

GitHub::getIdentity()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 46
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 8.125

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 46
ccs 15
cts 30
cp 0.5
rs 8.4751
cc 5
eloc 25
nc 5
nop 1
crap 8.125
1
<?php
2
/**
3
 * SocialConnect project
4
 * @author: Patsura Dmitry https://github.com/ovr <[email protected]>
5
 */
6
7
namespace SocialConnect\OAuth2\Provider;
8
9
use SocialConnect\Provider\AccessTokenInterface;
10
use SocialConnect\Provider\Exception\InvalidResponse;
11
use SocialConnect\Common\Entity\User;
12
use SocialConnect\Common\Hydrator\ObjectMap;
13
14
class GitHub extends \SocialConnect\OAuth2\AbstractProvider
15
{
16
    /**
17
     * @var array
18
     */
19
    protected $options = [
20
        /**
21
         * GitHub store only unverified and public email inside User
22
         * It's not possible to fetch user with email in GraphQL (new api)
23
         * For now, there is only one way, additional request for it by user/email API entrypoint
24
         *
25
         * It's disabled by default in SocialConnect 1.x, but you can enable it from configuration :)
26
         */
27
        'fetch_emails' => false
28
    ];
29
30 3
    public function getBaseUri()
31
    {
32 3
        return 'https://api.github.com/';
33
    }
34
35 2
    public function getAuthorizeUri()
36
    {
37 2
        return 'https://github.com/login/oauth/authorize';
38
    }
39
40 2
    public function getRequestTokenUri()
41
    {
42 2
        return 'https://github.com/login/oauth/access_token';
43
    }
44
45 3
    public function getName()
46
    {
47 3
        return 'github';
48
    }
49
50
    /**
51
     * {@inheritdoc}
52
     */
53 2
    public function getIdentity(AccessTokenInterface $accessToken)
54
    {
55 2
        $response = $this->httpClient->request(
56 2
            $this->getBaseUri() . 'user',
57
            [
58 2
                'access_token' => $accessToken->getToken()
59 2
            ]
60 2
        );
61
62 2
        if (!$response->isSuccess()) {
63 1
            throw new InvalidResponse(
64 1
                'API response with error code',
65
                $response
66 1
            );
67
        }
68
69 1
        $result = $response->json();
70 1
        if (!$result) {
71 1
            throw new InvalidResponse(
72 1
                'API response is not a valid JSON object',
73
                $response
74 1
            );
75
        }
76
77
        $hydrator = new ObjectMap(
78
            [
79
                'id' => 'id',
80
                'login' => 'username',
81
                'email' => 'email',
82
                'avatar_url' => 'pictureURL'
83
            ]
84
        );
85
86
        /** @var User $user */
87
        $user = $hydrator->hydrate(new User(), $result);
88
89
        if ($this->getBoolOption('fetch_emails', false)) {
90
            $primaryEmail = $this->getPrimaryEmail($accessToken);
91
            if ($primaryEmail) {
92
                $user->email = $primaryEmail->email;
93
                $user->emailVerified = $primaryEmail->verified;
94
            }
95
        }
96
97
        return $user;
98
    }
99
100
101
    /**
102
     * @param AccessTokenInterface $accessToken
103
     * @return object
104
     * @throws InvalidResponse
105
     */
106
    public function getPrimaryEmail(AccessTokenInterface $accessToken)
107
    {
108
        $emails = $this->getEmails($accessToken);
109
        if ($emails) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $emails of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
110
            foreach ($emails as $email) {
111
                if ($email->primary) {
112
                    return $email;
113
                }
114
            }
115
        }
116
117
        return null;
118
    }
119
120
    /**
121
     * @param AccessTokenInterface $accessToken
122
     * @return array
123
     * @throws InvalidResponse
124
     */
125
    public function getEmails(AccessTokenInterface $accessToken)
126
    {
127
        $response = $this->httpClient->request(
128
            $this->getBaseUri() . 'user/emails',
129
            [
130
                'access_token' => $accessToken->getToken()
131
            ]
132
        );
133
134
        if (!$response->isSuccess()) {
135
            throw new InvalidResponse(
136
                'API response with error code',
137
                $response
138
            );
139
        }
140
141
        $result = $response->json();
142
        if (!$result) {
143
            throw new InvalidResponse(
144
                'API response is not a valid JSON object',
145
                $response
146
            );
147
        }
148
149
        return $result;
150
    }
151
}
152