├── views
└── example_view.php
├── README.md
├── config
└── gapi.php
├── controllers
└── Example.php
└── libraries
└── Gapi.php
/views/example_view.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Codeigniter Google Analytics API
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Google Analytics API with Codeigniter #
2 |
3 | Works with [gapi-google-analytics-php-interface](https://github.com/erebusnz/gapi-google-analytics-php-interface)
4 |
5 | **config/gapi.php**
6 |
7 | ```
8 | $config['account_email'] = '847834925186-siheminq2k5rk84a03enev9jin2m3aq6@developer.gserviceaccount.com';
9 | ```
10 |
11 | This is the email address of your Google Project's service account.
12 |
13 | ```
14 | $config['p12_key'] = 'assets/admin/Analytics-ef0175d30222.p12';
15 | ```
16 |
17 | This is the .p12 key file's location.
18 |
19 | ```
20 | $config['ga_profile_id'] = '54982801';
21 | ```
22 |
23 | Profile ID of your website on Google Anaytics.
24 |
25 | For Turkish documentation [Click Here!](http://www.turankaratug.com/blog/php/3-codeigniter-ile-google-analytics-verilerini-cekmek)
--------------------------------------------------------------------------------
/config/gapi.php:
--------------------------------------------------------------------------------
1 | load->config('gapi');
14 | $params = [ 'client_email' => $this->config->item('account_email'), 'key_file' => $this->config->item('p12_key') ];
15 | $this->load->library('gapi', $params);
16 |
17 | $this->gapi->requestReportData($this->config->item('ga_profile_id'), array('day'), array('sessions','users','pageviews','organicSearches','bounceRate'), 'day', '', date('Y-m-01'), date('Y-m-d'), 1, 500);
18 | $data['totalSessions'] = $this->gapi->getSessions();
19 | $data['totalUsers'] = $this->gapi->getUsers();
20 | $data['totalPageViews'] = $this->gapi->getPageviews();
21 | $data['totalOrganik'] = $this->gapi->getOrganicSearches();
22 | $data['totalBounce'] = $this->gapi->getBounceRate();
23 |
24 | $this->load->view('exampla_view',$data);
25 | }
26 |
27 | }
--------------------------------------------------------------------------------
/libraries/Gapi.php:
--------------------------------------------------------------------------------
1 | .
22 | *
23 | * @author Stig Manning
24 | * @author Joel Kitching
25 | * @author Cliff Gordon
26 | * @version 2.0
27 | *
28 | */
29 |
30 | class gapi {
31 | const account_data_url = 'https://www.googleapis.com/analytics/v3/management/accountSummaries';
32 | const report_data_url = 'https://www.googleapis.com/analytics/v3/data/ga';
33 | const interface_name = 'GAPI-2.0';
34 | const dev_mode = false;
35 |
36 | private $auth_method = null;
37 | private $account_entries = array();
38 | private $report_aggregate_metrics = array();
39 | private $report_root_parameters = array();
40 | private $results = array();
41 |
42 | private $client_email = null;
43 | private $key_file = null;
44 |
45 | /**
46 | * Constructor function for new gapi instances
47 | *
48 | * @param string $client_email Email of OAuth2 service account (XXXXX@developer.gserviceaccount.com)
49 | * @param string $key_file Location/filename of .p12 key file
50 | * @param string $delegate_email Optional email of account to impersonate
51 | * @return gapi
52 | */
53 | public function __construct($login_params = array(), $delegate_email = null) {
54 | if (version_compare(PHP_VERSION, '5.3.0') < 0) {
55 | throw new Exception('GAPI: PHP version ' . PHP_VERSION . ' is below minimum required 5.3.0.');
56 | }
57 | $this->client_email = $login_params['client_email'];
58 | $this->key_file = $login_params['key_file'];
59 | $this->auth_method = new gapiOAuth2();
60 | $this->auth_method->fetchToken($this->client_email, $this->key_file, $delegate_email);
61 | }
62 |
63 | /**
64 | * Return the auth token string retrieved by Google
65 | *
66 | * @return String
67 | */
68 | public function getToken() {
69 | return $this->auth_method->getToken();
70 | }
71 |
72 | /**
73 | * Return the auth token information from the Google service
74 | *
75 | * @return Array
76 | */
77 | public function getTokenInfo() {
78 | return $this->auth_method->getTokenInfo();
79 | }
80 |
81 | /**
82 | * Revoke the current auth token, rendering it invalid for future requests
83 | *
84 | * @return Boolean
85 | */
86 | public function revokeToken() {
87 | return $this->auth_method->revokeToken();
88 | }
89 |
90 | /**
91 | * Request account data from Google Analytics
92 | *
93 | * @param Int $start_index OPTIONAL: Start index of results
94 | * @param Int $max_results OPTIONAL: Max results returned
95 | */
96 | public function requestAccountData($start_index=1, $max_results=1000) {
97 | $get_variables = array(
98 | 'start-index' => $start_index,
99 | 'max-results' => $max_results,
100 | );
101 | $url = new gapiRequest(gapi::account_data_url);
102 | $response = $url->get($get_variables, $this->auth_method->generateAuthHeader());
103 |
104 | if (substr($response['code'], 0, 1) == '2') {
105 | return $this->accountObjectMapper($response['body']);
106 | } else {
107 | throw new Exception('GAPI: Failed to request account data. Error: "' . strip_tags($response['body']) . '"');
108 | }
109 | }
110 |
111 | /**
112 | * Request report data from Google Analytics
113 | *
114 | * $report_id is the Google report ID for the selected account
115 | *
116 | * $parameters should be in key => value format
117 | *
118 | * @param String $report_id
119 | * @param Array $dimensions Google Analytics dimensions e.g. array('browser')
120 | * @param Array $metrics Google Analytics metrics e.g. array('pageviews')
121 | * @param Array $sort_metric OPTIONAL: Dimension or dimensions to sort by e.g.('-visits')
122 | * @param String $filter OPTIONAL: Filter logic for filtering results
123 | * @param String $start_date OPTIONAL: Start of reporting period
124 | * @param String $end_date OPTIONAL: End of reporting period
125 | * @param Int $start_index OPTIONAL: Start index of results
126 | * @param Int $max_results OPTIONAL: Max results returned
127 | */
128 | public function requestReportData($report_id, $dimensions=null, $metrics, $sort_metric=null, $filter=null, $start_date=null, $end_date=null, $start_index=1, $max_results=10000) {
129 | $parameters = array('ids'=>'ga:' . $report_id);
130 |
131 | if (is_array($dimensions)) {
132 | $dimensions_string = '';
133 | foreach ($dimensions as $dimesion) {
134 | $dimensions_string .= ',ga:' . $dimesion;
135 | }
136 | $parameters['dimensions'] = substr($dimensions_string, 1);
137 | } elseif ($dimensions !== null) {
138 | $parameters['dimensions'] = 'ga:'.$dimensions;
139 | }
140 |
141 | if (is_array($metrics)) {
142 | $metrics_string = '';
143 | foreach ($metrics as $metric) {
144 | $metrics_string .= ',ga:' . $metric;
145 | }
146 | $parameters['metrics'] = substr($metrics_string, 1);
147 | } else {
148 | $parameters['metrics'] = 'ga:'.$metrics;
149 | }
150 |
151 | if ($sort_metric==null&&isset($parameters['metrics'])) {
152 | $parameters['sort'] = $parameters['metrics'];
153 | } elseif (is_array($sort_metric)) {
154 | $sort_metric_string = '';
155 |
156 | foreach ($sort_metric as $sort_metric_value) {
157 | //Reverse sort - Thanks Nick Sullivan
158 | if (substr($sort_metric_value, 0, 1) == "-") {
159 | $sort_metric_string .= ',-ga:' . substr($sort_metric_value, 1); // Descending
160 | }
161 | else {
162 | $sort_metric_string .= ',ga:' . $sort_metric_value; // Ascending
163 | }
164 | }
165 |
166 | $parameters['sort'] = substr($sort_metric_string, 1);
167 | } else {
168 | if (substr($sort_metric, 0, 1) == "-") {
169 | $parameters['sort'] = '-ga:' . substr($sort_metric, 1);
170 | } else {
171 | $parameters['sort'] = 'ga:' . $sort_metric;
172 | }
173 | }
174 |
175 | if ($filter!=null) {
176 | $filter = $this->processFilter($filter);
177 | if ($filter!==false) {
178 | $parameters['filters'] = $filter;
179 | }
180 | }
181 |
182 | if ($start_date==null) {
183 | // Use the day that Google Analytics was released (1 Jan 2005).
184 | $start_date = '2005-01-01';
185 | } elseif (is_int($start_date)) {
186 | // Perhaps we are receiving a Unix timestamp.
187 | $start_date = date('Y-m-d', $start_date);
188 | }
189 |
190 | $parameters['start-date'] = $start_date;
191 |
192 | if ($end_date==null) {
193 | $end_date = date('Y-m-d');
194 | } elseif (is_int($end_date)) {
195 | // Perhaps we are receiving a Unix timestamp.
196 | $end_date = date('Y-m-d', $end_date);
197 | }
198 |
199 | $parameters['end-date'] = $end_date;
200 |
201 |
202 | $parameters['start-index'] = $start_index;
203 | $parameters['max-results'] = $max_results;
204 |
205 | $parameters['prettyprint'] = gapi::dev_mode ? 'true' : 'false';
206 |
207 | $url = new gapiRequest(gapi::report_data_url);
208 | $response = $url->get($parameters, $this->auth_method->generateAuthHeader());
209 |
210 | //HTTP 2xx
211 | if (substr($response['code'], 0, 1) == '2') {
212 | return $this->reportObjectMapper($response['body']);
213 | } else {
214 | throw new Exception('GAPI: Failed to request report data. Error: "' . $this->cleanErrorResponse($response['body']) . '"');
215 | }
216 | }
217 |
218 | /**
219 | * Clean error message from Google API
220 | *
221 | * @param String $error Error message HTML or JSON from Google API
222 | */
223 | private function cleanErrorResponse($error) {
224 | if (strpos($error, ']*>[^<]*<\/(style|title|script)>/i', '', $error);
226 | return trim(preg_replace('/\s+/', ' ', strip_tags($error)));
227 | }
228 | else
229 | {
230 | $json = json_decode($error);
231 | return isset($json->error->message) ? strval($json->error->message) : $error;
232 | }
233 | }
234 |
235 | /**
236 | * Process filter string, clean parameters and convert to Google Analytics
237 | * compatible format
238 | *
239 | * @param String $filter
240 | * @return String Compatible filter string
241 | */
242 | protected function processFilter($filter) {
243 | $valid_operators = '(!~|=~|==|!=|>|<|>=|<=|=@|!@)';
244 |
245 | $filter = preg_replace('/\s\s+/', ' ', trim($filter)); //Clean duplicate whitespace
246 | $filter = str_replace(array(',', ';'), array('\,', '\;'), $filter); //Escape Google Analytics reserved characters
247 | $filter = preg_replace('/(&&\s*|\|\|\s*|^)([a-z0-9]+)(\s*' . $valid_operators . ')/i','$1ga:$2$3',$filter); //Prefix ga: to metrics and dimensions
248 | $filter = preg_replace('/[\'\"]/i', '', $filter); //Clear invalid quote characters
249 | $filter = preg_replace(array('/\s*&&\s*/','/\s*\|\|\s*/','/\s*' . $valid_operators . '\s*/'), array(';', ',', '$1'), $filter); //Clean up operators
250 |
251 | if (strlen($filter) > 0) {
252 | return urlencode($filter);
253 | }
254 | else {
255 | return false;
256 | }
257 | }
258 |
259 | /**
260 | * Report Account Mapper to convert the JSON to array of useful PHP objects
261 | *
262 | * @param String $json_string
263 | * @return Array of gapiAccountEntry objects
264 | */
265 | protected function accountObjectMapper($json_string) {
266 | $json = json_decode($json_string, true);
267 | $results = array();
268 |
269 | foreach ($json['items'] as $item) {
270 | foreach ($item['webProperties'] as $property) {
271 | if (isset($property['profiles'][0]['id'])) {
272 | $property['ProfileId'] = $property['profiles'][0]['id'];
273 | }
274 | $results[] = new gapiAccountEntry($property);
275 | }
276 | }
277 |
278 | $this->account_entries = $results;
279 |
280 | return $results;
281 | }
282 |
283 | /**
284 | * Report Object Mapper to convert the JSON to array of useful PHP objects
285 | *
286 | * @param String $json_string
287 | * @return Array of gapiReportEntry objects
288 | */
289 | protected function reportObjectMapper($json_string) {
290 | $json = json_decode($json_string, true);
291 |
292 | $this->results = null;
293 | $results = array();
294 |
295 | $report_aggregate_metrics = array();
296 |
297 | //Load root parameters
298 |
299 | // Start with elements from the root level of the JSON that aren't themselves arrays.
300 | $report_root_parameters = array_filter($json, function($var){
301 | return !is_array($var);
302 | });
303 |
304 | // Get the items from the 'query' object, and rename them slightly.
305 | foreach($json['query'] as $index => $value) {
306 | $new_index = lcfirst(str_replace(' ', '', ucwords(str_replace('-', ' ', $index))));
307 | $report_root_parameters[$new_index] = $value;
308 | }
309 |
310 | // Now merge in the profileInfo, as this is also mostly useful.
311 | array_merge($report_root_parameters, $json['profileInfo']);
312 |
313 | //Load result aggregate metrics
314 |
315 | foreach($json['totalsForAllResults'] as $index => $metric_value) {
316 | //Check for float, or value with scientific notation
317 | if (preg_match('/^(\d+\.\d+)|(\d+E\d+)|(\d+.\d+E\d+)$/', $metric_value)) {
318 | $report_aggregate_metrics[str_replace('ga:', '', $index)] = floatval($metric_value);
319 | } else {
320 | $report_aggregate_metrics[str_replace('ga:', '', $index)] = intval($metric_value);
321 | }
322 | }
323 |
324 | //Load result entries
325 | if(isset($json['rows'])){
326 | foreach($json['rows'] as $row) {
327 | $metrics = array();
328 | $dimensions = array();
329 | foreach($json['columnHeaders'] as $index => $header) {
330 | switch($header['columnType']) {
331 | case 'METRIC':
332 | $metric_value = $row[$index];
333 |
334 | //Check for float, or value with scientific notation
335 | if(preg_match('/^(\d+\.\d+)|(\d+E\d+)|(\d+.\d+E\d+)$/',$metric_value)) {
336 | $metrics[str_replace('ga:', '', $header['name'])] = floatval($metric_value);
337 | } else {
338 | $metrics[str_replace('ga:', '', $header['name'])] = intval($metric_value);
339 | }
340 | break;
341 | case 'DIMENSION':
342 | $dimensions[str_replace('ga:', '', $header['name'])] = strval($row[$index]);
343 | break;
344 | default:
345 | throw new Exception("GAPI: Unrecognized columnType '{$header['columnType']}' for columnHeader '{$header['name']}'");
346 | }
347 | }
348 | $results[] = new gapiReportEntry($metrics, $dimensions);
349 | }
350 | }
351 |
352 | $this->report_root_parameters = $report_root_parameters;
353 | $this->report_aggregate_metrics = $report_aggregate_metrics;
354 | $this->results = $results;
355 |
356 | return $results;
357 | }
358 |
359 | /**
360 | * Get current analytics results
361 | *
362 | * @return Array
363 | */
364 | public function getResults() {
365 | return is_array($this->results) ? $this->results : false;
366 | }
367 |
368 | /**
369 | * Get current account data
370 | *
371 | * @return Array
372 | */
373 | public function getAccounts() {
374 | return is_array($this->account_entries) ? $this->account_entries : false;
375 | }
376 |
377 | /**
378 | * Get an array of the metrics and the matching
379 | * aggregate values for the current result
380 | *
381 | * @return Array
382 | */
383 | public function getMetrics() {
384 | return $this->report_aggregate_metrics;
385 | }
386 |
387 | /**
388 | * Call method to find a matching root parameter or
389 | * aggregate metric to return
390 | *
391 | * @param $name String name of function called
392 | * @return String
393 | * @throws Exception if not a valid parameter or aggregate
394 | * metric, or not a 'get' function
395 | */
396 | public function __call($name, $parameters) {
397 | if (!preg_match('/^get/', $name)) {
398 | throw new Exception('No such function "' . $name . '"');
399 | }
400 |
401 | $name = preg_replace('/^get/', '', $name);
402 |
403 | $parameter_key = gapi::ArrayKeyExists($name, $this->report_root_parameters);
404 |
405 | if ($parameter_key) {
406 | return $this->report_root_parameters[$parameter_key];
407 | }
408 |
409 | $aggregate_metric_key = gapi::ArrayKeyExists($name, $this->report_aggregate_metrics);
410 |
411 | if ($aggregate_metric_key) {
412 | return $this->report_aggregate_metrics[$aggregate_metric_key];
413 | }
414 |
415 | throw new Exception('No valid root parameter or aggregate metric called "' . $name . '"');
416 | }
417 |
418 | /**
419 | * Case insensitive array_key_exists function, also returns
420 | * matching key.
421 | *
422 | * @param String $key
423 | * @param Array $search
424 | * @return String Matching array key
425 | */
426 | public static function ArrayKeyExists($key, $search) {
427 | if (array_key_exists($key, $search)) {
428 | return $key;
429 | }
430 | if (!(is_string($key) && is_array($search))) {
431 | return false;
432 | }
433 | $key = strtolower($key);
434 | foreach ($search as $k => $v) {
435 | if (strtolower($k) == $key) {
436 | return $k;
437 | }
438 | }
439 | return false;
440 | }
441 | }
442 |
443 | /**
444 | * Storage for individual gapi account entries
445 | *
446 | */
447 | class gapiAccountEntry {
448 | private $properties = array();
449 |
450 | /**
451 | * Constructor function for all new gapiAccountEntry instances
452 | *
453 | * @param Array $properties
454 | * @return gapiAccountEntry
455 | */
456 | public function __construct($properties) {
457 | $this->properties = $properties;
458 | }
459 |
460 | /**
461 | * toString function to return the name of the account
462 | *
463 | * @return String
464 | */
465 | public function __toString() {
466 | return isset($this->properties['name']) ?
467 | $this->properties['name']: '';
468 | }
469 |
470 | /**
471 | * Get an associative array of the properties
472 | * and the matching values for the current result
473 | *
474 | * @return Array
475 | */
476 | public function getProperties() {
477 | return $this->properties;
478 | }
479 |
480 | /**
481 | * Call method to find a matching parameter to return
482 | *
483 | * @param $name String name of function called
484 | * @return String
485 | * @throws Exception if not a valid parameter, or not a 'get' function
486 | */
487 | public function __call($name, $parameters) {
488 | if (!preg_match('/^get/', $name)) {
489 | throw new Exception('No such function "' . $name . '"');
490 | }
491 |
492 | $name = preg_replace('/^get/', '', $name);
493 |
494 | $property_key = gapi::ArrayKeyExists($name, $this->properties);
495 |
496 | if ($property_key) {
497 | return $this->properties[$property_key];
498 | }
499 |
500 | throw new Exception('No valid property called "' . $name . '"');
501 | }
502 | }
503 |
504 | /**
505 | * Storage for individual gapi report entries
506 | *
507 | */
508 | class gapiReportEntry {
509 | private $metrics = array();
510 | private $dimensions = array();
511 |
512 | /**
513 | * Constructor function for all new gapiReportEntry instances
514 | *
515 | * @param Array $metrics
516 | * @param Array $dimensions
517 | * @return gapiReportEntry
518 | */
519 | public function __construct($metrics, $dimensions) {
520 | $this->metrics = $metrics;
521 | $this->dimensions = $dimensions;
522 | }
523 |
524 | /**
525 | * toString function to return the name of the result
526 | * this is a concatented string of the dimensions chosen
527 | *
528 | * For example:
529 | * 'Firefox 3.0.10' from browser and browserVersion
530 | *
531 | * @return String
532 | */
533 | public function __toString() {
534 | return is_array($this->dimensions) ?
535 | implode(' ', $this->dimensions) : '';
536 | }
537 |
538 | /**
539 | * Get an associative array of the dimensions
540 | * and the matching values for the current result
541 | *
542 | * @return Array
543 | */
544 | public function getDimensions() {
545 | return $this->dimensions;
546 | }
547 |
548 | /**
549 | * Get an array of the metrics and the matchning
550 | * values for the current result
551 | *
552 | * @return Array
553 | */
554 | public function getMetrics() {
555 | return $this->metrics;
556 | }
557 |
558 | /**
559 | * Call method to find a matching metric or dimension to return
560 | *
561 | * @param String $name name of function called
562 | * @param Array $parameters
563 | * @return String
564 | * @throws Exception if not a valid metric or dimensions, or not a 'get' function
565 | */
566 | public function __call($name, $parameters) {
567 | if (!preg_match('/^get/', $name)) {
568 | throw new Exception('No such function "' . $name . '"');
569 | }
570 |
571 | $name = preg_replace('/^get/', '', $name);
572 |
573 | $metric_key = gapi::ArrayKeyExists($name, $this->metrics);
574 |
575 | if ($metric_key) {
576 | return $this->metrics[$metric_key];
577 | }
578 |
579 | $dimension_key = gapi::ArrayKeyExists($name, $this->dimensions);
580 |
581 | if ($dimension_key) {
582 | return $this->dimensions[$dimension_key];
583 | }
584 |
585 | throw new Exception('No valid metric or dimesion called "' . $name . '"');
586 | }
587 | }
588 |
589 | /**
590 | * OAuth2 Google API authentication
591 | *
592 | */
593 | class gapiOAuth2 {
594 | const scope_url = 'https://www.googleapis.com/auth/analytics.readonly';
595 | const request_url = 'https://www.googleapis.com/oauth2/v3/token';
596 | const grant_type = 'urn:ietf:params:oauth:grant-type:jwt-bearer';
597 | const header_alg = 'RS256';
598 | const header_typ = 'JWT';
599 |
600 | private function base64URLEncode($data) {
601 | return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
602 | }
603 |
604 | private function base64URLDecode($data) {
605 | return base64_decode(str_pad(strtr($data, '-_', '+/'), strlen($data) % 4, '=', STR_PAD_RIGHT));
606 | }
607 |
608 | /**
609 | * Authenticate Google Account with OAuth2
610 | *
611 | * @param String $client_email
612 | * @param String $key_file
613 | * @param String $delegate_email
614 | * @return String Authentication token
615 | */
616 | public function fetchToken($client_email, $key_file, $delegate_email = null) {
617 | $header = array(
618 | "alg" => self::header_alg,
619 | "typ" => self::header_typ,
620 | );
621 |
622 | $claimset = array(
623 | "iss" => $client_email,
624 | "scope" => self::scope_url,
625 | "aud" => self::request_url,
626 | "exp" => time() + (60 * 60),
627 | "iat" => time(),
628 | );
629 |
630 | if(!empty($delegate_email)) {
631 | $claimset["sub"] = $delegate_email;
632 | }
633 |
634 | $data = $this->base64URLEncode(json_encode($header)) . '.' . $this->base64URLEncode(json_encode($claimset));
635 |
636 | if (!file_exists($key_file)) {
637 | if ( !file_exists(__DIR__ . DIRECTORY_SEPARATOR . $key_file) ) {
638 | throw new Exception('GAPI: Failed load key file "' . $key_file . '". File could not be found.');
639 | } else {
640 | $key_file = __DIR__ . DIRECTORY_SEPARATOR . $key_file;
641 | }
642 | }
643 |
644 | $key_data = file_get_contents($key_file);
645 |
646 | if (empty($key_data)) {
647 | throw new Exception('GAPI: Failed load key file "' . $key_file . '". File could not be opened or is empty.');
648 | }
649 |
650 | openssl_pkcs12_read($key_data, $certs, 'notasecret');
651 |
652 | if (!isset($certs['pkey'])) {
653 | throw new Exception('GAPI: Failed load key file "' . $key_file . '". Unable to load pkcs12 check if correct p12 format.');
654 | }
655 |
656 | openssl_sign($data, $signature, openssl_pkey_get_private($certs['pkey']), "sha256");
657 |
658 | $post_variables = array(
659 | 'grant_type' => self::grant_type,
660 | 'assertion' => $data . '.' . $this->base64URLEncode($signature),
661 | );
662 |
663 | $url = new gapiRequest(self::request_url);
664 | $response = $url->post(null, $post_variables);
665 | $auth_token = json_decode($response['body'], true);
666 |
667 | if (substr($response['code'], 0, 1) != '2' || !is_array($auth_token) || empty($auth_token['access_token'])) {
668 | throw new Exception('GAPI: Failed to authenticate user. Error: "' . strip_tags($response['body']) . '"');
669 | }
670 |
671 | $this->auth_token = $auth_token['access_token'];
672 |
673 | return $this->auth_token;
674 | }
675 |
676 | /**
677 | * Return the auth token string retrieved from Google
678 | *
679 | * @return String
680 | */
681 | public function getToken() {
682 | return $this->auth_token;
683 | }
684 |
685 | /**
686 | * Generate authorization token header for all requests
687 | *
688 | * @param String $token
689 | * @return Array
690 | */
691 | public function generateAuthHeader($token=null) {
692 | if ($token == null)
693 | $token = $this->auth_token;
694 | return array('Authorization' => 'Bearer ' . $token);
695 | }
696 | }
697 |
698 | /**
699 | * Google Analytics API request
700 | *
701 | */
702 | class gapiRequest {
703 | const http_interface = 'auto'; //'auto': autodetect, 'curl' or 'fopen'
704 | const interface_name = gapi::interface_name;
705 |
706 | private $url = null;
707 |
708 | public function __construct($url) {
709 | $this->url = $url;
710 | }
711 |
712 | /**
713 | * Return the URL to be requested, optionally adding GET variables
714 | *
715 | * @param Array $get_variables
716 | * @return String
717 | */
718 | public function getUrl($get_variables=null) {
719 | if (is_array($get_variables)) {
720 | $get_variables = '?' . str_replace('&', '&', urldecode(http_build_query($get_variables, '', '&')));
721 | } else {
722 | $get_variables = null;
723 | }
724 |
725 | return $this->url . $get_variables;
726 | }
727 |
728 | /**
729 | * Perform http POST request
730 | *
731 | *
732 | * @param Array $get_variables
733 | * @param Array $post_variables
734 | * @param Array $headers
735 | */
736 | public function post($get_variables=null, $post_variables=null, $headers=null) {
737 | return $this->request($get_variables, $post_variables, $headers);
738 | }
739 |
740 | /**
741 | * Perform http GET request
742 | *
743 | *
744 | * @param Array $get_variables
745 | * @param Array $headers
746 | */
747 | public function get($get_variables=null, $headers=null) {
748 | return $this->request($get_variables, null, $headers);
749 | }
750 |
751 | /**
752 | * Perform http request
753 | *
754 | *
755 | * @param Array $get_variables
756 | * @param Array $post_variables
757 | * @param Array $headers
758 | */
759 | public function request($get_variables=null, $post_variables=null, $headers=null) {
760 | $interface = self::http_interface;
761 |
762 | if (self::http_interface == 'auto')
763 | $interface = function_exists('curl_exec') ? 'curl' : 'fopen';
764 |
765 | switch ($interface) {
766 | case 'curl':
767 | return $this->curlRequest($get_variables, $post_variables, $headers);
768 | case 'fopen':
769 | return $this->fopenRequest($get_variables, $post_variables, $headers);
770 | default:
771 | throw new Exception('Invalid http interface defined. No such interface "' . self::http_interface . '"');
772 | }
773 | }
774 |
775 | /**
776 | * HTTP request using PHP CURL functions
777 | * Requires curl library installed and configured for PHP
778 | *
779 | * @param Array $get_variables
780 | * @param Array $post_variables
781 | * @param Array $headers
782 | */
783 | private function curlRequest($get_variables=null, $post_variables=null, $headers=null) {
784 | $ch = curl_init();
785 |
786 | if (is_array($get_variables)) {
787 | $get_variables = '?' . str_replace('&', '&', urldecode(http_build_query($get_variables, '', '&')));
788 | } else {
789 | $get_variables = null;
790 | }
791 |
792 | curl_setopt($ch, CURLOPT_URL, $this->url . $get_variables);
793 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
794 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //CURL doesn't like google's cert
795 |
796 | if (is_array($post_variables)) {
797 | curl_setopt($ch, CURLOPT_POST, true);
798 | curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_variables, '', '&'));
799 | }
800 |
801 | if (is_array($headers)) {
802 | $string_headers = array();
803 | foreach ($headers as $key => $value) {
804 | $string_headers[] = "$key: $value";
805 | }
806 | curl_setopt($ch, CURLOPT_HTTPHEADER, $string_headers);
807 | }
808 |
809 | $response = curl_exec($ch);
810 | $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
811 |
812 | curl_close($ch);
813 |
814 | return array('body' => $response, 'code' => $code);
815 | }
816 |
817 | /**
818 | * HTTP request using native PHP fopen function
819 | * Requires PHP openSSL
820 | *
821 | * @param Array $get_variables
822 | * @param Array $post_variables
823 | * @param Array $headers
824 | */
825 | private function fopenRequest($get_variables=null, $post_variables=null, $headers=null) {
826 | $http_options = array('method'=>'GET', 'timeout'=>3);
827 |
828 | $string_headers = '';
829 | if (is_array($headers)) {
830 | foreach ($headers as $key => $value) {
831 | $string_headers .= "$key: $value\r\n";
832 | }
833 | }
834 |
835 | if (is_array($get_variables)) {
836 | $get_variables = '?' . str_replace('&', '&', urldecode(http_build_query($get_variables, '', '&')));
837 | }
838 | else {
839 | $get_variables = null;
840 | }
841 |
842 | if (is_array($post_variables)) {
843 | $post_variables = str_replace('&', '&', urldecode(http_build_query($post_variables, '', '&')));
844 | $http_options['method'] = 'POST';
845 | $string_headers = "Content-type: application/x-www-form-urlencoded\r\n" . "Content-Length: " . strlen($post_variables) . "\r\n" . $string_headers;
846 | $http_options['header'] = $string_headers;
847 | $http_options['content'] = $post_variables;
848 | }
849 | else {
850 | $post_variables = '';
851 | $http_options['header'] = $string_headers;
852 | }
853 |
854 | $context = stream_context_create(array('http'=>$http_options));
855 | $response = @file_get_contents($this->url . $get_variables, null, $context);
856 |
857 | return array('body'=>$response!==false?$response:'Request failed, consider using php5-curl module for more information.', 'code'=>$response!==false?'200':'400');
858 | }
859 | }
--------------------------------------------------------------------------------