diff --git a/google_analytics_reports.blocks.inc b/google_analytics_reports.blocks.inc index 2bae17c..1a336d3 100644 --- a/google_analytics_reports.blocks.inc +++ b/google_analytics_reports.blocks.inc @@ -24,7 +24,7 @@ function google_analytics_reports_dashboard_ajax() { * Generates a block with the current page statistics. */ function google_analytics_reports_path_mini_build($path) { - if (!variable_get('google_analytics_reports_api_oauth_token', FALSE)) { + if (!variable_get('google_analytics_reports_api_access_token', FALSE)) { return '

' . t('You must authorize Drupal to use your Analytics account before you can view reports.', array('!url' => url('admin/config/system/google-analytics-reports-api'))) . '

'; } diff --git a/google_analytics_reports.css b/google_analytics_reports.css index fdab764..e652188 100644 --- a/google_analytics_reports.css +++ b/google_analytics_reports.css @@ -3,12 +3,12 @@ * Google Analytics Reports styles. */ -.google-analytics-referrals, -.google-analytics-keywords { +.google-analytics-reports-summary-top-sources, +.google-analytics-reports-summary-top-keywords { width: 49.3%; float: left; } -.google-analytics-referrals { +.google-analytics-reports-summary-top-sources { margin-right: 1.4%; } diff --git a/google_analytics_reports.info b/google_analytics_reports.info index 9ae51ba..04ffb5b 100644 --- a/google_analytics_reports.info +++ b/google_analytics_reports.info @@ -3,7 +3,8 @@ package = Statistics description = Provides interface to access Google Analytics Core Reporting API statistics. core = 7.x dependencies[] = google_analytics_reports_api -dependencies[] = chart +dependencies[] = charts +dependencies[] = charts_google stylesheets[all][] = google_analytics_reports.css scripts[] = google_analytics_reports.js diff --git a/google_analytics_reports.module b/google_analytics_reports.module index 4de199d..69279b5 100644 --- a/google_analytics_reports.module +++ b/google_analytics_reports.module @@ -9,14 +9,6 @@ * Implements hook_menu(). */ function google_analytics_reports_menu() { - $items['admin/reports/google-analytics'] = array( - 'title' => 'Google Analytics Summary', - 'description' => "View a traffic report for your site.", - 'page callback' => 'google_analytics_reports_summary_page', - 'access arguments' => array('access google analytics reports'), - 'file' => 'google_analytics_reports.pages.inc', - 'type' => MENU_NORMAL_ITEM, - ); $items['admin/reports/google-analytics/detail'] = array( 'title' => 'Content Detail', 'page callback' => 'google_analytics_reports_detail_page', @@ -58,8 +50,6 @@ function google_analytics_reports_page_build(&$page) { */ function google_analytics_reports_block_info() { $blocks['path_mini']['info'] = t('Google Analytics page traffic'); - $blocks['dashboard']['info'] = t('Google Analytics site visits'); - $blocks['dashboard']['properties']['administrative'] = TRUE; return $blocks; } @@ -75,11 +65,6 @@ function google_analytics_reports_block_view($delta = '') { $block['subject'] = t('Page traffic'); $block['content'] = '
'; return $block; - - case 'dashboard': - $block['subject'] = t('Google Analytics Summary'); - $block['content'] = '
'; - return $block; } } @@ -95,25 +80,24 @@ function google_analytics_reports_permission() { } /** + * Implements hook_views_api(). + */ +function google_analytics_reports_views_api() { + return array( + 'api' => 3.0, + ); +} + +/** * Implements hook_theme(). */ function google_analytics_reports_theme() { return array( - 'google_analytics_reports_summary' => array( - 'variables' => array('summary' => NULL), - 'template' => 'templates/google_analytics_reports_summary', - 'file' => 'google_analytics_reports.theme.inc', - ), 'google_analytics_reports_detail' => array( 'variables' => array('report' => NULL), 'template' => 'templates/google_analytics_reports_detail', 'file' => 'google_analytics_reports.theme.inc', ), - 'google_analytics_reports_dashboard' => array( - 'variables' => array('report' => NULL), - 'template' => 'templates/google_analytics_reports_dashboard', - 'file' => 'google_analytics_reports.theme.inc', - ), 'google_analytics_reports_path_mini' => array( 'variables' => array('report' => NULL), 'file' => 'google_analytics_reports.theme.inc', diff --git a/google_analytics_reports.pages.inc b/google_analytics_reports.pages.inc index 8ea1e0f..9142f36 100644 --- a/google_analytics_reports.pages.inc +++ b/google_analytics_reports.pages.inc @@ -6,38 +6,6 @@ */ /** - * Page callback for admin/reports/google-analytics. - * - * Returns HTML summary of the site-wide statistics. - */ -function google_analytics_reports_summary_page() { - if (!variable_get('google_analytics_reports_api_oauth_token', FALSE)) { - drupal_set_message(t('You must authorize Drupal to use your Analytics account before you can view reports.', - array('!url' => url('admin/config/system/google-analytics-reports-api'))), 'warning'); - return ' '; - } - - $summary = array( - 'visit_chart' => _google_analytics_reports_visits(), - 'usage' => _google_analytics_reports_usage(), - 'pages' => _google_analytics_reports_top_pages(), - 'referrals' => _google_analytics_reports_top_referrals(), - 'keywords' => _google_analytics_reports_top_keywords(), - ); - - if (in_array(FALSE, $summary, TRUE)) { - $menu_item = menu_get_item(); - if ($menu_item['href'] == 'admin/reports/google-analytics') { - drupal_set_message(_google_analytics_reports_error_message(), 'error'); - return ' '; - } - return '

' . _google_analytics_reports_error_message() . '

'; - } - - return theme('google_analytics_reports_summary', $summary); -} - -/** * Page callback for admin/reports/google-analytics/detail. */ function google_analytics_reports_detail_page() { diff --git a/google_analytics_reports.theme.inc b/google_analytics_reports.theme.inc index 25e9ca3..86cdd86 100644 --- a/google_analytics_reports.theme.inc +++ b/google_analytics_reports.theme.inc @@ -6,77 +6,6 @@ */ /** - * Google Analytics Reports summary template. - */ -function template_preprocess_google_analytics_reports_summary(&$vars) { - $vars = array_merge($vars, $vars['usage']); - - if ($vars['sessions'] <= 0) { - $vars['pages_per_visit'] = '0.00'; - $vars['new_visits'] = '0.00%'; - $vars['time_on_site'] = '0:00'; - } - else { - $vars['pages_per_visit'] = number_format(round($vars['pageviews'] / $vars['sessions'], 2), 2); - $vars['new_visits'] = number_format(round(($vars['newUsers'] / $vars['sessions']) * 100, 2), 2) . '%'; - $vars['time_on_site'] = format_interval($vars['sessionDuration'] / $vars['sessions']); - } - - if ($vars['entrances'] <= 0) { - $vars['bounces'] = '0.00%'; - } - else { - $vars['bounces'] = number_format(round(($vars['bounces'] / $vars['entrances']) * 100, 2), 2) . '%'; - } - - $vars['entrances'] = number_format($vars['entrances']); - $vars['pageviews'] = number_format($vars['pageviews']); - - $pages = array(); - foreach ($vars['pages'] as $page) { - if ($page['pagePath'] == '/index.html') { - $page['pagePath'] = variable_get('google_analytics_reports_api_default_page', '/'); - } - $pages[] = l($page['pageTitle'], 'http://' . $page['hostname'] . $page['pagePath'], - array( - 'external' => TRUE, - 'html' => TRUE, - ) - ) . ' - ' . format_plural($page['pageviews'], '1 View', '@views Views', array( - '@views' => number_format($page['pageviews']), - )); - } - $vars['pages'] = theme('item_list', array( - 'items' => $pages, - 'type' => 'ol', - )); - - $referrals = array(); - foreach ($vars['referrals'] as $referral) { - $referrals[] = '' . $referral['source'] . ' - ' . format_plural( - $referral['sessions'], '1 Session', '@sessions Sessions', array( - '@sessions' => number_format($referral['sessions']), - )); - } - $vars['referrals'] = theme('item_list', array( - 'items' => $referrals, - 'type' => 'ol', - )); - - $keywords = array(); - foreach ($vars['keywords'] as $keyword) { - $keywords[] = '' . $keyword['keyword'] . ' - ' . format_plural( - $keyword['sessions'], '1 Session', '@sessions Sessions', array( - '@sessions' => number_format($keyword['sessions']), - )); - } - $vars['keywords'] = theme('item_list', array( - 'items' => $keywords, - 'type' => 'ol', - )); -} - -/** * Google Analytics Reports detail template. */ function template_preprocess_google_analytics_reports_detail(&$vars) { diff --git a/google_analytics_reports_api/google_analytics_reports_api.info b/google_analytics_reports_api/google_analytics_reports_api.info index 56b37c1..96386d4 100644 --- a/google_analytics_reports_api/google_analytics_reports_api.info +++ b/google_analytics_reports_api/google_analytics_reports_api.info @@ -3,8 +3,6 @@ package = Statistics description = API to access statistics from the Google Analytics Core Reporting API. core = 7.x -dependencies[] = oauth_common - files[] = google_analytics_reports_api.lib.inc configure = admin/config/system/google-analytics-reports-api diff --git a/google_analytics_reports_api/google_analytics_reports_api.lib.inc b/google_analytics_reports_api/google_analytics_reports_api.lib.inc index 18c5aa1..194eb0d 100644 --- a/google_analytics_reports_api/google_analytics_reports_api.lib.inc +++ b/google_analytics_reports_api/google_analytics_reports_api.lib.inc @@ -12,6 +12,11 @@ */ class GoogleAnalyticsReportsApiFeed { + const OAUTH2_REVOKE_URI = 'https://accounts.google.com/o/oauth2/revoke'; + const OAUTH2_TOKEN_URI = 'https://accounts.google.com/o/oauth2/token'; + const OAUTH2_AUTH_URL = 'https://accounts.google.com/o/oauth2/auth'; + const SCOPE = 'https://www.googleapis.com/auth/analytics.readonly https://www.google.com/analytics/feeds/'; + // Response object. public $response; @@ -27,21 +32,21 @@ class GoogleAnalyticsReportsApiFeed { // Boolean TRUE if data is from the cache tables. public $fromCache = FALSE; + // OAuth access token. + public $access_token; + + // OAuth refresh token. + public $refresh_token; + + // OAuth expiration time. + public $expires_at; + // Host and endpoint of Google Analytics API. protected $host = 'www.googleapis.com/analytics/v3'; // Request header source. protected $source = 'drupal'; - // Default is HMAC-SHA1. - protected $signatureMethod; - - // HMAC-SHA1 Consumer data. - protected $consumer; - - // OAuth token. - protected $token; - // Google authorize callback verifier string. protected $verifier; @@ -52,121 +57,191 @@ class GoogleAnalyticsReportsApiFeed { * Check if object is authenticated with Google. */ public function isAuthenticated() { - return !empty($this->token); + return !empty($this->access_token); + } + + public function __construct($token = NULL) { + $this->access_token = $token; } /** - * Constructor for the GoogleAnalyticsReportsApiFeed class. + * Get the current page url + * + * @return String */ - public function __construct($consumer_key, $consumer_secret, $oauth_token = NULL, $oauth_token_secret = NULL) { - $this->signatureMethod = new OAuthSignatureMethod_HMAC_SHA1(); - $this->consumer = new OAuthConsumer($consumer_key, $consumer_secret); - - // Allow developers the option of OAuth authentication without - // using this class's methods. - if (!empty($oauth_token) && !empty($oauth_token_secret)) { - $this->token = new OAuthConsumer($oauth_token, $oauth_token_secret); + public static function currentUrl() { + $https = $_SERVER['HTTPS'] == 'on'; + $url = $https ? 'https://' : 'http://'; + $url .= $_SERVER['SERVER_NAME']; + if ((!$https && $_SERVER['SERVER_PORT'] != '80') || + ($https && $_SERVER['SERVER_PORT'] != '443')) { + $url .= ':' . $_SERVER['SERVER_PORT']; + } + + return $url . $_SERVER['REQUEST_URI']; + } + + /** + * Create a URL to obtain user authorization. + * The authorization endpoint allows the user to first + * authenticate, and then grant/deny the access request. + * @param string $client_id + * @return string + */ + public function createAuthUrl($client_id, $redirect_uri) { + $params = array( + 'response_type=code', + 'redirect_uri=' . $redirect_uri, + 'client_id=' . urlencode($client_id), + 'scope=' . self::SCOPE, + 'access_type=offline', + 'approval_prompt=force' + ); + + $params = implode('&', $params); + return self::OAUTH2_AUTH_URL . "?$params"; + } + + /** + * Authenticate with the Google API + * + * @param String $client_id + * @param String $client_secret + * @param String $refresh_token + * @return GAFeed + */ + protected function fetchToken($client_id, $client_secret, $redirect_uri, $refresh_token=NULL) { + if ($refresh_token) { + $params = array( + 'client_id=' . $client_id, + 'client_secret=' . $client_secret, + 'refresh_token=' . $refresh_token, + 'grant_type=refresh_token', + ); } + else { + $params = array( + 'code=' . $_GET['code'], + 'grant_type=authorization_code', + 'redirect_uri=' . $redirect_uri, + 'client_id=' . $client_id, + 'client_secret=' . $client_secret, + ); + } + + $data = implode('&', $params); + + $this->response = drupal_http_request(self::OAUTH2_TOKEN_URI, array('headers' => array('Content-Type' => 'application/x-www-form-urlencoded'), 'method' => 'POST', 'data' => $data)); + + if (substr($this->response->code, 0, 1) == '2') { + $decoded_response = json_decode($this->response->data, true); + $this->access_token = $decoded_response['access_token']; + $this->expires_at = time() + $decoded_response['expires_in']; + if (!$refresh_token) { + $this->refresh_token = $decoded_response['refresh_token']; + } + } + else { + $error_msg = 'Code: !code - Error: !message - Message: !details'; + $error_vars = array('!code' => $this->response->code, '!message' => $this->response->error, '!details' => strip_tags($this->response->data)); + $this->error = t($error_msg, $error_vars); + watchdog('google analytics reports', $error_msg, $error_vars, WATCHDOG_ERROR); } +} /** - * Set the verifier property. + * Complete the authentication process. + * We got here after being redirected from a successful authorization grant. + * Fetch the access token + * + * @param String $client_id + * @param String $client_secret */ - public function setVerifier($verifier) { - $this->verifier = $verifier; + public function finishAuthentication($client_id, $client_secret, $redirect_uri) { + $this->fetchToken($client_id, $client_secret, $redirect_uri); } /** - * Set the host property. + * Begin authentication by allowing the user to grant/deny access to the Google account + * + * @param String $client_id */ - public function setHost($host) { - $this->host = $host; + public function beginAuthentication($client_id, $redirect_uri) { + drupal_goto($this->createAuthUrl($client_id, $redirect_uri)); } /** - * Set the queryPath property. + * Fetches a fresh access token with the given refresh token. + * @param String $client_id + * @param String $client_secret + * @param string $refresh_token */ - protected function setQueryPath($path) { - $this->queryPath = 'https://' . $this->host . '/' . $path; + public function refreshToken($client_id, $client_secret, $refresh_token) { + $this->refresh_token = $refresh_token; + $this->fetchToken($client_id, $client_secret, '', $refresh_token); } /** * OAuth step #1: Fetch request token. + * Revoke an OAuth2 access token or refresh token. This method will revoke the current access + * token, if a token isn't provided. + * @param string|NULL $token The token (access token or a refresh token) that should be revoked. + * @return boolean Returns True if the revocation was successful, otherwise False. */ - public function getRequestToken() { - $this->setHost($this->oAuthHost); - $this->setQueryPath('accounts/OAuthGetRequestToken'); + public function revokeToken($token = NULL) { + if (!$token) { + $token = $this->refresh_token ? $this->refresh_token : $this->access_token; + } - // Xoauth_displayname is displayed on the Google Authentication page. - $params = array( - 'scope' => 'https://www.googleapis.com/auth/analytics.readonly', - 'oauth_callback' => url('google-analytics-reports/oauth', array('absolute' => TRUE)), - 'xoauth_displayname' => t('Google Analytics Reports Drupal module'), - ); + $this->response = drupal_http_request(self::OAUTH2_REVOKE_URI, array('headers' => array('Content-Type' => 'application/x-www-form-urlencoded'), 'method' => 'POST', 'data' => "token=$token")); - $this->query($this->queryPath, $params, 'GET', array('refresh' => TRUE)); - parse_str($this->response->data, $token); - $this->token = new OAuthConsumer($token['oauth_token'], $token['oauth_token_secret']); - return $token; + if ($this->response->code == 200) { + $this->access_token = NULL; + return true; + } + + return false; } /** * OAuth step #2: Authorize request token. + * Generate authorization token header for all requests + * + * @return Array */ - public function obtainAuthorization($token) { - $this->setHost($this->oAuthHost); - $this->setQueryPath('accounts/OAuthAuthorizeToken'); - - // HD is the best way of dealing with users with multiple domains - // verified with Google. - $params = array( - 'oauth_token' => $token['oauth_token'], - 'hd' => variable_get('google_analytics_reports_api_hd', 'default'), - ); - - // Check for the overlay. - if (module_exists('overlay') && overlay_get_mode() == 'child') { - overlay_close_dialog($this->queryPath, array( - 'query' => $params, - 'external' => TRUE, - )); - overlay_deliver_empty_page(); - } - else { - drupal_goto($this->queryPath, array('query' => $params)); - } + public function generateAuthHeader($token=NULL) { + if ($token == NULL) { + $token = $this->access_token; + } + return array('Authorization' => 'Bearer ' . $token); } /** * OAuth step #3: Fetch access token. + * Set the verifier property */ - public function getAccessToken() { - $this->setHost($this->oAuthHost); - $this->setQueryPath('accounts/OAuthGetAccessToken'); - - $params = array( - 'oauth_verifier' => $this->verifier, - ); + public function setVerifier($verifier) { + $this->verifier = $verifier; + } - $this->query($this->queryPath, $params, 'GET', array('refresh' => TRUE)); - parse_str($this->response->data, $token); - $this->token = new OAuthConsumer($token['oauth_token'], $token['oauth_token_secret']); - return $token; + /** + * Set the host property. + */ + public function setHost($host) { + $this->host = $host; } /** - * Revoke OAuth token. + * Set the queryPath property. */ - public function revokeToken() { - $this->setHost($this->oAuthHost); - $this->setQueryPath('accounts/AuthSubRevokeToken'); - $this->query($this->queryPath, array(), 'GET', array('refresh' => TRUE)); + protected function setQueryPath($path) { + $this->queryPath = 'https://' . $this->host . '/' . $path; } /** * Public query method for all Core Reporting API features. */ - public function query($path, $params = array(), $method = 'GET', $cache_options = array()) { + public function query($url, $params = array(), $method = 'GET', $headers, $cache_options = array()) { $params_defaults = array( 'start-index' => 1, 'max-results' => 1000, @@ -183,10 +258,10 @@ class GoogleAnalyticsReportsApiFeed { // Provide a query MD5 for the cid if the developer did not provide one. if (empty($cache_options['cid'])) { - $cache_options['cid'] = 'GoogleAnalyticsReportsApiFeed:' . md5(serialize(array_merge($params, array($path, $method)))); + $cache_options['cid'] = 'GoogleAnalyticsReportsApiFeed:' . md5(serialize(array_merge($params, array($url, $method)))); } - $cache = cache_get($cache_options['cid']); + $cache = FALSE; if (!$cache_options['refresh'] && isset($cache) && !empty($cache->data)) { $this->response = $cache->data; @@ -194,22 +269,11 @@ class GoogleAnalyticsReportsApiFeed { $this->fromCache = TRUE; } else { - $request = OAuthRequest::from_consumer_and_token($this->consumer, $this->token, $method, $this->queryPath, $params); - $request->sign_request($this->signatureMethod, $this->consumer, $this->token); - switch ($method) { - case 'GET': - $this->request($request->to_url()); - break; - - case 'POST': - $this->request($request->get_normalized_http_url(), $request->get_parameters(), 'POST'); - break; - } + $this->request($url, $params, $headers); + } - // Do not cache erroneous queries. - if (empty($this->error)) { - cache_set($cache_options['cid'], $this->response, 'cache', $cache_options['expire']); - } + if (empty($this->error)) { + cache_set($cache_options['cid'], $this->response, 'cache', $cache_options['expire']); } return (empty($this->error)); @@ -218,10 +282,12 @@ class GoogleAnalyticsReportsApiFeed { /** * Execute a query. */ - protected function request($url, $params = array(), $method = 'GET') { + protected function request($url, $params = array(), $headers = array(), $method = 'GET') { $options = array( 'method' => $method, + 'headers' => $headers, ); + if (count($params) > 0) { if ($method == 'GET') { $url .= '?' . drupal_http_build_query($params); @@ -256,7 +322,7 @@ class GoogleAnalyticsReportsApiFeed { */ public function queryAccounts($params = array(), $cache_options = array()) { $this->setQueryPath('management/accounts'); - $this->query($this->queryPath, $params, 'GET', $cache_options); + $this->query($this->queryPath, $params, 'GET', $this->generateAuthHeader(), $cache_options); return $this; } @@ -268,7 +334,7 @@ class GoogleAnalyticsReportsApiFeed { 'account-id' => '~all', ); $this->setQueryPath('management/accounts/' . $params['account-id'] . '/webproperties'); - $this->query($this->queryPath, $params, 'GET', $cache_options); + $this->query($this->queryPath, $params, 'GET', $this->generateAuthHeader(), $cache_options); return $this; } @@ -281,7 +347,8 @@ class GoogleAnalyticsReportsApiFeed { 'web-property-id' => '~all', ); $this->setQueryPath('management/accounts/' . $params['account-id'] . '/webproperties/' . $params['web-property-id'] . '/profiles'); - $this->query($this->queryPath, $params, 'GET', $cache_options); + $this->query($this->queryPath, $params, 'GET', $this->generateAuthHeader(), $cache_options); + return $this; } @@ -290,7 +357,7 @@ class GoogleAnalyticsReportsApiFeed { */ public function querySegments($params = array(), $cache_options = array()) { $this->setQueryPath('management/segments'); - $this->query($this->queryPath, $params, 'GET', $cache_options); + $this->query($this->queryPath, $params, 'GET', $this->generateAuthHeader(), $cache_options); return $this; } @@ -385,7 +452,7 @@ class GoogleAnalyticsReportsApiFeed { $parameters['max-results'] = $params['max_results']; $this->setQueryPath('data/ga'); - if ($this->query($this->queryPath, $parameters, 'GET', $cache_options)) { + if ($this->query($this->queryPath, $parameters, 'GET', $this->generateAuthHeader(), $cache_options)) { $this->sanitizeReport(); } return $this; diff --git a/google_analytics_reports_api/google_analytics_reports_api.module b/google_analytics_reports_api/google_analytics_reports_api.module index 48d4db5..c983581 100644 --- a/google_analytics_reports_api/google_analytics_reports_api.module +++ b/google_analytics_reports_api/google_analytics_reports_api.module @@ -33,15 +33,6 @@ function google_analytics_reports_api_menu() { 'page arguments' => array('google_analytics_reports_api_admin'), 'access arguments' => array('administer google analytics reports api'), ); - - // OAuth callback from Google. - $items['google-analytics-reports/oauth'] = array( - 'title' => 'Google Analytics Reports API OAuth Callback', - 'access callback' => TRUE, - 'page callback' => 'google_analytics_reports_api_oauth_callback', - 'type' => MENU_CALLBACK, - 'file' => 'google_analytics_reports_api.pages.inc', - ); return $items; } @@ -77,11 +68,58 @@ function google_analytics_reports_api_theme() { * from the Google Analytics Core Reporting API. */ function google_analytics_reports_api_new_gafeed() { - $key = variable_get('google_analytics_reports_api_consumer_key', 'anonymous'); - $secret = variable_get('google_analytics_reports_api_consumer_secret', 'anonymous'); - $oauth_token = variable_get('google_analytics_reports_api_oauth_token', NULL); - $oauth_token_secret = variable_get('google_analytics_reports_api_oauth_token_secret', NULL); - return new GoogleAnalyticsReportsApiFeed($key, $secret, $oauth_token, $oauth_token_secret); + module_load_include('inc', 'google_analytics_reports_api', 'google_analytics_reports_api.lib'); + if (variable_get('google_analytics_reports_api_access_token', NULL) && time() < variable_get('google_analytics_reports_api_expires_at', NULL)) { + // If the access token is still valid, return an authenticated GAFeed + return new GoogleAnalyticsReportsApiFeed(variable_get('google_analytics_reports_api_access_token', NULL)); + } + else if (variable_get('google_analytics_reports_api_refresh_token', NULL)) { + // If the site has an access token and refresh token, but the access + // token has expired, authenticate the user with the refresh token + $client_id = variable_get('google_analytics_reports_client_id', NULL); + $client_secret = variable_get('google_analytics_reports_client_secret', NULL); + $refresh_token = variable_get('google_analytics_reports_api_refresh_token', NULL); + + try { + $GAFeed = new GoogleAnalyticsReportsApiFeed(); + $GAFeed -> refreshToken($client_id, $client_secret, $refresh_token); + + variable_set("google_analytics_reports_api_access_token", $GAFeed->access_token); + variable_set("google_analytics_reports_api_expires_at", $GAFeed->expires_at); + return $GAFeed; + } + catch (Exception $e) { + drupal_set_message(t("There was an authentication error. Message: " . $e->getMessage()), 'error', FALSE); + return NULL; + } + } + else if (isset($_GET['code'])) { + // If there is no access token or refresh token and client is returned + // to the config page with an access code, complete the authentication + $client_id = variable_get('google_analytics_reports_client_id', NULL); + $client_secret = variable_get('google_analytics_reports_client_secret', NULL); + $redirect_uri = variable_get('google_analytics_reports_redirect_uri', NULL); + + try { + $GAFeed = new GoogleAnalyticsReportsApiFeed(); + $GAFeed -> finishAuthentication($client_id, $client_secret, $redirect_uri); + + variable_set('google_analytics_reports_api_access_token', $GAFeed->access_token); + variable_set('google_analytics_reports_api_expires_at', $GAFeed->expires_at); + variable_set('google_analytics_reports_api_refresh_token', $GAFeed->refresh_token); + variable_del('google_analytics_reports_redirect_uri'); + + drupal_set_message(t("You have been successfully authenticated."), 'status', FALSE); + drupal_goto($redirect_uri); + } + catch (Exception $e) { + drupal_set_message(t("There was an authentication error. Message: " . $e->getMessage()), 'error', FALSE); + return NULL; + } + } + else { + return NULL; + } } /** @@ -111,17 +149,23 @@ function google_analytics_reports_api_new_gafeed() { * from the Google Analytics Core Reporting API after reporting data. */ function google_analytics_reports_api_report_data($params = array(), $cache_options = array()) { - - $params_defaults = array( - 'profile_id' => 'ga:' . variable_get('google_analytics_reports_api_profile_id', 0), - ); - - $params += $params_defaults; + if(isset($params['profile_id'])) { + $params['profile_id'] = 'ga:' .$params['profile_id']; + } else { + $params['profile_id'] = 'ga:' . variable_get('google_analytics_reports_api_profile_id', 0); + } $ga_feed = google_analytics_reports_api_new_gafeed(); - $ga_feed->queryReportFeed($params, $cache_options); - return $ga_feed; + if ($ga_feed) { + $ga_feed->queryReportFeed($params, $cache_options); + return $ga_feed; + } + else { + drupal_set_message(t("There was an authentication error. Please check your Google API settings and try again."), 'error', FALSE); + $error = array('error' => TRUE); + return $error; + } } /** diff --git a/google_analytics_reports_api/google_analytics_reports_api.pages.inc b/google_analytics_reports_api/google_analytics_reports_api.pages.inc index 8620931..3b3204a 100644 --- a/google_analytics_reports_api/google_analytics_reports_api.pages.inc +++ b/google_analytics_reports_api/google_analytics_reports_api.pages.inc @@ -13,7 +13,7 @@ function google_analytics_reports_api_admin() { $form = array(); $account = google_analytics_reports_api_new_gafeed(); - if ($account->isAuthenticated()) { + if ($account && $account->isAuthenticated()) { $webprops = $account->queryWebProperties()->results->items; $profiles = $account->queryProfiles()->results->items; $options = array(); @@ -21,23 +21,25 @@ function google_analytics_reports_api_admin() { $set_default = FALSE; // Add optgroups for each web property. - foreach ($profiles as $profile) { - $webprop = NULL; - foreach ($webprops as $webprop_value) { - if ($webprop_value->id == $profile->webPropertyId) { - $webprop = $webprop_value; - break; + if(!empty($profiles)){ + foreach ($profiles as $profile) { + $webprop = NULL; + foreach ($webprops as $webprop_value) { + if ($webprop_value->id == $profile->webPropertyId) { + $webprop = $webprop_value; + break; + } } - } - $options[$webprop->name][$profile->id] = theme('google_analytics_reports_api_profile_label', array('profile' => $profile)); - // Rough attempt to see if the current site is in the account list. - if (empty($profile_id) && (parse_url($webprop->websiteUrl, PHP_URL_PATH) == $_SERVER['HTTP_HOST'])) { - $profile_id = $profile->id; - $set_default = TRUE; + $options[$webprop->name][$profile->id] = theme('google_analytics_reports_api_profile_label', array('profile' => $profile)); + // Rough attempt to see if the current site is in the account list. + if (empty($profile_id) && (parse_url($webprop->websiteUrl, PHP_URL_PATH) == $_SERVER['HTTP_HOST'])) { + $profile_id = $profile->id; + $set_default = TRUE; + } } } - + // If no profile ID is set yet, set the first profile in the list. if (empty($profile_id)) { $profile_id = key($options[key($options)]); @@ -65,6 +67,8 @@ function google_analytics_reports_api_admin() { '#collapsible' => TRUE, '#collapsed' => FALSE, ); + + $form['ga']['google_analytics_reports_api_profile_id'] = array( '#type' => 'select', '#title' => t('Reports profile'), @@ -74,8 +78,12 @@ function google_analytics_reports_api_admin() { '%profile' => theme('google_analytics_reports_api_profile_label', array('profile' => $current_profile)), )), - '#required' => TRUE, ); + + if(!empty($options) || $options[0]){ + $form['ga']['google_analytics_reports_api_profile_id']['#required'] = TRUE; + } + // Default cache periods. $times = array(); // 1-6 days. @@ -123,11 +131,23 @@ function google_analytics_reports_api_admin() { '#collapsible' => TRUE, '#collapsed' => FALSE, ); - $form['setup']['google_analytics_reports_api_hd'] = array( - '#type' => 'textfield', - '#title' => t('Google Apps for Business Domain (optional)'), - '#description' => t('Provide the domain name (example.com) if your domain is registered with Google Apps for Business. Otherwise, leave blank.'), - '#default_value' => variable_get('google_analytics_reports_api_hd', ''), + + $form['setup']['client_id'] = array( + '#type' => 'textfield', + '#title' => t('Client ID'), + '#default_value' => variable_get('google_analytics_reports_client_id', ''), + '#size' => 30, + '#description' => t('Client ID created for the app in the access tab of the ') . l('Google API Console', 'http://code.google.com/apis/console', array('attributes' => array('target' => '_blank'))), + '#weight' => -9, + ); + + $form['setup']['client_secret'] = array( + '#type' => 'textfield', + '#title' => t('Client Secret'), + '#default_value' => variable_get('google_analytics_reports_client_secret', ''), + '#size' => 30, + '#description' => t('Client Secret created for the app in the Google API Console'), + '#weight' => -8, ); $form['setup']['setup_submit'] = array( '#type' => 'submit', @@ -147,24 +167,21 @@ function google_analytics_reports_api_admin_submit($form, &$form_state) { cache_clear_all('GoogleAnalyticsReportsApiFeed', 'cache', '*'); switch ($op) { case t('Start setup and authorize account'): - variable_set('google_analytics_reports_api_hd', $form_state['values']['google_analytics_reports_api_hd']); - // Anonymous keys are a Google default. - $key = variable_get('google_analytics_reports_api_consumer_key', 'anonymous'); - $secret = variable_get('google_analytics_reports_api_consumer_secret', 'anonymous'); - $ga_feed = new GoogleAnalyticsReportsApiFeed($key, $secret); - - // Step #1 of OAuth. - $token = $ga_feed->getRequestToken(); - $_SESSION['google_analytics_reports_api_oauth']['token'] = $token; - $_SESSION['google_analytics_reports_api_oauth']['destination'] = $_GET['q']; - - // Step #2 of OAuth. - $ga_feed->obtainAuthorization($token); + $client_id = $form_state['values']['client_id']; + $client_secret = $form_state['values']['client_secret']; + $redirect_uri = GoogleAnalyticsReportsApiFeed::currentUrl(); + variable_set('google_analytics_reports_client_id', $client_id); + variable_set('google_analytics_reports_client_secret', $client_secret); + variable_set('google_analytics_reports_redirect_uri', $redirect_uri); + + module_load_include('inc', 'google_analytics_api', 'GAFeed.lib'); + $GAFeed = new GoogleAnalyticsReportsApiFeed(); + $GAFeed -> beginAuthentication($client_id, $redirect_uri); break; case t('Save settings'): - variable_set('google_analytics_reports_api_profile_id', $form_state['values']['google_analytics_reports_api_profile_id']); - variable_set('google_analytics_reports_api_cache_length', $form_state['values']['google_analytics_reports_api_cache_length']); + variable_set('google_analytics_reports_profile_id', $form_state['values']['google_analytics_reports_profile_id']); + variable_set('google_analytics_reports_cache_length', $form_state['values']['google_analytics_reports_cache_length']); drupal_set_message(t('Settings have been saved successfully.')); break; @@ -173,37 +190,4 @@ function google_analytics_reports_api_admin_submit($form, &$form_state) { drupal_set_message(t('Access token has been successfully revoked.')); break; } -} - -/** - * Page callback - Provided for Google to call back during the OAuth process. - */ -function google_analytics_reports_api_oauth_callback() { - $key = variable_get('google_analytics_reports_api_consumer_key', 'anonymous'); - $secret = variable_get('google_analytics_reports_api_consumer_secret', 'anonymous'); - - $session_data = $_SESSION['google_analytics_reports_api_oauth']; - unset($_SESSION['google_analytics_reports_api_oauth']); - - $token = $session_data['token']; - if (!is_array($token) || !$key || !$secret) { - drupal_set_message(t('Invalid Google Analytics OAuth request'), 'error'); - return ' '; - } - - if ($token['oauth_token'] != $_GET['oauth_token']) { - drupal_set_message(t('Invalid OAuth token.'), 'error'); - return ' '; - } - - $ga_feed = new GoogleAnalyticsReportsApiFeed($key, $secret, $token['oauth_token'], $token['oauth_token_secret']); - - // Google required the verifier. - $ga_feed->setVerifier($_GET['oauth_verifier']); - $response = $ga_feed->getAccessToken(); - - variable_set('google_analytics_reports_api_oauth_token', $response['oauth_token']); - variable_set('google_analytics_reports_api_oauth_token_secret', $response['oauth_token_secret']); - - drupal_goto('admin/config/system/google-analytics-reports-api'); -} +} \ No newline at end of file diff --git a/google_analytics_reports_views/google_analytics_reports_views.views.inc b/google_analytics_reports_views/google_analytics_reports_views.views.inc index 64b23cf..4549ec5 100644 --- a/google_analytics_reports_views/google_analytics_reports_views.views.inc +++ b/google_analytics_reports_views/google_analytics_reports_views.views.inc @@ -49,7 +49,7 @@ function google_analytics_reports_views_views_data() { 'title' => t('Profile ID'), 'help' => t('Profile ID'), 'argument' => array( - 'handler' => 'google_analytics_reports_views_handler_argument_string', + 'handler' => 'google_analytics_reports_views_handler_argument', ), 'filter' => array( 'handler' => 'google_analytics_reports_views_handler_filter_string', diff --git a/google_analytics_reports_views/plugins/google_analytics_reports_views_plugin_query_google_analytics.inc b/google_analytics_reports_views/plugins/google_analytics_reports_views_plugin_query_google_analytics.inc index f446f99..9eec6de 100644 --- a/google_analytics_reports_views/plugins/google_analytics_reports_views_plugin_query_google_analytics.inc +++ b/google_analytics_reports_views/plugins/google_analytics_reports_views_plugin_query_google_analytics.inc @@ -225,7 +225,14 @@ class google_analytics_reports_views_plugin_query_google_analytics extends views * Values to set: $view->result, $view->total_rows, $view->execute_time, * $view->current_page. */ - function execute(&$view) { + function execute(&$view) { + // Initial check to see if we should attempt to run the query. + if (!variable_get('google_analytics_reports_api_access_token', FALSE)) { + drupal_set_message(t('You must authorize Drupal to use your Analytics account before you can view reports.', + array('!url' => url('admin/config/system/google-analytics-reports-api'))), 'warning', FALSE); + return; + } + $query = $view->build_info['query']; $count_query = $view->build_info['count_query']; $start = microtime(TRUE);