Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
22 / 22
100.00% covered (success)
100.00%
8 / 8
CRAP
100.00% covered (success)
100.00%
1 / 1
Reddit
100.00% covered (success)
100.00%
22 / 22
100.00% covered (success)
100.00%
8 / 8
10
100.00% covered (success)
100.00%
1 / 1
 getAuthorizeUrl
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getAccessTokenUrl
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getScope
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getFullAuthorizeUrl
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getAccessToken
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 getUserProfile
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
3
 getLogoSource
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getThemeColor
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace Miniframe\SocialLogin\Provider;
4
5use Miniframe\Core\Config;
6use Miniframe\Core\Request;
7use Miniframe\SocialLogin\Model\User;
8
9class Reddit extends AbstractOAuth2Provider
10{
11    /**
12     * User agent for the cURL requests (Reddit requires a specific format)
13     *
14     * @var string
15     */
16    protected $userAgent = 'PHP:MiniframeSocialLogin:1.0 (by /u/garrcomm)';
17
18    /**
19     * Returns the Authorize URL
20     *
21     * @return string
22     */
23    protected function getAuthorizeUrl(): string
24    {
25        return 'https://www.reddit.com/api/v1/authorize';
26    }
27
28    /**
29     * Returns the Access Token URL
30     *
31     * @return string
32     */
33    protected function getAccessTokenUrl(): string
34    {
35        return 'https://www.reddit.com/api/v1/access_token';
36    }
37
38    /**
39     * Returns the requested scope
40     *
41     * @return string|null
42     */
43    protected function getScope(): ?string
44    {
45        return 'identity';
46    }
47
48    /**
49     * Gets a full authorize URL, including the client ID and all other required parameters.
50     *
51     * @param array $data Optionally extra fields to append to the authorize URL.
52     *
53     * @return string
54     */
55    protected function getFullAuthorizeUrl(array $data = array()): string
56    {
57        $data['duration'] = 'temporary';
58        return parent::getFullAuthorizeUrl($data);
59    }
60
61    /**
62     * Reddit doesn't follow the original flow but has another way instead for getting the access token.
63     *
64     * @param string $code The provided code.
65     *
66     * @return array
67     */
68    protected function getAccessToken(string $code): array
69    {
70        $data = array(
71            'code' => $code,
72            'redirect_uri' => $this->getCurrentUri(),
73            'grant_type' => 'authorization_code',
74        );
75        $headers = array(
76            'Authorization: Basic ' . base64_encode($this->clientId . ':' . $this->clientSecret),
77        );
78
79        return $this->curlRequest($this->getAccessTokenUrl(), 'POST', $data, $headers);
80    }
81
82    /**
83     * Returns the user profile
84     *
85     * @param array $accessToken The access token.
86     *
87     * @return User
88     */
89    protected function getUserProfile(array $accessToken): User
90    {
91        $data = $this->curlRequest('https://oauth.reddit.com/api/v1/me', 'GET', null, [
92            'Authorization: Bearer ' . $accessToken['access_token'],
93        ]);
94
95        if ($data['subreddit']['user_is_banned']) {
96            throw new \RuntimeException('User is banned');
97        }
98        if (!$data['has_verified_email']) {
99            throw new \RuntimeException('Email address not yet verified');
100        }
101
102        return new User(
103            $data['id'],
104            $data['name'],
105            $data['subreddit']['title'],
106            html_entity_decode($data['icon_img']), // Reddit encodes the image URL for some reason
107            static::class,
108            ['accessToken' => $accessToken, 'userData' => $data]
109        );
110    }
111
112    /**
113     * Returns the image source for the logo of this provider.
114     *
115     * @return string
116     */
117    public static function getLogoSource(): string
118    {
119        return 'data:image/svg+xml;base64,'
120            . base64_encode(file_get_contents(__DIR__ . '/../../templates/logos/Reddit.svg'));
121    }
122
123    /**
124     * Returns the theme color for this provider.
125     *
126     * @return string
127     */
128    public static function getThemeColor(): string
129    {
130        return 'rgb(255,99,20)';
131    }
132}