1<?php
2/*
3 * Copyright 2011 Google Inc.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18use GuzzleHttp\ClientInterface;
19use Symfony\Component\DomCrawler\Crawler;
20use League\Flysystem\Adapter\Local;
21use League\Flysystem\Filesystem;
22use Cache\Adapter\Filesystem\FilesystemCachePool;
23use PHPUnit\Framework\TestCase;
24
25class BaseTest extends TestCase
26{
27  private $key;
28  private $client;
29  protected $testDir = __DIR__;
30
31  public function getClient()
32  {
33    if (!$this->client) {
34      $this->client = $this->createClient();
35    }
36
37    return $this->client;
38  }
39
40  public function getCache($path = null)
41  {
42    $path = $path ?: sys_get_temp_dir().'/google-api-php-client-tests/';
43    $filesystemAdapter = new Local($path);
44    $filesystem        = new Filesystem($filesystemAdapter);
45
46    return new FilesystemCachePool($filesystem);
47  }
48
49  private function createClient()
50  {
51    $options = [
52      'auth' => 'google_auth',
53      'exceptions' => false,
54    ];
55
56    if ($proxy = getenv('HTTP_PROXY')) {
57      $options['proxy'] = $proxy;
58      $options['verify'] = false;
59    }
60
61    // adjust constructor depending on guzzle version
62    if (!$this->isGuzzle6()) {
63      $options = ['defaults' => $options];
64    }
65
66    $httpClient = new GuzzleHttp\Client($options);
67
68    $client = new Google_Client();
69    $client->setApplicationName('google-api-php-client-tests');
70    $client->setHttpClient($httpClient);
71    $client->setScopes([
72        "https://www.googleapis.com/auth/plus.me",
73        "https://www.googleapis.com/auth/urlshortener",
74        "https://www.googleapis.com/auth/tasks",
75        "https://www.googleapis.com/auth/adsense",
76        "https://www.googleapis.com/auth/youtube",
77        "https://www.googleapis.com/auth/drive",
78    ]);
79
80    if ($this->key) {
81      $client->setDeveloperKey($this->key);
82    }
83
84    list($clientId, $clientSecret) = $this->getClientIdAndSecret();
85    $client->setClientId($clientId);
86    $client->setClientSecret($clientSecret);
87    if (version_compare(PHP_VERSION, '5.5', '>=')) {
88      $client->setCache($this->getCache());
89    }
90
91    return $client;
92  }
93
94  public function checkToken()
95  {
96    $client = $this->getClient();
97    $cache = $client->getCache();
98    $cacheItem = $cache->getItem('access_token');
99
100    if (!$token = $cacheItem->get()) {
101      if (!$token = $this->tryToGetAnAccessToken($client)) {
102        return $this->markTestSkipped("Test requires access token");
103      }
104      $cacheItem->set($token);
105      $cache->save($cacheItem);
106    }
107
108    $client->setAccessToken($token);
109
110    if ($client->isAccessTokenExpired()) {
111      // as long as we have client credentials, even if its expired
112      // our access token will automatically be refreshed
113      $this->checkClientCredentials();
114    }
115
116    return true;
117  }
118
119  public function tryToGetAnAccessToken(Google_Client $client)
120  {
121    $this->checkClientCredentials();
122
123    $client->setRedirectUri("urn:ietf:wg:oauth:2.0:oob");
124    $client->setConfig('access_type', 'offline');
125    $authUrl = $client->createAuthUrl();
126
127    echo "\nPlease enter the auth code:\n";
128    ob_flush();
129    `open '$authUrl'`;
130    $authCode = trim(fgets(STDIN));
131
132    if ($accessToken = $client->fetchAccessTokenWithAuthCode($authCode)) {
133      if (isset($accessToken['access_token'])) {
134        return $accessToken;
135      }
136    }
137
138    return false;
139  }
140
141  private function getClientIdAndSecret()
142  {
143    $clientId = getenv('GCLOUD_CLIENT_ID') ?: null;
144    $clientSecret = getenv('GCLOUD_CLIENT_SECRET') ?: null;
145
146    return array($clientId, $clientSecret);
147  }
148
149  public function checkClientCredentials()
150  {
151    list($clientId, $clientSecret) = $this->getClientIdAndSecret();
152    if (!($clientId && $clientSecret)) {
153      $this->markTestSkipped("Test requires GCLOUD_CLIENT_ID and GCLOUD_CLIENT_SECRET to be set");
154    }
155  }
156
157  public function checkServiceAccountCredentials()
158  {
159    if (!$f = getenv('GOOGLE_APPLICATION_CREDENTIALS')) {
160      $skip = "This test requires the GOOGLE_APPLICATION_CREDENTIALS environment variable to be set\n"
161        . "see https://developers.google.com/accounts/docs/application-default-credentials";
162      $this->markTestSkipped($skip);
163
164      return false;
165    }
166
167    if (!file_exists($f)) {
168      $this->markTestSkipped('invalid path for GOOGLE_APPLICATION_CREDENTIALS');
169    }
170
171    return true;
172  }
173
174  public function checkKey()
175  {
176    $this->key = $this->loadKey();
177
178    if (!strlen($this->key)) {
179      $this->markTestSkipped("Test requires api key\nYou can create one in your developer console");
180      return false;
181    }
182  }
183
184  public function loadKey()
185  {
186    if (file_exists($f = __DIR__ . DIRECTORY_SEPARATOR . '.apiKey')) {
187      return file_get_contents($f);
188    }
189  }
190
191  protected function loadExample($example)
192  {
193    // trick app into thinking we are a web server
194    $_SERVER['HTTP_USER_AGENT'] = 'google-api-php-client-tests';
195    $_SERVER['HTTP_HOST'] = 'localhost';
196    $_SERVER['REQUEST_METHOD'] = 'GET';
197
198    // include the file and return an HTML crawler
199    $file = __DIR__ . '/../examples/' . $example;
200    if (is_file($file)) {
201        ob_start();
202        include $file;
203        $html = ob_get_clean();
204
205        return new Crawler($html);
206    }
207
208    return false;
209  }
210
211  protected function isGuzzle6()
212  {
213    $version = ClientInterface::VERSION;
214
215    return ('6' === $version[0]);
216  }
217
218  protected function isGuzzle5()
219  {
220    $version = ClientInterface::VERSION;
221
222    return ('5' === $version[0]);
223  }
224
225  public function onlyGuzzle6()
226  {
227    if (!$this->isGuzzle6()) {
228      $this->markTestSkipped('Guzzle 6 only');
229    }
230  }
231
232  public function onlyPhp55AndAbove()
233  {
234    if (version_compare(PHP_VERSION, '5.5', '<')) {
235      $this->markTestSkipped('PHP 5.5 and above only');
236    }
237  }
238
239  public function onlyGuzzle5()
240  {
241    if (!$this->isGuzzle5()) {
242      $this->markTestSkipped('Guzzle 5 only');
243    }
244  }
245}
246