GitHub   A
last analyzed

Complexity

Total Complexity 16

Size/Duplication

Total Lines 140
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Test Coverage

Coverage 41.18%

Importance

Changes 0
Metric Value
wmc 16
lcom 1
cbo 7
dl 0
loc 140
ccs 21
cts 51
cp 0.4118
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A getBaseUri() 0 4 1
A getAuthorizeUri() 0 4 1
A getRequestTokenUri() 0 4 1
A getName() 0 4 1
B getIdentity() 0 46 5
A getPrimaryEmail() 0 13 4
A getEmails() 0 26 3
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
    const NAME = 'github';
17
18
    /**
19
     * @var array
20
     */
21
    protected $options = [
22
        /**
23
         * GitHub store only unverified and public email inside User
24
         * It's not possible to fetch user with email in GraphQL (new api)
25
         * For now, there is only one way, additional request for it by user/email API entrypoint
26
         *
27
         * It's disabled by default in SocialConnect 1.x, but you can enable it from configuration :)
28
         */
29
        'fetch_emails' => false
30
    ];
31
32 3
    public function getBaseUri()
33
    {
34 3
        return 'https://api.github.com/';
35
    }
36
37 2
    public function getAuthorizeUri()
38
    {
39 2
        return 'https://github.com/login/oauth/authorize';
40
    }
41
42 2
    public function getRequestTokenUri()
43
    {
44 2
        return 'https://github.com/login/oauth/access_token';
45
    }
46
47 3
    public function getName()
48
    {
49 3
        return self::NAME;
50
    }
51
52
    /**
53
     * {@inheritdoc}
54
     */
55 2
    public function getIdentity(AccessTokenInterface $accessToken)
56
    {
57 2
        $response = $this->httpClient->request(
58 2
            $this->getBaseUri() . 'user',
59
            [
60 2
                'access_token' => $accessToken->getToken()
61
            ]
62
        );
63
64 2
        if (!$response->isSuccess()) {
65 1
            throw new InvalidResponse(
66 1
                'API response with error code',
67 1
                $response
68
            );
69
        }
70
71 1
        $result = $response->json();
72 1
        if (!$result) {
73 1
            throw new InvalidResponse(
74 1
                'API response is not a valid JSON object',
75 1
                $response
76
            );
77
        }
78
79
        $hydrator = new ObjectMap(
80
            [
81
                'id' => 'id',
82
                'login' => 'username',
83
                'email' => 'email',
84
                'avatar_url' => 'pictureURL'
85
            ]
86
        );
87
88
        /** @var User $user */
89
        $user = $hydrator->hydrate(new User(), $result);
90
91
        if ($this->getBoolOption('fetch_emails', false)) {
92
            $primaryEmail = $this->getPrimaryEmail($accessToken);
93
            if ($primaryEmail) {
94
                $user->email = $primaryEmail->email;
95
                $user->emailVerified = $primaryEmail->verified;
96
            }
97
        }
98
99
        return $user;
100
    }
101
102
103
    /**
104
     * @param AccessTokenInterface $accessToken
105
     * @return object
106
     * @throws InvalidResponse
107
     */
108
    public function getPrimaryEmail(AccessTokenInterface $accessToken)
109
    {
110
        $emails = $this->getEmails($accessToken);
111
        if ($emails) {
0 ignored issues
show
Bug Best Practice introduced by Dmitry Patsura
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...
112
            foreach ($emails as $email) {
113
                if ($email->primary) {
114
                    return $email;
115
                }
116
            }
117
        }
118
119
        return null;
120
    }
121
122
    /**
123
     * @param AccessTokenInterface $accessToken
124
     * @return array
125
     * @throws InvalidResponse
126
     */
127
    public function getEmails(AccessTokenInterface $accessToken)
128
    {
129
        $response = $this->httpClient->request(
130
            $this->getBaseUri() . 'user/emails',
131
            [
132
                'access_token' => $accessToken->getToken()
133
            ]
134
        );
135
136
        if (!$response->isSuccess()) {
137
            throw new InvalidResponse(
138
                'API response with error code',
139
                $response
140
            );
141
        }
142
143
        $result = $response->json();
144
        if (!$result) {
145
            throw new InvalidResponse(
146
                'API response is not a valid JSON object',
147
                $response
148
            );
149
        }
150
151
        return $result;
152
    }
153
}
154