GitHub   A
last analyzed

Complexity

Total Complexity 16

Size/Duplication

Total Lines 139
Duplicated Lines 0 %

Test Coverage

Coverage 41.18%

Importance

Changes 3
Bugs 0 Features 0
Metric Value
wmc 16
eloc 52
dl 0
loc 139
rs 10
c 3
b 0
f 0
ccs 21
cts 51
cp 0.4118

7 Methods

Rating   Name   Duplication   Size   Complexity  
A getRequestTokenUri() 0 3 1
A getPrimaryEmail() 0 12 4
A getEmails() 0 25 3
A getName() 0 3 1
A getBaseUri() 0 3 1
A getAuthorizeUri() 0 3 1
A getIdentity() 0 46 5
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
                'name' => 'fullname'
86
            ]
87
        );
88
89
        /** @var User $user */
90
        $user = $hydrator->hydrate(new User(), $result);
91
92
        if ($this->getBoolOption('fetch_emails', false)) {
93
            $primaryEmail = $this->getPrimaryEmail($accessToken);
94
            if ($primaryEmail) {
0 ignored issues
show
introduced by Dmitry Patsura
$primaryEmail is of type object, thus it always evaluated to true.
Loading history...
95
                $user->email = $primaryEmail->email;
96
                $user->emailVerified = $primaryEmail->verified;
97
            }
98
        }
99
100
        return $user;
101
    }
102
103
104
    /**
105
     * @param AccessTokenInterface $accessToken
106
     * @return object
107
     * @throws InvalidResponse
108
     */
109
    public function getPrimaryEmail(AccessTokenInterface $accessToken)
110
    {
111
        $emails = $this->getEmails($accessToken);
112
        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...
113
            foreach ($emails as $email) {
114
                if ($email->primary) {
115
                    return $email;
116
                }
117
            }
118
        }
119
120
        return null;
121
    }
122
123
    /**
124
     * @param AccessTokenInterface $accessToken
125
     * @return array
126
     * @throws InvalidResponse
127
     */
128
    public function getEmails(AccessTokenInterface $accessToken)
129
    {
130
        $response = $this->httpClient->request(
131
            $this->getBaseUri() . 'user/emails',
132
            [
133
                'access_token' => $accessToken->getToken()
134
            ]
135
        );
136
137
        if (!$response->isSuccess()) {
138
            throw new InvalidResponse(
139
                'API response with error code',
140
                $response
141
            );
142
        }
143
144
        $result = $response->json();
145
        if (!$result) {
146
            throw new InvalidResponse(
147
                'API response is not a valid JSON object',
148
                $response
149
            );
150
        }
151
152
        return $result;
153
    }
154
}
155