MonsterInsights_GA

The Google Analytics for WordPress by MonsterInsights MonsterInsights GA class.

Defined (1)

The class is defined in the following location(s).

/includes/admin/google.php  
  1. final class MonsterInsights_GA { 
  2.  
  3. /** 
  4. * Holds the GA client object if using oAuth. 
  5. * @access public 
  6. * @since 6.0.0 
  7. * @var MonsterInsights_GA_Client $client GA client object. 
  8. */ 
  9. public $client; 
  10.  
  11. /** 
  12. * Google Profile ID. 
  13. * @access public 
  14. * @since 6.0.0 
  15. * @var int $profile ID of profile in use. 
  16. */ 
  17. public $profile; 
  18.  
  19. /** 
  20. * Google UA code. 
  21. * @access public 
  22. * @since 6.0.0 
  23. * @var string|false $ua Google UA code for the current profile if valid oAuth in use, else false. 
  24. */ 
  25. public $ua; 
  26.  
  27. /** 
  28. * Google profile name. 
  29. * @access public 
  30. * @since 6.0.0 
  31. * @var string|false $ua Google profile name for the current profile if valid oAuth in use, else false. 
  32. */ 
  33. public $name; 
  34.  
  35. /** 
  36. * Status of Google client object. 
  37. * @access public 
  38. * @since 6.0.0 
  39. * @var string $status Possible values include manual, expired, valid, needs-permissions, blocked and none. 
  40. */ 
  41. public $status; 
  42.  
  43. /** 
  44. * oAuth Permissions Version. 
  45. * @access public 
  46. * @since 6.0.0 
  47. * @var string $oauth_version Version of oAuth permissions granted. 
  48. */ 
  49. public $oauth_version;  
  50.  
  51. /** 
  52. * Holds the base object. 
  53. * @access public 
  54. * @since 6.0.0 
  55. * @var MonsterInsights $base MonsterInsights Base object. 
  56. */ 
  57. public $base; 
  58.  
  59. /** 
  60. * Primary class constructor. 
  61. * @access public 
  62. * @since 6.0.0 
  63. */ 
  64. public function __construct() { 
  65. // Get object  
  66. $this->client = $this->get_client(); 
  67. $this->profile = $this->get_profile(); 
  68. $this->ua = $this->get_ua(); 
  69. $this->name = $this->get_name(); 
  70. $this->oauth_version = $this->get_oauth_version(); 
  71. $this->status = $this->get_status(); 
  72. $this->base = MonsterInsights(); 
  73.  
  74.  
  75. // Show any info/error notices 
  76. $this->get_notices(); 
  77.  
  78. // Authentication Actions 
  79. add_action( 'wp_ajax_monsterinsights_google_view', array( $this, 'google_auth_view' ) ); 
  80. add_action( 'wp_ajax_monsterinsights_google_cancel', array( $this, 'google_cancel' ) ); 
  81.  
  82. add_action( 'admin_init', array( $this, 'deactivate_google' ) ); // Deactivate 
  83.  
  84. private function get_client() { 
  85. return ! empty( $this->client ) ? $this->client : monsterinsights_create_client(); 
  86.  
  87. private function set_test_client() {  
  88. $this->client = monsterinsights_create_test_client(); 
  89.  
  90. private function set_client() {  
  91. $this->client = monsterinsights_create_client(); 
  92.  
  93. /** 
  94. * Get the current GA profile 
  95. * @return null 
  96. */ 
  97. private function get_profile() { 
  98. return monsterinsights_get_option( 'analytics_profile', false ); 
  99.  
  100. private function get_name() { 
  101. return monsterinsights_get_option( 'analytics_profile_name', false ); 
  102.  
  103. private function get_ua() { 
  104. return monsterinsights_get_ua(); 
  105.  
  106. private function get_oauth_version() { 
  107. return monsterinsights_get_option( 'oauth_version', '1.0' ); 
  108.  
  109. private function get_status() { 
  110. $status = 'valid'; 
  111. if ( ! empty( $this->profile ) ) { 
  112. // We are using oAuth 
  113.  
  114. $last_run = monsterinsights_get_option( 'cron_last_run', false ); 
  115. $failed = monsterinsights_get_option( 'cron_failed', false ); 
  116. $dash_dis = monsterinsights_get_option( 'dashboards_disabled', false ); 
  117.  
  118. // See if issue connecting or expired 
  119. if ( ! $dash_dis && $failed && ( $last_run === false || monsterinsights_hours_between( $last_run ) >= 48 ) ) {  
  120. $status = 'blocked'; 
  121.  
  122. $access_token = $this->client->get_access_token(); 
  123.  
  124. // Check to make sure access token is there and not expired 
  125. if ( empty( $access_token ) || empty( $access_token['expires'] ) || current_time( 'timestamp' ) >= $access_token['expires'] ) { 
  126. $status = 'expired'; 
  127. return $status; 
  128.  
  129. // See if needs permissions 
  130. if ( version_compare( $this->oauth_version, '1.0', '<' ) ) {  
  131. $status = 'needs-permissions'; 
  132.  
  133. } else if ( ! empty( $this->ua ) ) { 
  134. // We are using manual 
  135.  
  136. } else { 
  137. // We do not have oAuth or manual active 
  138. $status = 'empty'; 
  139.  
  140. return $status; 
  141.  
  142. private function get_notices() { 
  143. // Notice for no manual or profile GA 
  144. if ( $this->status === 'empty' ) { 
  145. add_action( 'admin_notices', array( $this, 'monsterinsights_show_admin_config_empty_notice' ) ); 
  146.  
  147. $current_page = filter_input( INPUT_GET, 'page' ); 
  148.  
  149. // Only show expired, needs permission, or blocked notices on the MI pages 
  150. // We do this because unlike status empty, these only block reporting, not the frontend 
  151. // tracking from working, and as a result, these are not as urgent. Plus users generally 
  152. // don't like global notices. 
  153. if ( strpos( $current_page, 'monsterinsights' ) === 0 ) { 
  154.  
  155. // Notice for GA Access token expired (needs re-authenticate) 
  156. if ( $this->status === 'expired' ) { 
  157. add_action( 'admin_notices', array( $this, 'monsterinsights_show_admin_config_expired_notice' ) ); 
  158.  
  159. // Notice for Needs Permissions 
  160. if ( $this->status === 'needs-permissions' ) { 
  161. add_action( 'admin_notices', array( $this, 'monsterinsights_show_admin_config_needs_permissions_notice' ) ); 
  162.  
  163. // Notice for trouble connecting to Google 
  164. if ( $this->status === 'blocked' ) { 
  165. add_action( 'admin_notices', array( $this, 'monsterinsights_show_admin_config_blocked_notice' ) ); 
  166.  
  167. /** 
  168. * Used when switching GA profiles, or switching 
  169. * to/from oAuth <--> manual, or when reauthenticating 
  170. * or deleting GA profile. 
  171. * @return null 
  172. */ 
  173. private function reinitialize() {  
  174. // Get object  
  175. $this->client = $this->get_client(); 
  176. $this->profile = $this->get_profile(); 
  177. $this->ua = $this->get_ua(); 
  178. $this->name = $this->get_name(); 
  179. $this->oauth_version = $this->get_oauth_version(); 
  180. $this->status = $this->get_status(); 
  181.  
  182. // Re-get data if possible 
  183. if ( $this->ua === 'valid' ) { 
  184. $this->refresh_dashboard_data(); 
  185.  
  186. public function create_auth_url() { 
  187. return $this->client->createAuthUrl(); 
  188.  
  189. /** 
  190. * Getting the analytics profiles 
  191. * Doing the request to the Google analytics API and if there is a response, parses this response and return its 
  192. * array 
  193. * @return array 
  194. */ 
  195. public function get_profiles() { // @todo: this needs exception handling for a 401 login required  
  196. $accounts = $this->get_profiles_request(); 
  197. if ( is_array( $accounts ) ) { 
  198. return $accounts; 
  199. } else { 
  200. return array(); 
  201.  
  202. public function find_selected_profile( $profile_id ) { 
  203. $profiles = $this->get_profiles(); 
  204. $found = array(); 
  205. foreach ( $profiles as $account ) { 
  206. foreach ( $account['items'] as $profile ) { 
  207. foreach ( $profile['items'] as $subprofile ) { 
  208. if ( isset( $subprofile['id'] ) && $subprofile['id'] == $profile_id ) { 
  209. $found = array( 
  210. 'id' => $profile_id,  
  211. 'ua' => $subprofile['ua_code'],  
  212. 'name' => $subprofile['name'],  
  213.  
  214. ); 
  215. break 3; 
  216. return $found; 
  217.  
  218. public function save_selected_profile( $profile ) { 
  219. monsterinsights_update_option( 'analytics_profile', $profile['id'] ); 
  220. monsterinsights_update_option( 'analytics_profile_code', $profile['ua'] ); 
  221. monsterinsights_update_option( 'analytics_profile_name', $profile['name'] ); 
  222. monsterinsights_set_client_oauth_version(); 
  223.  
  224.  
  225. /** 
  226. * Get accounts request 
  227. * @param array $response 
  228. * @return mixed 
  229. */ 
  230. private function get_profiles_request() { 
  231. global $wp_version; 
  232. $version = str_replace( '-src', '', $wp_version ); 
  233. $accounts = array(); 
  234. $start_index = 1; 
  235. $paginate = false; 
  236. $continue = true; 
  237. while ( $continue ) { 
  238. $body = array( 
  239. 'max-results' => 1000,  
  240. 'start-index' => $paginate ? $start_index + 1000 : $start_index,  
  241. ); 
  242. if ( $paginate ) { 
  243. $start_index = $start_index + 1000; 
  244. $response = $this->client->do_request( 'https://www.googleapis.com/analytics/v3/management/accounts/~all/webproperties/~all/profiles', false, 'GET', $body ); 
  245. if ( ! empty( $response ) ) { 
  246. $response = array( 
  247. 'response' => array( 'code' => $this->client->get_http_response_code() ),  
  248. 'body' => json_decode( $response->getResponseBody(), true ),  
  249. ); 
  250. } else { 
  251. if ( version_compare( $version, '4.6', '<' ) ) { 
  252. return esc_html__( 'MonsterInsights requires WordPress version 4.6 or newer to use oAuth. Please update your WordPress version.', 'google-analytics-for-wordpress' ); 
  253. } else { 
  254. if ( ! empty( $accounts ) ) { 
  255. return $accounts; 
  256. } else { 
  257. return esc_html__( 'Google Analytics had a connection error or your Google account is not signed up for Google Analytics.', 'google-analytics-for-wordpress' ); 
  258.  
  259. if ( isset( $response['response']['code'] ) && $response['response']['code'] == 200 ) { 
  260. if ( ! empty( $response['body']['items'] ) && is_array( $response['body']['items'] ) ) { 
  261. foreach ( $response['body']['items'] as $item ) { 
  262.  
  263. // Only deal with web properties, not apps. 
  264. if ( isset( $item['type'] ) && 'WEB' != $item['type'] ) { 
  265. continue; 
  266.  
  267. if ( empty( $accounts[ $item['accountId'] ] ) ) { 
  268. $accounts[ $item['accountId'] ] = array(  
  269. 'id' => $item['accountId'],  
  270. 'ua_code' => $item['webPropertyId'],  
  271. 'parent_name' => $item['websiteUrl'],  
  272. 'items' => array(),  
  273. ); 
  274.  
  275. if ( empty( $accounts[ $item['accountId'] ]['items'][ $item['internalWebPropertyId'] ] ) ) { 
  276. $accounts[ $item['accountId'] ]['items'][ $item['internalWebPropertyId'] ]= array(  
  277. 'id' => $item['webPropertyId'],  
  278. 'name' => $item['websiteUrl'],  
  279. 'items' => array(),  
  280. ); 
  281.  
  282. if ( empty( $accounts[ $item['accountId'] ]['items'][ $item['internalWebPropertyId'] ]['items'][ $item['id'] ] ) ) { 
  283. $accounts[ $item['accountId'] ]['items'][ $item['internalWebPropertyId'] ]['items'][ $item['id'] ] = array(  
  284. 'name' => $item['name'] . ' (' . $item['webPropertyId'] . ')',  
  285. 'ua_code' => $item['webPropertyId'],  
  286. 'id' => $item['id'],  
  287. ); 
  288. } else if ( isset( $response['response']['code'] ) && isset( $response['body']['error']['errors']['message'] ) && $response['response']['code'] !== 200 && ! $paginate ) { 
  289. return $response['body']['error']['errors']['message']; 
  290. } else if ( isset( $response['response']['code'] ) && $response['response']['code'] !== 200 && ! $paginate ) { 
  291. if ( version_compare( $version, '4.6', '<' ) ) { 
  292. return esc_html__( 'MonsterInsights requires WordPress version 4.6 or newer to use oAuth. Please update your WordPress version.', 'google-analytics-for-wordpress' ); 
  293. } else { 
  294. if ( ! empty( $accounts ) ) { 
  295. return $accounts; 
  296. } else { 
  297. $code = isset( $response['response']['code'] ) ? $response['response']['code'] : 'Unknown'; 
  298. return sprintf( esc_html__( 'Google Analytics had a connection error. Error code: %s.', 'google-analytics-for-wordpress' ), $code ); 
  299.  
  300. if ( isset( $response['body']['totalResults'] ) && $start_index < $response['body']['totalResults'] && ! empty( $response['body']['nextLink'] ) ) { 
  301. $paginate = true; 
  302. } else { 
  303. $continue = false; 
  304. return $accounts; 
  305.  
  306. private function clear_oauth_data() { 
  307. // Delete the stored profiles 
  308. $options = array( 
  309. 'analytics_profile_code',  
  310. 'analytics_profile',  
  311. 'analytics_profile_name',  
  312. 'oauth_version',  
  313. 'cron_failed',  
  314. 'cron_last_run',  
  315. ); 
  316. monsterinsights_delete_options( $options ); 
  317.  
  318. // Destroy the data 
  319. $this->base->reports->delete_aggregate_data(); 
  320.  
  321. $this->client->clear_data(); 
  322.  
  323. private function clear_manual_data() { 
  324. // Delete the manual ua code 
  325. monsterinsights_delete_option( 'manual_ua_code' ); 
  326.  
  327. public function deactivate_google() { 
  328. // Check if user pressed the deactivate button and nonce is valid 
  329. if ( ! isset( $_POST['monsterinsights-google-deauthenticate-submit'] ) ) { 
  330. return; 
  331.  
  332. if ( ! wp_verify_nonce( $_POST['monsterinsights-google-authenticated-nonce'], 'monsterinsights-google-authenticated-nonce' ) ) { 
  333. return; 
  334.  
  335. if ( ! current_user_can( 'monsterinsights_save_settings' ) ) { 
  336. return; 
  337.  
  338. // Destroy the client 
  339. $this->clear_oauth_data(); 
  340.  
  341. // Refresh the client 
  342. $this->reinitialize(); 
  343.  
  344. public function refresh_dashboard_data( ) { 
  345. // Destroy the data 
  346. $this->base->reports->delete_aggregate_data(); 
  347.  
  348. $this->base->reports->run_cron(); 
  349.  
  350. /** 
  351. * Check if client has a refresh token 
  352. * @return bool 
  353. */ 
  354. public function has_refresh_token() { 
  355. return $this->client->is_authenticated(); 
  356.  
  357. /** 
  358. * Doing request to Google Analytics 
  359. * This method will do a request to google and get the response code and body from content 
  360. * @param string $target_request_url 
  361. * @return array|null 
  362. */ 
  363. public function do_request( $target_request_url ) { 
  364. $response = $this->client->do_request( $target_request_url ); 
  365. if ( ! empty( $response ) ) { 
  366. return array( 
  367. 'response' => array( 'code' => $this->client->get_http_response_code() ),  
  368. 'body' => json_decode( $response->getResponseBody(), true ),  
  369. ); 
  370.  
  371. /** 
  372. * Wrapper for authenticate the client. If authentication code is send it will get and check an access token. 
  373. * @param mixed $authentication_code 
  374. * @return boolean 
  375. */ 
  376. public function authenticate( $authentication_code = null ) { 
  377. // When authentication again we should clean up some stuff 
  378. monsterinsights_delete_options( array( 'cron_last_run', 'cron_failed' ) ); 
  379. return $this->client->authenticate_client( $authentication_code ); 
  380.  
  381. public function google_auth_view() { 
  382. $view = isset( $_POST['view'] ) && in_array( $_POST['view'], array( 'prestart', 'start', 'enterkey', 'selectprofile', 'done' ) ) ? $_POST['view'] : ''; 
  383. $reauth = isset( $_POST['reauth'] ) && $_POST['reauth'] && $_POST['reauth'] !== 'false' ? true : false; 
  384.  
  385. if ( ! current_user_can( 'monsterinsights_save_settings' ) ) { 
  386. echo esc_html__( 'Permission Denied', 'google-analytics-for-wordpress'); 
  387. wp_die(); 
  388.  
  389. // We run the save routines, if required, for a view, and then after that send back the results + next view 
  390. $nextview = array(); 
  391.  
  392. switch ( $view ) { 
  393. case 'start': 
  394. if ( ! $this->is_wp_blocking_google() && ! $this->is_google_on_blacklist() ) { 
  395. $auth_url = $this->create_auth_url(); 
  396. $nextview = monsterinsights_google_auth_enterkey_view( $reauth, $auth_url ); 
  397. } else { 
  398. $error = esc_html__( 'Cannot connect to Google', 'google-analytics-for-wordpress' ); 
  399. $nextview = monsterinsights_google_auth_error_view( $reauth, $error ); 
  400. break; 
  401.  
  402. case 'enterkey': 
  403. $auth_key = ! empty( $_POST['stepdata'] ) ? sanitize_text_field( $_POST['stepdata'] ) : ''; 
  404. if ( $auth_key ) { 
  405. if ( $this->test_authkey( $auth_key ) ) { 
  406. $profiles = $this->get_profiles_request(); 
  407. delete_option( 'monsterinsights_get_profiles' ); 
  408. update_option( 'monsterinsights_get_profiles', $profiles ); 
  409. if ( ! empty( $profiles ) && is_array( $profiles ) ) { 
  410. $select = $this->ga_select( $profiles ); 
  411. $nextview = monsterinsights_google_auth_selectprofile_view( $reauth, $select ); 
  412. } else if ( ! empty( $profiles ) && is_string( $profiles ) ) { 
  413. // Error from Google 
  414. $auth_url = $this->create_auth_url(); 
  415. $this->client->clear_data(); 
  416. $this->set_test_client(); 
  417. $nextview = monsterinsights_google_auth_enterkey_view( $reauth, $auth_url, esc_html( $profiles ) ); 
  418. } else { 
  419. // No profiles or not enough permissions 
  420. $auth_url = $this->create_auth_url(); 
  421. $this->client->clear_data(); 
  422. $this->set_test_client(); 
  423. $nextview = monsterinsights_google_auth_enterkey_view( $reauth, $auth_url, esc_html__( 'No profiles viewable for that account. Please use another account.', 'google-analytics-for-wordpress' ) ); 
  424. } else { 
  425. // if bad authentication error message 
  426. $auth_url = $this->create_auth_url(); 
  427. $this->client->clear_data(); 
  428. $this->set_test_client(); 
  429. $nextview = monsterinsights_google_auth_enterkey_view( $reauth, $auth_url, esc_html__( 'Bad Google Code. Please try again.', 'google-analytics-for-wordpress' ) ); 
  430. } else { 
  431. $auth_url = $this->create_auth_url(); 
  432. $this->client->clear_data(); 
  433. $this->set_test_client(); 
  434. // if no auth key error message 
  435. $nextview = monsterinsights_google_auth_enterkey_view( $reauth, $auth_url, esc_html__( 'Please paste in your Google code.', 'google-analytics-for-wordpress' ) ); 
  436. break; 
  437.  
  438. case 'selectprofile': 
  439. $profile = ! empty( $_POST['stepdata'] ) ? absint( sanitize_text_field( $_POST['stepdata'] ) ) : ''; 
  440. if ( ! empty( $profile ) ) { 
  441. $this->set_test_client(); 
  442. $profile = $this->find_selected_profile( $profile ); 
  443. if ( ! empty( $profile ) ) { 
  444.  
  445. $this->clear_manual_data(); // Just in case we were manual, clear out UA 
  446.  
  447. $this->client->move_test_to_live(); 
  448. $this->save_selected_profile( $profile ); 
  449. $this->set_client(); 
  450. $this->reinitialize(); 
  451.  
  452. // Refresh reporting data 
  453. $this->base->reports->refresh_aggregate_data(); 
  454.  
  455. $nextview = monsterinsights_google_auth_done_view( $reauth ); 
  456. } else { 
  457. // Invalid profile selected 
  458. $profiles = get_option( 'monsterinsights_get_profiles', array() ); 
  459. $select = $this->ga_select( $profiles ); 
  460. $nextview = monsterinsights_google_auth_selectprofile_view( $reauth, $select, esc_html__( 'Invalid profile selected.', 'google-analytics-for-wordpress' ) ); 
  461. } else {  
  462. // No profile selected 
  463. $profiles = get_option( 'monsterinsights_get_profiles', array() ); 
  464. $select = $this->ga_select( $profiles ); 
  465. $nextview = monsterinsights_google_auth_selectprofile_view( $reauth, $select, esc_html__( 'Please select a profile.', 'google-analytics-for-wordpress' ) ); 
  466. break; 
  467.  
  468. case 'done': 
  469. $nextview = monsterinsights_google_auth_done_view( $reauth ); 
  470. break; 
  471.  
  472. case 'prestart': 
  473. default: 
  474. $nextview = monsterinsights_google_auth_start_view( $reauth ); 
  475. break; 
  476. echo $nextview; 
  477. wp_die(); 
  478.  
  479. public function google_cancel() { 
  480. $view = isset( $_POST['view'] ) && in_array( $_POST['view'], array( 'prestart', 'start', 'enterkey', 'selectprofile', 'done' ) ) ? $_POST['view'] : ''; 
  481. $reauth = isset( $_POST['reauth'] ) && $_POST['reauth'] && $_POST['reauth'] !== 'false' ? true : false; 
  482.  
  483. if ( ! current_user_can( 'monsterinsights_save_settings' ) ) { 
  484. echo esc_html__( 'Permission Denied', 'google-analytics-for-wordpress'); 
  485. wp_die(); 
  486.  
  487. // If we cancelled on enterkey or selectprofile, delete the temp access tokens and set client back to normal client 
  488. if ( $view === 'enterkey' || $view === 'selectprofile' ) { 
  489. $this->client->clear_data(); 
  490. delete_option( 'monsterinsights_get_profiles' ); 
  491. $this->set_client(); 
  492.  
  493. private function test_authkey( $authkey ) { 
  494. $this->set_test_client(); 
  495. $result = $this->authenticate( $authkey ); 
  496. return $result; 
  497.  
  498. /** 
  499. * Generates the GA select box 
  500. * @return null|string 
  501. */ 
  502. private function ga_select( $profiles = array() ) { 
  503. if ( empty( $profiles ) || ! is_array( $profiles ) ) {  
  504. $profiles = $this->get_profiles(); 
  505.  
  506. $optgroups = array(); 
  507. foreach ( $profiles as $key => $value ) { 
  508. foreach ( $value['items'] as $subitem ) { 
  509. $optgroups[ $subitem['name'] ]['items'] = $subitem['items']; 
  510.  
  511. $values = $optgroups; 
  512. $select = ''; 
  513. $select .= '<div class="monsterinsights_ga_form">'; 
  514. $select .= '<label for="monsterinsights_step_data" id="monsterinsights_select_ga_profile_label">' . esc_html__( 'Analytics profile', 'google-analytics-for-wordpress' ) . ':</label>'; 
  515. $select .= '<select data-placeholder="' . esc_attr__( 'Select a profile', 'google-analytics-for-wordpress' ) . '" name="monsterinsights_step_data" class="monsterinsights-select300 monsterinsights_select_ga_profile" id="monsterinsights_step_data" style="width:80%;margin-left:10%;margin-right:10%;background-color: #FFF;">'; 
  516. $select .= '<option></option>'; 
  517.  
  518. if ( count( $values ) >= 1 ) { 
  519. foreach ( $values as $optgroup => $value ) { 
  520. if ( ! empty( $value['items'] ) ) { 
  521. $select .= $this->create_optgroup( $optgroup, $value ); 
  522. else { 
  523. $select .= '<option value="' . esc_attr( $value['id'] ) . '">' . esc_attr( stripslashes( $value['name'] ) ) . '</option>'; 
  524. $select .= '</select>'; 
  525. $select .= '</div>'; 
  526. return $select; 
  527.  
  528. /** 
  529. * Creates a optgroup with the items. If items contain items it will create a nested optgroup 
  530. * @param string $optgroup 
  531. * @param array $value 
  532. * @param array $select_value 
  533. * @return string 
  534. */ 
  535. private function create_optgroup( $optgroup, $value ) { 
  536. $optgroup = '<optgroup label="' . esc_attr( $optgroup ) . '">'; 
  537.  
  538. foreach ( $value['items'] as $option ) { 
  539. if ( ! empty( $option['items'] ) ) { 
  540.  
  541. $optgroup .= $this->create_optgroup( esc_attr( $option['name'] ), $option ); 
  542. else { 
  543. $optgroup .= '<option value="' . esc_attr( $option['id'] ) . '">' . esc_attr( stripslashes( $option['name'] ) ) . '</option>'; 
  544.  
  545. $optgroup .= '</optgroup>'; 
  546.  
  547. return $optgroup; 
  548.  
  549. /** 
  550. * See if Google is on the block_request list. 
  551. * @return bool  
  552. */ 
  553. private function is_wp_blocking_google() { 
  554. if ( defined( 'WP_HTTP_BLOCK_EXTERNAL' ) && WP_HTTP_BLOCK_EXTERNAL ) { // @todo: put this in sysinfo  
  555. if ( defined( 'WP_ACCESSIBLE_HOSTS' ) ) { 
  556. $on_blacklist = $this->is_google_on_blacklist(); 
  557. if ( $on_blacklist ) { 
  558. return true; 
  559. } else { 
  560. $params = array( 
  561. 'sslverify' => false,  
  562. 'timeout' => 60,  
  563. 'user-agent' => 'MonsterInsights/' . MONSTERINSIGHTS_VERSION,  
  564. 'body' => '' 
  565. ); 
  566. $response = wp_remote_get( 'https://www.googleapis.com/discovery/v1/apis/analytics/v3/rest', $params ); 
  567. if( ! is_wp_error( $response ) && $response['response']['code'] >= 200 && $response['response']['code'] < 300 ) { 
  568. return false; 
  569. } else { 
  570. return true; 
  571. } else { 
  572. return true; 
  573. } else { 
  574. $params = array( 
  575. 'sslverify' => false,  
  576. 'timeout' => 60,  
  577. 'user-agent' => 'MonsterInsights/' . MONSTERINSIGHTS_VERSION,  
  578. 'body' => '' 
  579. ); 
  580. $response = wp_remote_get( 'https://www.googleapis.com/discovery/v1/apis/analytics/v3/rest', $params ); 
  581.  
  582. if( !is_wp_error( $response ) && $response['response']['code'] >= 200 && $response['response']['code'] < 300 ) { 
  583. return false; 
  584. } else { 
  585. return true; 
  586.  
  587. /** 
  588. * See if Google is on the block_request list. 
  589. * @return bool  
  590. */ 
  591. private function is_google_on_blacklist() { // @todo: put this in sysinfo 
  592. $wp_http = new WP_Http(); 
  593. if ( $wp_http->block_request( 'https://www.googleapis.com/discovery/v1/apis/analytics/v3/rest' ) ) { 
  594. return true; 
  595.  
  596. return false; 
  597.  
  598. public function monsterinsights_show_admin_config_empty_notice() { 
  599. $screen = get_current_screen();  
  600. if ( empty( $screen->id ) || strpos( $screen->id, 'monsterinsights' ) !== false ) { 
  601. return; 
  602. echo '<div class="error"><p>' .  
  603. sprintf( esc_html__( 'Please configure your %1$sGoogle Analytics settings%2$s!', 'google-analytics-for-wordpress' ),  
  604. '<a href="' . admin_url( 'admin.php?page=monsterinsights_settings' ) . '">',  
  605. '</a>' 
  606. . '</p></div>'; 
  607.  
  608. /** 
  609. * Throw a warning when the fetching failed 
  610. */ 
  611. public function monsterinsights_show_admin_config_expired_notice() { 
  612. echo '<div class="error"><p>' .  
  613. sprintf( 
  614. esc_html__( 'It seems the authentication for the plugin has expired or the connection to Google Analytics is blocked, please try %1$sre-authenticating%2$s with Google Analytics to allow the plugin to fetch data.', 'google-analytics-for-wordpress' ),  
  615. '<a href="' . admin_url( 'admin.php?page=monsterinsights_settings' ) . '">',  
  616. '</a>' 
  617. . '</p></div>'; 
  618.  
  619. /** 
  620. * Throw a warning when the fetching failed 
  621. */ 
  622. public function monsterinsights_show_admin_config_needs_permissions_notice() { 
  623. echo '<div class="error"><p>' .  
  624. sprintf( 
  625. esc_html__( 'It seems the authentication for the plugin is missing permissions. Please %1$sre-authenticate%2$s with Google Analytics to allow the plugin to fetch data.', 'google-analytics-for-wordpress' ),  
  626. '<a href="' . admin_url( 'admin.php?page=monsterinsights_settings' ) . '">',  
  627. '</a>' 
  628. . '</p></div>'; 
  629.  
  630. /** 
  631. * Throw a warning when the fetching failed 
  632. */ 
  633. public function monsterinsights_show_admin_config_blocked_notice() { 
  634. echo '<div class="error"><p>' .  
  635. sprintf( 
  636. esc_html__( 'Data is not up-to-date, there was an error in retrieving the data from Google Analytics. This error could be caused by several issues. If the error persists, please see %1$sthis page%2$s.', 'google-analytics-for-wordpress' ),  
  637. '<a href="https://www.monsterinsights.com/docs/blocked-connection/">',  
  638. '</a>' 
  639. . '</p></div>';