Passed
Push — master ( f10fb0...03a61c )
by Francis
01:20
created

GMail::getMessages()   B

Complexity

Conditions 9
Paths 96

Size

Total Lines 31
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 18
c 0
b 0
f 0
dl 0
loc 31
rs 8.0555
cc 9
nc 96
nop 7
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
require_once('Message.php');
8
9
class GMail {
10
11
  const AUTH_URL  = 'https://accounts.google.com/o/oauth2/auth';
12
  const TOKEN_URL = 'https://www.googleapis.com/oauth2/v4/token';
13
  const API       = 'https://www.googleapis.com/gmail/v1/users/';
14
  const HTTP_CODE = 'http_code';
15
  private $clientId;
16
  private $clientSecret;
17
  private $redirectUri = 'urn:ietf:wg:oauth:2.0:oob';
18
  private $token;
19
  private $userAgent = 'CodeIgniter GMail API';
20
21
  function __construct($params=null) {
22
    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

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

84
    curl_setopt(/** @scrutinizer ignore-type */ $ch, CURLOPT_RETURNTRANSFER, true);
Loading history...
85
    curl_setopt($ch, CURLINFO_HEADER_OUT, true);
86
    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...
87
      curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
88
    }
89
    $body = http_build_query([
90
      'code'          => $code,
91
      'client_id'     => $this->clientId,
92
      'client_secret' => $this->clientSecret,
93
      'redirect_uri'  => $this->redirectUri,
94
      'grant_type'    => 'authorization_code'
95
    ]);
96
    $header = [
97
      'Content-Type: application/x-www-form-urlencoded',
98
      'Content-Length: ' . strlen($body)
99
    ];
100
    curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
101
    curl_setopt($ch, CURLOPT_USERAGENT, $this->userAgent);
102
    // Request Method and Body.
103
    curl_setopt($ch, CURLOPT_POST, true);
104
    curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
105
    $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

105
    $response = curl_exec(/** @scrutinizer ignore-type */ $ch);
Loading history...
106
    $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

106
    $code = curl_getinfo(/** @scrutinizer ignore-type */ $ch, CURLINFO_HTTP_CODE);
Loading history...
107
    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

107
    curl_close(/** @scrutinizer ignore-type */ $ch);
Loading history...
108
    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

108
    if ($response !== false) return $this->process_response($code, /** @scrutinizer ignore-type */ $response);
Loading history...
109
    return null;
110
  }
111
  /**
112
   * [refreshAccessToken description]
113
   * @param  string $refreshToken [description]
114
   * @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...
115
   */
116
  public function refreshAccessToken(string $refreshToken):?array {
117
    $ch = curl_init(self::TOKEN_URL);
118
    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

118
    curl_setopt(/** @scrutinizer ignore-type */ $ch, CURLOPT_RETURNTRANSFER, true);
Loading history...
119
    curl_setopt($ch, CURLINFO_HEADER_OUT, true);
120
    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...
121
      curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
122
    }
123
    $body = http_build_query([
124
      'refresh_token' => $refreshToken,
125
      'client_id'     => $this->clientId,
126
      'client_secret' => $this->clientSecret,
127
      'grant_type'    => 'refresh_token'
128
    ]);
129
    $header = [
130
      'Content-Type: application/x-www-form-urlencoded',
131
      'Content-Length: ' . strlen($body)
132
    ];
133
    curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
134
    curl_setopt($ch, CURLOPT_USERAGENT, $this->userAgent);
135
    // Request Method and Body.
136
    curl_setopt($ch, CURLOPT_POST, true);
137
    curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
138
    // Exec.
139
    $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

139
    $response = curl_exec(/** @scrutinizer ignore-type */ $ch);
Loading history...
140
    $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

140
    $code = curl_getinfo(/** @scrutinizer ignore-type */ $ch, CURLINFO_HTTP_CODE);
Loading history...
141
    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

141
    curl_close(/** @scrutinizer ignore-type */ $ch);
Loading history...
142
    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

142
    if ($response !== false) return $this->process_response($code, /** @scrutinizer ignore-type */ $response);
Loading history...
143
    return null;
144
  }
145
  /**
146
   * [getProfile Get user's profile
147
   * see https://developers.google.com/gmail/api/v1/reference/users/getProfile]
148
   * @param  string $user [description]
149
   * @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...
150
   */
151
  public function getProfile(string $user='me'):?array {
152
    list($code, $response) = (new GMailCURL(GMailCURL::GET))(
153
      self::API . "$user/profile",
154
      ["Authorization: Bearer $this->token"]
155
    );
156
    if ($response !== false) return $this->process_response($code, $response);
157
    return null;
158
  }
159
  /**
160
   * [watch Causes push notifications to be sent on events which occur in the
161
   * user's mailbox. Requires Google Cloud PubSub.
162
   * see https://developers.google.com/gmail/api/v1/reference/users/watch]
163
   * @param  string $topic             Topic to push events to.
164
   * @param  mixed  $labelIds          Narrow down labels in the mailbox, whose
165
   *                                   mailbox event, are being listened to.
166
   *                                   events are to be listened to.
167
   * @param  string $userId            The ID/Email address of the user.
168
   * @param  string $labelFilterAction [description]
169
   * @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...
170
   */
171
  public function watch(string $topic, $labelIds=null, string $userId='me', string $labelFilterAction='include'):?array {
172
    $body = [
173
      'topicName'         => $topic,
174
      'labelFilterAction' => $labelFilterAction
175
    ];
176
177
    if ($labelIds != null) {
178
      if (is_scalar($labelIds)) {
179
        $body['labelIds'] = [$labelIds];
180
      } elseif (is_array($labelIds)) {
181
        $body['labelIds'] = $labelIds;
182
      }
183
    }
184
185
    list($code, $response) = (new GMailCURL(GMailCURL::POST))(
186
      self::API . "$userId/watch",
187
      ["Authorization: Bearer $this->token"],
188
      $body
189
    );
190
    if ($response !== false) return $this->process_response($code, $response);
191
    return null;
192
  }
193
  /**
194
   * [endWatch stop watch operations on given email ID]
195
   * @date   2019-11-20
196
   * @param  string     $userId ID or Email Address of the user.
197
   * @return bool               [description]
198
   */
199
  public function endWatch(string $userId='me'):bool
200
  {
201
    list($code, $response) = (new GMailCURL(GMailCURL::POST))(
202
      self::API . "$userId/stop",
203
      ["Authorization: Bearer $this->token"]
204
    );
205
    if ($response !== false) return $code == 204;
206
    return false;
207
  }
208
  /**
209
   * [getLabels description]
210
   * @date   2019-11-20
211
   * @param  string     $userID [description]
212
   * @return null|array         [description]
213
   */
214
  public function getLabels(string $userId='me'):?array
215
  {
216
    list($code, $response) = (new GMailCURL(GMailCURL::GET))(
217
      self::API . "$userId/labels",
218
      ["Authorization: Bearer $this->token"]
219
    );
220
    if ($response !== false) {
221
      return json_decode($response)->labels;
222
    }
223
    return null;
224
  }
225
  /**
226
   * [getMessages description]
227
   * @date   2019-11-21
228
   * @param  string     $userId           [description]
229
   * @param  [type]     $labelIds         [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...
230
   * @param  [type]     $q                [description]
231
   * @param  [type]     $maxMessages      [description]
232
   * @param  [type]     $pageToken        [description]
233
   * @param  boolean    $includeSpamTrash [description]
234
   * @param  [type]     $truncateAfter    [description]
235
   * @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...
236
   */
237
  public function getMessages(string $userId='me', array $labelIds=null,
238
  string $q=null, int $maxMessages=null, string $pageToken=null, bool $includeSpamTrash=false,
239
  $truncateAfter=null):?object
240
  {
241
    $query = [];
242
243
    if ($labelIds != null) $query['labelIds'] = $labelIds;
244
    if ($includeSpamTrash) $query['includeSpamTrash'] = $includeSpamTrash;
245
    if ($q != null) $query['q'] = $q;
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $q of type null|string against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
246
    if ($pageToken != null) $query['pageToken'] = $pageToken;
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $pageToken of type null|string against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
247
    if ($maxMessages != null) $query['maxResults'] = $maxMessages;
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $maxMessages of type integer|null against null; this is ambiguous if the integer can be zero. Consider using a strict comparison !== instead.
Loading history...
248
249
    list($code, $response) = (new GMailCURL(GMailCURL::GET))(
250
      self::API . "$userId/messages?" . http_build_query($query),
251
      ["Authorization: Bearer $this->token"]
252
    );
253
254
    if ($response !== false) {
255
      if ($truncateAfter != null && $code == 200) {
256
        $response = json_decode($response);
257
        $response->messages = array_filter($response->messages, function ($e) use ($truncateAfter) {
258
          return strcmp($truncateAfter, $e->id) <= 0;
259
        });
260
        $response->{self::HTTP_CODE} = $code;
261
        return $response;
262
      }
263
264
      return $this->process_response($code, $response);
265
    }
266
267
    return null;
268
  }
269
  /**
270
   * [getMessage description]
271
   * @date   2019-11-21
272
   * @param  string       $userId          [description]
273
   * @param  string       $messageId       [description]
274
   * @param  string       $format          [description]
275
   * @param  [type]       $metadataHeaders [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...
276
   * @return Message|null                  [description]
277
   */
278
  public function getMessage(string $userId='me', string $messageId,
279
  string $format='full', array $metadataHeaders=null):?Message
280
  {
281
    $query = [];
282
283
    if ($format != 'full' && $format != null) $query['format'] = $format;
284
    if ($metadataHeaders != null) $query['metadataHeaders'] = $metadataHeaders;
285
286
    list($code, $response) = (new GMailCURL(GMailCURL::GET))(
287
      self::API . "$userId/messages/$messageId?" . http_build_query($query),
288
      ["Authorization: Bearer $this->token"]
289
    );
290
291
    if ($response !== false) return new Message($response);
292
293
    return null;
294
  }
295
  /**
296
   * [process_response description]
297
   * @param  int    $code   [description]
298
   * @param  string $response [description]
299
   * @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...
300
   */
301
  private function process_response(int $code, string $response) {
302
    $response = json_decode($response);
303
    $response->{self::HTTP_CODE} = $code;
304
    return $response;
305
  }
306
}
307
?>
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...
308