Passed
Push — master ( 3e41fe...15a2ff )
by Francis
01:32
created

GMail::refreshAccessToken()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 28
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 22
c 0
b 0
f 0
dl 0
loc 28
rs 9.568
cc 3
nc 4
nop 1
1
<?php
2
declare(strict_types=1);
3
defined('BASEPATH') OR exit('No direct script access allowed');
4
5
require_once('GMailScopes.php');
6
require_once('GMailUtil.php');
7
8
class GMail {
9
10
  const AUTH_URL  = 'https://accounts.google.com/o/oauth2/auth';
11
  const TOKEN_URL = 'https://www.googleapis.com/oauth2/v4/token';
12
  const API       = 'https://www.googleapis.com/gmail/v1/users/';
13
  const HTTP_CODE = 'http_code';
14
  private $clientId;
15
  private $clientSecret;
16
  private $redirectUri = 'urn:ietf:wg:oauth:2.0:oob';
17
  private $token;
18
  private $userAgent = 'CodeIgniter GMail API';
19
20
  function __construct($params=null) {
21
    get_instance()->load->splint('francis94c/ci-gmail', '%curl');
0 ignored issues
show
Bug introduced by
The function get_instance was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

21
    /** @scrutinizer ignore-call */ 
22
    get_instance()->load->splint('francis94c/ci-gmail', '%curl');
Loading history...
22
    if ($params != null) $this->init($params);
23
  }
24
25
  /**
26
   * [init Initialize library with cofigs. Can be called multiple times to set
27
   *       config items]
28
   * @param array $config Associative Config Array.
29
   */
30
  public function init(array $config):void {
31
    $this->clientId = $config['client_id'] ?? $this->clientId;
32
    $this->clientSecret = $config['client_secret'] ?? $this->clientSecret;
33
    $this->redirectUri = $config['redirect_uri'] ?? $this->redirectUri;
34
  }
35
  /**
36
   * [setAccessToken description]
37
   * @param string $token [description]
38
   */
39
  public function setAccessToken(string $token):void {
40
    $this->token = $token;
41
  }
42
  /**
43
   * [getClientId Get Client ID.]
44
   * @return null|string Client ID.
45
   */
46
  public function getClientId():?string {
47
    return $this->clientId;
48
  }
49
  /**
50
   * [getAuthorizeUrl Gets/composes the authorize url to direct users to so they
51
   *                  can give your application access to their GMail accounts
52
   *                  based on the given scopes.]
53
   * @param  string $scope        Access Scope.
54
   * @param  string $redirectUri  URL to redirect to after access is granted.
55
   * @param  string $responseType Response type. 'code' by default.
56
   * @param  bool   $prompt       Add the prompt=consent query to the URL.
57
   * @return string               Authorize URL
58
   */
59
  public function getAuthorizeUrl(string $scope, string $redirectUri=null, string $responseType='code', string $accessType='offline', bool $prompt=false):string {
60
    $redirectUri = $redirectUri ?? $this->redirectUri;
61
    if ($scope == null) throw new Exception("GMail scope cannot be null");
62
    $params = [
63
      'client_id'     => $this->clientId,
64
      'redirect_uri'  => $redirectUri,
65
      'scope'         => $scope,
66
      'response_type' => $responseType,
67
      'access_type'   => $accessType
68
    ];
69
    if ($prompt) $params['prompt'] = 'consent';
70
    return self::AUTH_URL . build_url_query($params, false);
71
  }
72
  /**
73
   * [getToken description]
74
   * @param  string $code [description]
75
   * @return [type]       [description]
0 ignored issues
show
Documentation Bug introduced by
The doc comment [type] at position 0 could not be parsed: Unknown type name '[' at position 0 in [type].
Loading history...
76
   */
77
  public function getToken(string $code, string $redirectUri=null):?array {
78
    $redirectUri = $redirectUri ?? $this->redirectUri;
0 ignored issues
show
Unused Code introduced by
The assignment to $redirectUri is dead and can be removed.
Loading history...
79
    $ch = curl_init(self::TOKEN_URL);
80
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
0 ignored issues
show
Bug introduced by
It seems like $ch can also be of type false; however, parameter $ch of curl_setopt() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

80
    curl_setopt(/** @scrutinizer ignore-type */ $ch, CURLOPT_RETURNTRANSFER, true);
Loading history...
81
    curl_setopt($ch, CURLINFO_HEADER_OUT, true);
82
    if (ENVIRONMENT == 'development') {
0 ignored issues
show
Bug introduced by
The constant ENVIRONMENT was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
83
      curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
84
    }
85
    $body = http_build_query([
86
      'code'          => $code,
87
      'client_id'     => $this->clientId,
88
      'client_secret' => $this->clientSecret,
89
      'redirect_uri'  => $this->redirectUri,
90
      'grant_type'    => 'authorization_code'
91
    ]);
92
    $header = [
93
      'Content-Type: application/x-www-form-urlencoded',
94
      'Content-Length: ' . strlen($body)
95
    ];
96
    curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
97
    curl_setopt($ch, CURLOPT_USERAGENT, $this->userAgent);
98
    // Request Method and Body.
99
    curl_setopt($ch, CURLOPT_POST, true);
100
    curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
101
    $response = curl_exec($ch);
0 ignored issues
show
Bug introduced by
It seems like $ch can also be of type false; however, parameter $ch of curl_exec() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

101
    $response = curl_exec(/** @scrutinizer ignore-type */ $ch);
Loading history...
102
    $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
0 ignored issues
show
Bug introduced by
It seems like $ch can also be of type false; however, parameter $ch of curl_getinfo() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

102
    $code = curl_getinfo(/** @scrutinizer ignore-type */ $ch, CURLINFO_HTTP_CODE);
Loading history...
103
    curl_close($ch);
0 ignored issues
show
Bug introduced by
It seems like $ch can also be of type false; however, parameter $ch of curl_close() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

103
    curl_close(/** @scrutinizer ignore-type */ $ch);
Loading history...
104
    if ($response !== false) return $this->process_response($code, $response);
0 ignored issues
show
Bug introduced by
It seems like $response can also be of type true; however, parameter $response of GMail::process_response() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

104
    if ($response !== false) return $this->process_response($code, /** @scrutinizer ignore-type */ $response);
Loading history...
105
    return null;
106
  }
107
  /**
108
   * [refreshAccessToken description]
109
   * @param  string $refreshToken [description]
110
   * @return [type]               [description]
0 ignored issues
show
Documentation Bug introduced by
The doc comment [type] at position 0 could not be parsed: Unknown type name '[' at position 0 in [type].
Loading history...
111
   */
112
  public function refreshAccessToken(string $refreshToken):?array {
113
    $ch = curl_init(self::TOKEN_URL);
114
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
0 ignored issues
show
Bug introduced by
It seems like $ch can also be of type false; however, parameter $ch of curl_setopt() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

114
    curl_setopt(/** @scrutinizer ignore-type */ $ch, CURLOPT_RETURNTRANSFER, true);
Loading history...
115
    curl_setopt($ch, CURLINFO_HEADER_OUT, true);
116
    if (ENVIRONMENT == 'development') {
0 ignored issues
show
Bug introduced by
The constant ENVIRONMENT was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
117
      curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
118
    }
119
    $body = http_build_query([
120
      'refresh_token' => $refreshToken,
121
      'client_id'     => $this->clientId,
122
      'client_secret' => $this->clientSecret,
123
      'grant_type'    => 'refresh_token'
124
    ]);
125
    $header = [
126
      'Content-Type: application/x-www-form-urlencoded',
127
      'Content-Length: ' . strlen($body)
128
    ];
129
    curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
130
    curl_setopt($ch, CURLOPT_USERAGENT, $this->userAgent);
131
    // Request Method and Body.
132
    curl_setopt($ch, CURLOPT_POST, true);
133
    curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
134
    // Exec.
135
    $response = curl_exec($ch);
0 ignored issues
show
Bug introduced by
It seems like $ch can also be of type false; however, parameter $ch of curl_exec() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

135
    $response = curl_exec(/** @scrutinizer ignore-type */ $ch);
Loading history...
136
    $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
0 ignored issues
show
Bug introduced by
It seems like $ch can also be of type false; however, parameter $ch of curl_getinfo() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

136
    $code = curl_getinfo(/** @scrutinizer ignore-type */ $ch, CURLINFO_HTTP_CODE);
Loading history...
137
    curl_close($ch);
0 ignored issues
show
Bug introduced by
It seems like $ch can also be of type false; however, parameter $ch of curl_close() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

137
    curl_close(/** @scrutinizer ignore-type */ $ch);
Loading history...
138
    if ($response !== false) return $this->process_response($code, $response);
0 ignored issues
show
Bug introduced by
It seems like $response can also be of type true; however, parameter $response of GMail::process_response() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

138
    if ($response !== false) return $this->process_response($code, /** @scrutinizer ignore-type */ $response);
Loading history...
139
    return null;
140
  }
141
  /**
142
   * [getProfile Get user's profile
143
   * see https://developers.google.com/gmail/api/v1/reference/users/getProfile]
144
   * @param  string $user [description]
145
   * @return [type]       [description]
0 ignored issues
show
Documentation Bug introduced by
The doc comment [type] at position 0 could not be parsed: Unknown type name '[' at position 0 in [type].
Loading history...
146
   */
147
  public function getProfile(string $user='me'):?array {
148
    list($code, $response) = (new GMailCURL(GMailCURL::GET))(
149
      self::API . "$user/profile",
150
      ["Authorization: Bearer $this->token"]
151
    );
152
    if ($response !== false) return $this->process_response($code, $response);
153
    return null;
154
  }
155
  /**
156
   * [watch Causes push notifications to be sent on events which occur in the
157
   * user's mailbox. Requires Google Cloud PubSub.
158
   * see https://developers.google.com/gmail/api/v1/reference/users/watch]
159
   * @param  string $topic             Topic to push events to.
160
   * @param  mixed  $labelIds          Narrow down labels in the mailbox, whose
161
   *                                   mailbox event, are being listened to.
162
   *                                   events are to be listened to.
163
   * @param  string $userId            The ID/Email address of the user whose
164
   * @param  string $labelFilterAction [description]
165
   * @return [type]                    [description]
0 ignored issues
show
Documentation Bug introduced by
The doc comment [type] at position 0 could not be parsed: Unknown type name '[' at position 0 in [type].
Loading history...
166
   */
167
  public function watch(string $topic, $labelIds=null, string $userId='me', string $labelFilterAction='include'):?array {
168
    $body = [
169
      'topicName'         => $topic,
170
      'labelFilterAction' => $labelFilterAction
171
    ];
172
173
    if ($labelIds != null) {
174
      if (is_scalar($labelIds)) {
175
        $body['labelIds'] = [$labelIds];
176
      } elseif (is_array($labelIds)) {
177
        $body['labelIds'] = $labelIds;
178
      }
179
    }
180
181
    list($code, $response) = (new GMailCURL(GMailCURL::POST))(
182
      self::API . "$userId/watch",
183
      ["Authorization: Bearer $this->token"],
184
      $body
185
    );
186
    if ($response !== false) return $this->process_response($code, $response);
187
    return null;
188
  }
189
  /**
190
   * [process_response description]
191
   * @param  int    $code   [description]
192
   * @param  string $response [description]
193
   * @return [type]         [description]
0 ignored issues
show
Documentation Bug introduced by
The doc comment [type] at position 0 could not be parsed: Unknown type name '[' at position 0 in [type].
Loading history...
194
   */
195
  private function process_response(int $code, string $response) {
196
    $response = json_decode($response, true);
197
    $response[self::HTTP_CODE] = $code;
198
    return $response;
199
  }
200
}
201
?>
0 ignored issues
show
Best Practice introduced by
It is not recommended to use PHP's closing tag ?> in files other than templates.

Using a closing tag in PHP files that only contain PHP code is not recommended as you might accidentally add whitespace after the closing tag which would then be output by PHP. This can cause severe problems, for example headers cannot be sent anymore.

A simple precaution is to leave off the closing tag as it is not required, and it also has no negative effects whatsoever.

Loading history...
202