Yoast_GA_Admin

This class is for the backend, extendable for all child classes.

Defined (1)

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

/admin/class-admin.php  
  1. class Yoast_GA_Admin extends Yoast_GA_Options { 
  2.  
  3. /** 
  4. * Constructor 
  5. */ 
  6. public function __construct() { 
  7. parent::__construct(); 
  8.  
  9. add_action( 'plugins_loaded', array( $this, 'init_ga' ) ); 
  10.  
  11. // Only run admin_init when there is a cron jon executed. 
  12. $current_page = filter_input( INPUT_GET, 'page' ); 
  13.  
  14. // Only when current page is not 'wpseo'. 
  15. if ( strpos( $current_page, 'wpseo' ) !== 0 ) { 
  16. if ( ( $this->is_running_cron() || $this->is_running_ajax() ) || strpos( $current_page, 'yst_ga' ) === 0 ) { 
  17. add_action( 'admin_init', array( $this, 'init_settings' ) ); 
  18.  
  19. add_action( 'admin_init', array( $this, 'system_info' ) ); 
  20.  
  21.  
  22. /** 
  23. * Init function when the plugin is loaded 
  24. */ 
  25. public function init_ga() { 
  26.  
  27. new Yoast_GA_Admin_Menu( $this ); 
  28.  
  29. add_filter( 'plugin_action_links_' . plugin_basename( GAWP_FILE ), array( $this, 'add_action_links' ) ); 
  30.  
  31.  
  32. /** 
  33. * Init function for the settings of GA 
  34. */ 
  35. public function init_settings() { 
  36. $this->options = $this->get_options(); 
  37.  
  38. try { 
  39. // Loading Google Api Libs with minimal version 2.0. 
  40. new MI_Api_Libs( '2.0' ); 
  41. catch( Exception $exception ) { 
  42. if ( $exception->getMessage() === 'required_version' ) { 
  43. add_action( 'admin_notices', array( $this, 'set_api_libs_error' ) ); 
  44.  
  45. $dashboards = Yoast_GA_Dashboards::get_instance(); 
  46.  
  47. // Listener for reconnecting with google analytics 
  48. $this->google_analytics_listener(); 
  49.  
  50. if ( is_null( $this->get_tracking_code() ) && $this->show_admin_warning() ) { 
  51. add_action( 'admin_notices', array( 'Yoast_Google_Analytics_Notice', 'config_warning' ) ); 
  52.  
  53. // Check if something has went wrong with GA-api calls 
  54. $has_tracking_code = ( ! is_null( $this->get_tracking_code() ) && empty( $this->options['manual_ua_code_field'] ) ); 
  55. if ( $has_tracking_code && $this->show_admin_dashboard_warning() ) { 
  56. Yoast_Google_Analytics::get_instance()->check_for_ga_issues(); 
  57.  
  58.  
  59. if ( $_SERVER['REQUEST_METHOD'] == 'POST' ) { 
  60. $this->handle_ga_post_request( $dashboards ); 
  61.  
  62. /** 
  63. * Show the notifications if we have one 
  64. */ 
  65. $this->show_notification( 'ga_notifications' ); 
  66.  
  67. // Load the Google Analytics Dashboards functionality 
  68. $dashboards->init_dashboards( $this->get_current_profile() ); 
  69.  
  70. /** 
  71. * There is an error with the API libs. So show a notice. 
  72. */ 
  73. public function set_api_libs_error() { 
  74. echo '<div class="error notice"><p>' . __( 'MonsterInsights plugins share some code between them to make your site faster. As a result of that, we need all MonsterInsights plugins to be up to date. We\'ve detected this isn\'t the case, so please update the MonsterInsights plugins that aren\'t up to date yet.', 'google-analytics-for-wordpress' ) . '</p></div>'; 
  75.  
  76. /** 
  77. * This function saves the settings in the option field and returns a wp success message on success 
  78. * @param array $data 
  79. */ 
  80. public function save_settings( $data ) { 
  81.  
  82. unset( $data['google_auth_code'] ); 
  83.  
  84. foreach ( $data as $key => $value ) { 
  85. if ( $key != 'return_tab' ) { 
  86. if ( is_string( $value ) ) { 
  87. if ( $key === 'custom_code' && ! current_user_can( 'unfiltered_html' ) ) { 
  88. continue; 
  89. else { 
  90. $value = strip_tags( $value ); 
  91.  
  92. $this->options[ $key ] = $value; 
  93.  
  94. // Check checkboxes, on a uncheck they won't be posted to this function 
  95. $defaults = $this->default_ga_values(); 
  96. foreach ( $defaults[ $this->option_prefix ] as $option_name => $value ) { 
  97. $this->handle_default_setting( $data, $option_name, $value ); 
  98.  
  99. if ( ! empty( $this->options['analytics_profile'] ) ) { 
  100. $this->options['analytics_profile_code'] = $this->get_ua_code_from_profile( $this->options['analytics_profile'] ); 
  101.  
  102. $this->do_validation( $data['return_tab'] ); 
  103.  
  104. if ( $this->update_option( $this->options ) ) { 
  105. // Success, add a new notification 
  106. $this->add_notification( 'ga_notifications', array( 
  107. 'type' => 'success',  
  108. 'description' => __( 'Settings saved.', 'google-analytics-for-wordpress' ),  
  109. ) ); 
  110. else { 
  111. // Fail, add a new notification 
  112. $this->add_notification( 'ga_notifications', array( 
  113. 'type' => 'error',  
  114. 'description' => __( 'There were no changes to save, please try again.', 'google-analytics-for-wordpress' ),  
  115. ) ); 
  116.  
  117. // redirect 
  118. wp_redirect( admin_url( 'admin.php' ) . '?page=yst_ga_settings#top#' . $data['return_tab'], 301 ); 
  119. exit; 
  120.  
  121. /** 
  122. * Redirect to settings with a validation error if there are validation errors 
  123. * @param string $return_tab The tab to return to when there is a validation error. 
  124. */ 
  125. protected function do_validation( $return_tab ) { 
  126. $validation = $this->validate_settings(); 
  127. if ( is_wp_error( $validation ) ) { 
  128. $this->add_notification( 'ga_notifications', array( 
  129. 'type' => 'error',  
  130. 'description' => $validation->get_error_message(),  
  131. ) ); 
  132.  
  133. wp_redirect( admin_url( 'admin.php' ) . '?page=yst_ga_settings#top#' . $return_tab, 301 ); 
  134. exit; 
  135.  
  136. /** 
  137. * Validates the settings in the `options` attribute, returns an WP_Error object on error 
  138. * @return true|WP_Error true or an error object. 
  139. */ 
  140. protected function validate_settings() { 
  141.  
  142. if ( ! empty( $this->options['manual_ua_code_field'] ) ) { 
  143. $this->options['manual_ua_code_field'] = trim( $this->options['manual_ua_code_field'] ); 
  144. // en dash to minus, prevents issue with code copied from web with "fancy" dash 
  145. $this->options['manual_ua_code_field'] = str_replace( '*', '-', $this->options['manual_ua_code_field'] ); 
  146.  
  147. // Regex to tests if a valid UA code has been set. Valid codes follow: "UA-[4 digits]-[at least 1 digit]". 
  148. if ( ! preg_match( '|^UA-\d{4, }-\d+$|', $this->options['manual_ua_code_field'] ) ) { 
  149.  
  150. return new WP_Error( 
  151. 'ua-code-format',  
  152. __( 'The UA code needs to follow UA-XXXXXXXX-X format.', 'google-analytics-for-wordpress' ) 
  153. ); 
  154.  
  155. /** 
  156. * Filters the validation for the admin options 
  157. * @param true|WP_Error true if the validation is successful, WP_Error on error. 
  158. * @param array $this->options The options that are being saved. 
  159. */ 
  160. return apply_filters( 'yst_ga_admin_validate_settings', true, $this->options ); 
  161.  
  162. /** 
  163. * Run a this deactivation hook on deactivation of GA. When this happens we'll 
  164. * remove the options for the profiles and the refresh token. 
  165. */ 
  166. public static function ga_deactivation_hook() { 
  167. // Remove the refresh token and other API settings 
  168. self::analytics_api_clean_up(); 
  169.  
  170. /** 
  171. * Handle a default setting in GA 
  172. * @param array $data 
  173. * @param string $option_name 
  174. * @param mixed $value 
  175. */ 
  176. private function handle_default_setting( $data, $option_name, $value ) { 
  177. if ( ! isset( $data[ $option_name ] ) ) { 
  178. // If no data was passed in, set it to the default. 
  179. if ( $value === 1 ) { 
  180. // Disable the checkbox for now, use value 0 
  181. $this->options[ $option_name ] = 0; 
  182. else { 
  183. $this->options[ $option_name ] = $value; 
  184.  
  185. /** 
  186. * Handle the post requests in the admin form of the GA plugin 
  187. * @param Yoast_GA_Dashboards $dashboards 
  188. */ 
  189. private function handle_ga_post_request( $dashboards ) { 
  190. if ( ! function_exists( 'wp_verify_nonce' ) ) { 
  191. require_once( ABSPATH . 'wp-includes/pluggable.php' ); 
  192.  
  193. if ( isset( $_POST['ga-form-settings'] ) && wp_verify_nonce( $_POST['yoast_ga_nonce'], 'save_settings' ) ) { 
  194. if ( ! isset ( $_POST['ignore_users'] ) ) { 
  195. $_POST['ignore_users'] = array(); 
  196.  
  197. $dashboards_disabled = Yoast_GA_Settings::get_instance()->dashboards_disabled(); 
  198.  
  199. if ( ( $dashboards_disabled == false && isset( $_POST['dashboards_disabled'] ) ) || $this->ga_profile_changed( $_POST ) ) { 
  200. $dashboards->reset_dashboards_data(); 
  201.  
  202. // Post submitted and verified with our nonce 
  203. $this->save_settings( $_POST ); 
  204.  
  205. /** 
  206. * Is there selected an other property in the settings post? Returns true or false. 
  207. * @param array $post 
  208. * @return bool 
  209. */ 
  210. private function ga_profile_changed( $post ) { 
  211. if ( isset( $post['analytics_profile'] ) && isset( $this->options['analytics_profile'] ) ) { 
  212. if ( $post['analytics_profile'] != $this->options['analytics_profile'] ) { 
  213. return true; 
  214.  
  215. return false; 
  216.  
  217. /** 
  218. * Are we allowed to show a warning message? returns true if it's allowed 
  219. * @return bool 
  220. */ 
  221. private function show_admin_warning() { 
  222. return ( current_user_can( 'manage_options' ) && ( ! isset( $_GET['page'] ) || ( isset( $_GET['page'] ) && $_GET['page'] !== 'yst_ga_settings' ) ) ); 
  223.  
  224. /** 
  225. * Are we allowed to show a warning message? returns true if it's allowed ( this is meant to be only for dashboard ) 
  226. * @return bool 
  227. */ 
  228. private function show_admin_dashboard_warning() { 
  229. return ( current_user_can( 'manage_options' ) && isset( $_GET['page'] ) && $_GET['page'] === 'yst_ga_dashboard' ); 
  230.  
  231. /** 
  232. * Transform the Profile ID into an helpful UA code 
  233. * @param integer $profile_id 
  234. * @return null 
  235. */ 
  236. private function get_ua_code_from_profile( $profile_id ) { 
  237. $profiles = $this->get_profiles(); 
  238. $ua_code = null; 
  239.  
  240. foreach ( $profiles as $account ) { 
  241. foreach ( $account['items'] as $profile ) { 
  242. foreach ( $profile['items'] as $subprofile ) { 
  243. if ( isset( $subprofile['id'] ) && $subprofile['id'] === $profile_id ) { 
  244. return $subprofile['ua_code']; 
  245.  
  246. return $ua_code; 
  247.  
  248. /** 
  249. * Add a link to the settings page to the plugins list 
  250. * @param array $links array of links for the plugins, adapted when the current plugin is found. 
  251. * @return array $links 
  252. */ 
  253. public function add_action_links( $links ) { 
  254. // add link to knowledgebase 
  255. // @todo UTM link fix 
  256. $faq_link = '<a title="MonsterInsights Knowledge Base" href="http://www.monsterinsights.com/docs/">' . __( 'FAQ', 'google-analytics-for-wordpress' ) . '</a>'; 
  257. array_unshift( $links, $faq_link ); 
  258.  
  259. $settings_link = '<a href="' . esc_url( admin_url( 'admin.php?page=yst_ga_settings' ) ) . '">' . __( 'Settings', 'google-analytics-for-wordpress' ) . '</a>'; 
  260. array_unshift( $links, $settings_link ); 
  261.  
  262. return $links; 
  263.  
  264. /** 
  265. * Adds some promo text for the premium plugin on the custom dimensions tab. 
  266. */ 
  267. public function premium_promo() { 
  268. echo '<div class="ga-promote">'; 
  269. echo '<p>'; 
  270. printf( __( 'If you want to track custom dimensions like page views per author or post type, you should upgrade to the %1$spremium version of Google Analytics by MonsterInsights%2$s.', 'google-analytics-for-wordpress' ), '<a href="https://www.monsterinsights.com/pricing/#utm_medium=text-link&utm_source=gawp-config&utm_campaign=wpgaplugin&utm_content=custom_dimensions_tab">', '</a>' ); 
  271. echo ' '; 
  272. _e( 'This will also give you access to the support team at MonsterInsights, who will provide support on the plugin 24/7.', 'google-analytics-for-wordpress' ); 
  273. echo '</p>'; 
  274. echo '</div>'; 
  275.  
  276. /** 
  277. * Load the page of a menu item in the GA plugin 
  278. */ 
  279. public function load_page() { 
  280.  
  281. if ( ! has_action( 'yst_ga_custom_dimensions_tab-content' ) ) { 
  282. add_action( 'yst_ga_custom_dimensions_tab-content', array( $this, 'premium_promo' ) ); 
  283.  
  284. if ( ! has_action( 'yst_ga_custom_dimension_add-dashboards-tab' ) ) { 
  285. add_action( 'yst_ga_custom_dimension_add-dashboards-tab', array( $this, 'premium_promo' ) ); 
  286.  
  287. switch ( filter_input( INPUT_GET, 'page' ) ) { 
  288. case 'yst_ga_settings': 
  289. require_once( $this->plugin_path . 'admin/pages/settings.php' ); 
  290. break; 
  291. case 'yst_ga_extensions': 
  292. require_once( $this->plugin_path . 'admin/pages/extensions.php' ); 
  293. break; 
  294. case 'yst_ga_dashboard': 
  295. default: 
  296. require_once( $this->plugin_path . 'admin/pages/dashboard.php' ); 
  297. break; 
  298.  
  299.  
  300. /** 
  301. * Get the Google Analytics profiles which are in this google account 
  302. * @return array 
  303. */ 
  304. public function get_profiles() { 
  305. $return = Yoast_Google_Analytics::get_instance()->get_profiles(); 
  306.  
  307. return $return; 
  308.  
  309. /** 
  310. * Checks if there is a callback to get token from Google Analytics API 
  311. */ 
  312. private function google_analytics_listener() { 
  313. $google_auth_code = filter_input( INPUT_POST, 'google_auth_code' ); 
  314. if ( $google_auth_code && current_user_can( 'manage_options' ) && wp_verify_nonce( filter_input( INPUT_POST, 'yoast_ga_nonce' ), 'save_settings' ) ) { 
  315. self::analytics_api_clean_up(); 
  316.  
  317. Yoast_Google_Analytics::get_instance()->authenticate( trim( $google_auth_code ) ); 
  318.  
  319. /** 
  320. * Clean up the Analytics API settings 
  321. */ 
  322. public static function analytics_api_clean_up() { 
  323. delete_option( 'yoast-ga-refresh_token' ); 
  324. delete_option( 'yst_ga_api_call_fail' ); 
  325. delete_option( 'yst_ga_last_wp_run' ); 
  326. delete_option( 'yst_ga_api' ); 
  327.  
  328. /** 
  329. * Get the current GA profile 
  330. * @return null 
  331. */ 
  332. private function get_current_profile() { 
  333. if ( ! empty( $this->options['analytics_profile'] ) ) { 
  334. return $this->options['analytics_profile']; 
  335.  
  336. return null; 
  337.  
  338. /** 
  339. * Get the user roles of this WordPress blog 
  340. * @return array 
  341. */ 
  342. public function get_userroles() { 
  343. global $wp_roles; 
  344.  
  345. $all_roles = $wp_roles->roles; 
  346. $roles = array(); 
  347.  
  348. /** 
  349. * Filter: 'editable_roles' - Allows filtering of the roles shown within the plugin (and elsewhere in WP as it's a WP filter) 
  350. * @api array $all_roles 
  351. */ 
  352. $editable_roles = apply_filters( 'editable_roles', $all_roles ); 
  353.  
  354. foreach ( $editable_roles as $id => $name ) { 
  355. $roles[] = array( 
  356. 'id' => $id,  
  357. 'name' => translate_user_role( $name['name'] ),  
  358. ); 
  359.  
  360. return $roles; 
  361.  
  362. /** 
  363. * Get types of how we can track downloads 
  364. * @return array 
  365. */ 
  366. public function track_download_types() { 
  367. return array( 
  368. 0 => array( 'id' => 'event', 'name' => __( 'Event', 'google-analytics-for-wordpress' ) ),  
  369. 1 => array( 'id' => 'pageview', 'name' => __( 'Pageview', 'google-analytics-for-wordpress' ) ),  
  370. ); 
  371.  
  372. /** 
  373. * Get options for the track full url or links setting 
  374. * @return array 
  375. */ 
  376. public function get_track_full_url() { 
  377. return array( 
  378. 0 => array( 'id' => 'domain', 'name' => __( 'Just the domain', 'google-analytics-for-wordpress' ) ),  
  379. 1 => array( 'id' => 'full_links', 'name' => __( 'Full links', 'google-analytics-for-wordpress' ) ),  
  380. ); 
  381.  
  382. /** 
  383. * Render the admin page head for the GA Plugin 
  384. */ 
  385. public function content_head() { 
  386. require 'views/content_head.php'; 
  387.  
  388. /** 
  389. * Output System Info file 
  390. */ 
  391. public function system_info() { 
  392. if ( ! empty( $_REQUEST['monsterinsights-action'] ) && $_REQUEST['monsterinsights-action'] === 'download_sysinfo' ) { 
  393. if ( ! current_user_can( 'manage_options' ) ) { 
  394. return; 
  395. nocache_headers(); 
  396. header( 'Content-Type: text/plain' ); 
  397. header( 'Content-Disposition: attachment; filename="monsterinsights-system-info.txt"' ); 
  398. echo wp_strip_all_tags( $_POST['monsterinsights-sysinfo'] ); 
  399. die(); 
  400.  
  401. /** 
  402. * Render the admin page footer with sidebar for the GA Plugin 
  403. */ 
  404. public function content_footer() { 
  405.  
  406. do_action( 'yoast_ga_admin_footer' ); 
  407.  
  408. if ( class_exists( 'MI_Product_GA_Premium' ) ) { 
  409. $license_manager = new MI_Plugin_License_Manager( new MI_Product_GA_Premium() ); 
  410. if ( $license_manager->license_is_valid() ) { 
  411. return; 
  412.  
  413. $banners = array(); 
  414. $banners[] = array( 
  415. 'url' => 'https://optinmonster.com/?utm_source=monsterinsights-config&utm_medium=banner&utm_campaign=gaplugin',  
  416. 'banner' => $this->plugin_url . 'assets/img/omupsell.png',  
  417. 'title' => 'Convert Visitors into Subscribers',  
  418. ); 
  419. $banners[] = array( 
  420. 'url' => 'https://www.monsterinsights.com/pricing/?utm_source=monsterinsights-config&utm_medium=banner&utm_campaign=gaplugin',  
  421. 'banner' => $this->plugin_url . 'assets/img/upgradetopro.png',  
  422. 'title' => 'Get the premium version of Google Analytics by MonsterInsights!',  
  423. ); 
  424. $banners[] = array( 
  425. 'url' => 'http://www.wpbeginner.net/?utm_source=monsterinsights-config&utm_medium=banner&utm_campaign=gaplugin',  
  426. 'banner' => $this->plugin_url . 'assets/img/wpbeginnerupsell.png',  
  427. 'title' => 'The best collection of free beginner WordPress resources!',  
  428. ); 
  429. $banners[] = array( 
  430. 'url' => 'https://wpforms.com/pricing/?utm_source=monsterinsights-config&utm_medium=banner&utm_campaign=gaplugin',  
  431. 'banner' => $this->plugin_url . 'assets/img/wpformsupsell.png',  
  432. 'title' => 'Get the most beginner friendly WordPress contact form plugin in the market!',  
  433. ); 
  434.  
  435. shuffle( $banners ); 
  436.  
  437. require 'views/content-footer.php'; 
  438.  
  439.  
  440. /** 
  441. * Returns a list of all available extensions 
  442. * @return array 
  443. */ 
  444. public function get_extensions() { 
  445. $extensions = array( 
  446. 'ga_premium' => (object) array( 
  447. 'url' => 'https://www.monsterinsights.com/pricing/',  
  448. 'title' => __( 'Google Analytics by MonsterInsights Pro', 'google-analytics-for-wordpress' ),  
  449. 'desc' => __( 'The premium version of Google Analytics by MonsterInsights with more features and support.', 'google-analytics-for-wordpress' ),  
  450. 'status' => 'uninstalled',  
  451. ),  
  452. 'ecommerce' => (object) array( 
  453. 'url' => 'https://www.monsterinsights.com/pricing/',  
  454. 'title' => __( 'Google Analytics by MonsterInsights', 'google-analytics-for-wordpress' ) . '<br />' . __( 'eCommerce tracking', 'google-analytics-for-wordpress' ),  
  455. 'desc' => __( 'Track your eCommerce data and transactions with this eCommerce extension for Google Analytics.', 'google-analytics-for-wordpress' ),  
  456. 'status' => 'uninstalled',  
  457. ),  
  458. ); 
  459.  
  460. $extensions = apply_filters( 'yst_ga_extension_status', $extensions ); 
  461.  
  462. return $extensions; 
  463.  
  464. /** 
  465. * Add a notification to the notification transient 
  466. * @param string $transient_name 
  467. * @param array $settings 
  468. */ 
  469. private function add_notification( $transient_name, $settings ) { 
  470. set_transient( $transient_name, $settings, MINUTE_IN_SECONDS ); 
  471.  
  472. /** 
  473. * Show the notification that should be set, after showing the notification this function unset the transient 
  474. * @param string $transient_name The name of the transient which contains the notification 
  475. */ 
  476. public function show_notification( $transient_name ) { 
  477. $transient = get_transient( $transient_name ); 
  478.  
  479. if ( isset( $transient['type'] ) && isset( $transient['description'] ) ) { 
  480. if ( $transient['type'] == 'success' ) { 
  481. add_settings_error( 
  482. 'yoast_google_analytics',  
  483. 'yoast_google_analytics',  
  484. $transient['description'],  
  485. 'updated' 
  486. ); 
  487. else { 
  488. add_settings_error( 
  489. 'yoast_google_analytics',  
  490. 'yoast_google_analytics',  
  491. $transient['description'],  
  492. 'error' 
  493. ); 
  494.  
  495. delete_transient( $transient_name ); 
  496.  
  497. /** 
  498. * Check if there the aggregate data cron is executed 
  499. * @return bool 
  500. */ 
  501. private function is_running_cron() { 
  502. return doing_action( 'yst_ga_aggregate_data' ) && defined( 'DOING_CRON' ) && DOING_CRON; 
  503.  
  504. /** 
  505. * Check if there the aggregate data cron is executed 
  506. * @return bool 
  507. */ 
  508. private function is_running_ajax() { 
  509. return defined( 'DOING_AJAX' ) && DOING_AJAX && strpos( filter_input( INPUT_GET, 'action' ), 'yoast_dashboard' ) === 0; 
  510.