Issues (994)

src/GoogleExt/client.php (13 issues)

1
<?php
2
3
namespace GoogleExt;
4
5
use Filemanager\file;
6
//use Google_Client;
7
use Google\Client as Google_Client;
8
9
class client extends Google_Client
10
{
11
  /**
12
   * Google Client Instances.
13
   *
14
   * @var \Google_Client
15
   */
16
  private $Client;
0 ignored issues
show
The private property $Client is not used, and could be removed.
Loading history...
17
  /**
18
   * Filemanager instance.
19
   *
20
   * @var \Filemanager\file
21
   */
22
  private $filemanager;
23
  private $token_folder;
24
  private $configuration;
25
  public $application_name = "Google Client Library";
26
27
  public function __construct(array $config = ['token' => ['folder' => __DIR__ . '/token']])
28
  {
29
    parent::__construct($config);
30
    $this->filemanager = new \Filemanager\file();
31
    if (isset($config['token']['folder'])) {
32
      $token_folder = $config['token']['folder'];
33
      $this->token_folder = $token_folder;
34
      file::folder($token_folder, null, null, true);
0 ignored issues
show
The call to Filemanager\file::folder() has too many arguments starting with null. ( Ignorable by Annotation )

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

34
      file::/** @scrutinizer ignore-call */ 
35
            folder($token_folder, null, null, true);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
35
      file::file($token_folder . '/.htaccess', 'deny from all');
0 ignored issues
show
'deny from all' of type string is incompatible with the type boolean expected by parameter $create of Filemanager\file::file(). ( Ignorable by Annotation )

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

35
      file::file($token_folder . '/.htaccess', /** @scrutinizer ignore-type */ 'deny from all');
Loading history...
36
      file::file($token_folder . '/.gitignore', "*\n!.gitignore\n!.htaccess");
37
    }
38
    $this->configuration = $config;
39
  }
40
41
  public static function get_profile()
42
  {
43
    if (isset($_SESSION['google']['login'])) {
44
      return $_SESSION['google']['login'];
45
    }
46
    return [];
47
  }
48
49
  public static function get_profile_picture()
50
  {
51
    if (!empty(self::get_profile())) {
52
      if (isset(self::get_profile()['picture'])) return self::get_profile()['picture'];
53
    }
54
    return 'https://upload.wikimedia.org/wikipedia/commons/thumb/a/ac/No_image_available.svg/480px-No_image_available.svg.png';
55
  }
56
57
  public static function get_profile_name()
58
  {
59
    if (!empty(self::get_profile())) {
60
      if (isset(self::get_profile()['name'])) return self::get_profile()['name'];
61
    }
62
    return 'Login Required';
63
  }
64
65
  /**
66
   * @param string $redirect /auth/google
67
   */
68
  public function create_auth_url($scope, $redirect)
69
  {
70
    $this->custom_client($scope, $redirect);
71
    return $this->createAuthUrl();
72
  }
73
74
  /**
75
   * @return \GoogleExt\Client
76
   */
77
  public function custom_client($scope, $redirect)
78
  {
79
    $this->setApplicationName($this->application_name);
80
    $this->setCredentials(
81
      CONFIG['google']['client'],
82
      CONFIG['google']['secret'],
83
      CONFIG['google']['key']
84
    );
85
    $scopes = [
86
      'https://www.googleapis.com/auth/userinfo.email',
87
      'https://www.googleapis.com/auth/userinfo.profile'
88
    ];
89
    if (is_string($scope)) {
90
      switch ($scope) {
91
        case 'blogger':
92
          $scopes[] = 'https://www.googleapis.com/auth/blogger';
93
          break;
94
      }
95
    }
96
    $this->set_scope(array_unique($scopes));
97
    $this->set_offline(true);
98
    $this->setRedirectUri($this->getOrigin($redirect));
99
    //$this->auto_login($redirect);
100
    return $this;
101
  }
102
103
  /**
104
   * Check user google is login.
105
   *
106
   * @return bool
107
   */
108
  public function is_login()
109
  {
110
    return isset($_SESSION['google']['login']) && !empty($_SESSION['google']['login']) && isset($_SESSION['google']['login']['email']);
111
  }
112
113
  /**
114
   * Revoke token.
115
   *
116
   * @return $this
117
   */
118
  public function revoke()
119
  {
120
    $this->revokeToken();
121
122
    $this;
123
  }
124
125
  /**
126
   * Get current origin url.
127
   *
128
   * @return string
129
   */
130
  public function getOrigin(string $path = null)
131
  {
132
    return (isset($_SERVER['HTTPS']) && 'on' === $_SERVER['HTTPS'] ? 'https' : 'http') . "://$_SERVER[HTTP_HOST]$path";
133
  }
134
135
  public function get_token_folder()
136
  {
137
    return $this->token_folder;
138
  }
139
140
  public function set_token_folder(string $path)
141
  {
142
    if ($path = realpath($path)) {
143
      $this->token_folder = $path;
144
    }
145
146
    return $this;
147
  }
148
149
  public function set_scope($scopes)
150
  {
151
    if (is_string($scopes)) {
152
      if ($this->is_url($scopes)) {
153
        $this->addScope($scopes);
154
      } else {
155
        throw new \MVC\Exception('Scope is URL format', 1);
156
157
        return null;
0 ignored issues
show
return null is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
158
      }
159
    } elseif (is_array($scopes)) {
160
      $this->setScopes($scopes);
161
    }
162
163
    return $this;
164
  }
165
166
  /**
167
   * Set access token offline.
168
   *
169
   * @param bool $offline
170
   *
171
   * @return client
172
   */
173
  public function set_offline($offline = true)
174
  {
175
    if ($offline) {
176
      $this->setAccessType('offline');
177
      $this->setApprovalPrompt('force');
178
    } else {
179
      $this->setApprovalPrompt('auto');
180
    }
181
182
    return $this;
183
  }
184
185
  /**
186
   * Set default credentials.
187
   *
188
   * @return client
189
   */
190
  public function setCredentials(string $client, string $secret, string $key)
191
  {
192
    $this->setApplicationName('Login to ' . $_SERVER['HTTP_HOST']);
193
    $this->setDeveloperKey($key);
194
    $this->setClientId($client);
195
    $this->setClientSecret($secret);
196
    $this->addScope('https://www.googleapis.com/auth/userinfo.email');
197
    $this->addScope('https://www.googleapis.com/auth/userinfo.profile');
198
199
    return $this;
200
  }
201
202
  /**
203
   * Check if current instance is valid.
204
   *
205
   * @return bool
206
   */
207
  public function isValid()
208
  {
209
    return $this->getAccessToken() && !$this->isAccessTokenExpired();
210
  }
211
212
  public function is_url($string)
213
  {
214
    return filter_var($string, FILTER_VALIDATE_URL);
215
  }
216
217
  /**
218
   * Check user has subscribed to youtube channel.
219
   *
220
   * @param string $cid          channel id
221
   * @param bool   $only_get_url = return URL channel
222
   */
223
  public function check_subscriber(string $cid = 'UCGNaoefvJRfd15fo-LQ0zvg', bool $only_get_url = false)
224
  {
225
    if (!$only_get_url) {
226
      /**
227
       * @var \Google\Client
228
       */
229
      $client = $this;
230
      $service = new \Google_Service_YouTube($client);
0 ignored issues
show
$client of type GoogleExt\client is incompatible with the type Google_Client expected by parameter $client of Google_Service_YouTube::__construct(). ( Ignorable by Annotation )

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

230
      $service = new \Google_Service_YouTube(/** @scrutinizer ignore-type */ $client);
Loading history...
231
      $response = $service->subscriptions->listSubscriptions(
232
        'snippet,contentDetails',
233
        array_filter(['forChannelId' => $cid, 'mine' => true])
234
      );
235
236
      $result = count($response['items']);
0 ignored issues
show
It seems like $response['items'] can also be of type null; however, parameter $value of count() does only seem to accept Countable|array, 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

236
      $result = count(/** @scrutinizer ignore-type */ $response['items']);
Loading history...
237
      $output = [];
238
      if ($result > 0) {
239
        $output['success'] = true;
240
        $output['data'] = $response['items'];
241
        $_SESSION['subscribed'] = 1;
242
      } else {
243
        $output['error'] = true;
244
        $output['data'] = 'Belum Subscribe';
245
        $output['msg'] = 'Belum Subscribe';
246
        $_SESSION['subscribed'] = 0;
247
      }
248
    } else {
249
      $output = 'https://www.youtube.com/channel/' . $cid;
250
    }
251
252
    return $output;
253
  }
254
255
  /**
256
   * Auto get token from $_GET['code']
257
   * And auto refresh token
258
   * * @param string $redirect /auth/google
259
   */
260
  public function auto_login($redirect)
261
  {
262
    $config = $this->configuration;
263
    $this->setCredentials(
264
      CONFIG['google']['client'],
265
      CONFIG['google']['secret'],
266
      CONFIG['google']['key']
267
    );
268
    $this->setRedirectUri($this->getOrigin($redirect));
269
    // authenticating
270
    if (isset($_GET['code'])) {
271
      $token = $this->fetchAccessTokenWithAuthCode($_GET['code']);
272
      /*$this->authenticate($_GET['code']);
273
      $access_token = $this->getAccessToken();
274
      e($access_token, $token);*/
275
      if (!empty($token)) {
276
        if (isset($token['error'])) {
277
          e($token);
278
        }
279
        $this->setAccessToken($token);
280
      }
281
      if (isset($config['token']['folder']) && $this->getAccessToken()) {
282
        $user = $this->fetch_user();
283
        $_SESSION['google']['login'] = $user;
284
        file::file($config['token']['folder'] . '/' . $user['email'] . '.json', $token, true);
285
      }
286
    }
287
288
    $tokenpath = null;
289
    if (isset($_SESSION['google']['login'])) {
290
      $user = $_SESSION['google']['login'];
291
      $tokenpath = $config['token']['folder'] . '/' . $user['email'] . '.json';
292
      if (isset($user['email'])) {
293
        $email = $user['email'];
0 ignored issues
show
The assignment to $email is dead and can be removed.
Loading history...
294
      }
295
      // auto refresh token
296
      if ($this->isAccessTokenExpired() && isset($user['email']) && $this->getAccessToken()) {
297
        $this->fetchAccessTokenWithRefreshToken($this->getRefreshToken());
298
        file::file($tokenpath, json_encode($this->getAccessToken()), true);
0 ignored issues
show
json_encode($this->getAccessToken()) of type string is incompatible with the type boolean expected by parameter $create of Filemanager\file::file(). ( Ignorable by Annotation )

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

298
        file::file($tokenpath, /** @scrutinizer ignore-type */ json_encode($this->getAccessToken()), true);
Loading history...
299
      }
300
    } else if (isset($this->login_data()['email'])) {
301
      $email = $this->login_data()['email'];
302
      $tokenpath = $config['token']['folder'] . '/' . $email . '.json';
303
    }
304
305
    if (file_exists($tokenpath)) {
0 ignored issues
show
It seems like $tokenpath can also be of type null; however, parameter $filename of file_exists() 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

305
    if (file_exists(/** @scrutinizer ignore-type */ $tokenpath)) {
Loading history...
306
      $token = json_decode(file_get_contents($tokenpath), true);
0 ignored issues
show
It seems like $tokenpath can also be of type null; however, parameter $filename of file_get_contents() 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

306
      $token = json_decode(file_get_contents(/** @scrutinizer ignore-type */ $tokenpath), true);
Loading history...
307
      $this->setAccessToken($token);
308
    }
309
  }
310
311
  /**
312
   * Get current user login ($_SESSION['login']).
313
   *
314
   * @return array
315
   */
316
  public function login_data()
317
  {
318
    return isset($_SESSION['login']) ? \ArrayHelper\helper::unset($_SESSION['login'], ['password']) : [];
319
  }
320
321
  /**
322
   * Get current google user data.
323
   *
324
   * @return void
325
   */
326
  public function userdata()
327
  {
328
    return isset($_SESSION['google']['login']) ? \ArrayHelper\helper::unset($_SESSION['google']['login'], ['password']) : [];
0 ignored issues
show
Bug Best Practice introduced by
The expression return IssetNode ? Array...('password')) : array() also could return the type array which is incompatible with the documented return type void.
Loading history...
329
  }
330
331
  /**
332
   * Fetch user information from google.
333
   *
334
   * @return array
335
   */
336
  public function fetch_user()
337
  {
338
    /**
339
     * @var \Google\Client
340
     */
341
    $client = $this;
342
    $service = new \Google_Service_Oauth2($client);
0 ignored issues
show
$client of type GoogleExt\client is incompatible with the type Google_Client expected by parameter $client of Google_Service_Oauth2::__construct(). ( Ignorable by Annotation )

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

342
    $service = new \Google_Service_Oauth2(/** @scrutinizer ignore-type */ $client);
Loading history...
343
    $this->addScope(\Google_Service_Oauth2::USERINFO_EMAIL);
344
    $this->addScope(\Google_Service_Oauth2::USERINFO_PROFILE);
345
    $this->authenticate($_GET['code']);
0 ignored issues
show
Deprecated Code introduced by
The function Google\Client::authenticate() has been deprecated. ( Ignorable by Annotation )

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

345
    /** @scrutinizer ignore-deprecated */ $this->authenticate($_GET['code']);
Loading history...
346
347
    return (array) $service->userinfo->get();
348
  }
349
}
350