class-gsc.php 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. <?php
  2. /**
  3. * WPSEO plugin file.
  4. *
  5. * @package WPSEO\admin\google_search_console
  6. */
  7. /**
  8. * Class WPSEO_GSC
  9. */
  10. class WPSEO_GSC {
  11. /**
  12. * The option where data will be stored
  13. */
  14. const OPTION_WPSEO_GSC = 'wpseo-gsc';
  15. /**
  16. * @var WPSEO_GSC_Service
  17. */
  18. private $service;
  19. /**
  20. * @var WPSEO_GSC_Category_Filters
  21. */
  22. protected $category_filter;
  23. /**
  24. * @var WPSEO_GSC_Issues
  25. */
  26. protected $issue_fetch;
  27. /**
  28. * @var string current platform
  29. */
  30. private $platform;
  31. /**
  32. * @var string current category
  33. */
  34. private $category;
  35. /**
  36. * Constructor for the page class. This will initialize all GSC related stuff
  37. */
  38. public function __construct() {
  39. add_action( 'init', array( $this, 'init' ) );
  40. }
  41. /**
  42. * Run init logic.
  43. */
  44. public function init() {
  45. // Setting the screen option.
  46. if ( filter_input( INPUT_GET, 'page' ) === 'wpseo_search_console' ) {
  47. if ( filter_input( INPUT_GET, 'tab' ) !== 'settings' && WPSEO_GSC_Settings::get_profile() === '' ) {
  48. wp_redirect( add_query_arg( 'tab', 'settings' ) );
  49. exit;
  50. }
  51. $this->set_hooks();
  52. $this->set_dependencies();
  53. $this->request_handler();
  54. }
  55. add_action( 'admin_init', array( $this, 'register_gsc_notification' ) );
  56. add_action( 'admin_init', array( $this, 'register_settings' ) );
  57. }
  58. /**
  59. * If the Google Search Console has no credentials, add a notification for the user to give him a heads up. This message is dismissable.
  60. */
  61. public function register_gsc_notification() {
  62. $notification = $this->get_profile_notification();
  63. $notification_center = Yoast_Notification_Center::get();
  64. if ( WPSEO_GSC_Settings::get_profile() === '' ) {
  65. $notification_center->add_notification( $notification );
  66. }
  67. else {
  68. $notification_center->remove_notification( $notification );
  69. }
  70. }
  71. /**
  72. * Builds the notification used when GSC is not connected to a profile
  73. *
  74. * @return Yoast_Notification
  75. */
  76. private function get_profile_notification() {
  77. return new Yoast_Notification(
  78. sprintf(
  79. /* translators: 1: link open tag; 2: link close tag. */
  80. __( 'Don\'t miss your crawl errors: %1$sconnect with Google Search Console here%2$s.', 'wordpress-seo' ),
  81. '<a href="' . admin_url( 'admin.php?page=wpseo_search_console&tab=settings' ) . '">',
  82. '</a>'
  83. ),
  84. array(
  85. 'type' => Yoast_Notification::WARNING,
  86. 'id' => 'wpseo-dismiss-gsc',
  87. 'capabilities' => 'wpseo_manage_options',
  88. )
  89. );
  90. }
  91. /**
  92. * Be sure the settings will be registered, so data can be stored
  93. */
  94. public function register_settings() {
  95. register_setting( 'yoast_wpseo_gsc_options', self::OPTION_WPSEO_GSC );
  96. }
  97. /**
  98. * Function that outputs the redirect page
  99. */
  100. public function display() {
  101. require_once WPSEO_PATH . 'admin/google_search_console/views/gsc-display.php';
  102. }
  103. /**
  104. * Display the table
  105. */
  106. public function display_table() {
  107. // The list table.
  108. $list_table = new WPSEO_GSC_Table( $this->platform, $this->category, $this->issue_fetch->get_issues() );
  109. // Adding filter to display the category filters.
  110. add_filter( 'views_' . $list_table->get_screen_id(), array( $this->category_filter, 'as_array' ) );
  111. // Preparing and displaying the table.
  112. $list_table->prepare_items();
  113. $list_table->search_box( __( 'Search', 'wordpress-seo' ), 'wpseo-crawl-issues-search' );
  114. $list_table->display();
  115. }
  116. /**
  117. * Load the admin redirects scripts
  118. */
  119. public function page_scripts() {
  120. $asset_manager = new WPSEO_Admin_Asset_Manager();
  121. $asset_manager->enqueue_script( 'admin-gsc' );
  122. $asset_manager->enqueue_style( 'metabox-css' );
  123. add_screen_option( 'per_page', array(
  124. 'label' => __( 'Crawl errors per page', 'wordpress-seo' ),
  125. 'default' => 50,
  126. 'option' => 'errors_per_page',
  127. ) );
  128. }
  129. /**
  130. * Set the screen options
  131. *
  132. * @param string $status Status string.
  133. * @param string $option Option key.
  134. * @param string $value Value to return.
  135. *
  136. * @return mixed
  137. */
  138. public function set_screen_option( $status, $option, $value ) {
  139. if ( 'errors_per_page' === $option ) {
  140. return $value;
  141. }
  142. }
  143. /**
  144. * Setting the hooks to be load on page request
  145. */
  146. private function set_hooks() {
  147. add_action( 'admin_enqueue_scripts', array( $this, 'page_scripts' ) );
  148. add_filter( 'set-screen-option', array( $this, 'set_screen_option' ), 11, 3 );
  149. }
  150. /**
  151. * Handles the POST and GET requests
  152. */
  153. private function request_handler() {
  154. // List the table search post to a get.
  155. $this->list_table_search_post_to_get();
  156. // Catch the authorization code POST.
  157. $this->catch_authentication_post();
  158. // Is there a reset post than we will remove the posts and data.
  159. if ( filter_input( INPUT_GET, 'gsc_reset' ) ) {
  160. // Clear the google data.
  161. WPSEO_GSC_Settings::clear_data( $this->service );
  162. // Adding notification to the notification center.
  163. /* Translators: %1$s: expands to Google Search Console. */
  164. $this->add_notification( sprintf( __( 'The %1$s data has been removed. You will have to reauthenticate if you want to retrieve the data again.', 'wordpress-seo' ), 'Google Search Console' ), Yoast_Notification::UPDATED );
  165. // Directly output the notifications.
  166. wp_redirect( remove_query_arg( 'gsc_reset' ) );
  167. exit;
  168. }
  169. // Reloads al the issues.
  170. if ( wp_verify_nonce( filter_input( INPUT_POST, 'reload-crawl-issues-nonce' ), 'reload-crawl-issues' ) && filter_input( INPUT_POST, 'reload-crawl-issues' ) ) {
  171. // Reloading all the issues.
  172. WPSEO_GSC_Settings::reload_issues();
  173. // Adding the notification.
  174. $this->add_notification( __( 'The issues have been successfully reloaded!', 'wordpress-seo' ), Yoast_Notification::UPDATED );
  175. // Directly output the notifications.
  176. Yoast_Notification_Center::get()->display_notifications();
  177. }
  178. // Catch bulk action request.
  179. new WPSEO_GSC_Bulk_Action();
  180. }
  181. /**
  182. * Catch the redirects search post and redirect it to a search get
  183. */
  184. private function list_table_search_post_to_get() {
  185. $search_string = filter_input( INPUT_POST, 's' );
  186. if ( $search_string === null ) {
  187. return;
  188. }
  189. // When there is nothing being search and there is no search param in the url, break this method.
  190. if ( $search_string === '' && filter_input( INPUT_GET, 's' ) === null ) {
  191. return;
  192. }
  193. $url = ( $search_string !== '' ) ? add_query_arg( 's', $search_string ) : remove_query_arg( 's' );
  194. // Do the redirect.
  195. wp_redirect( $url );
  196. exit;
  197. }
  198. /**
  199. * Catch the authentication post
  200. */
  201. private function catch_authentication_post() {
  202. $gsc_values = filter_input( INPUT_POST, 'gsc', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY );
  203. // Catch the authorization code POST.
  204. if ( ! empty( $gsc_values['authorization_code'] ) && wp_verify_nonce( $gsc_values['gsc_nonce'], 'wpseo-gsc_nonce' ) ) {
  205. if ( ! WPSEO_GSC_Settings::validate_authorization( trim( $gsc_values['authorization_code'] ), $this->service->get_client() ) ) {
  206. $this->add_notification( __( 'Incorrect Google Authorization Code.', 'wordpress-seo' ), Yoast_Notification::ERROR );
  207. }
  208. // Redirect user to prevent a post resubmission which causes an oauth error.
  209. wp_redirect( admin_url( 'admin.php' ) . '?page=' . esc_attr( filter_input( INPUT_GET, 'page' ) ) . '&tab=settings' );
  210. exit;
  211. }
  212. }
  213. /**
  214. * Adding notification to the yoast notification center
  215. *
  216. * @param string $message Message string.
  217. * @param string $type Message type.
  218. */
  219. private function add_notification( $message, $type ) {
  220. Yoast_Notification_Center::get()->add_notification(
  221. new Yoast_Notification( $message, array( 'type' => $type ) )
  222. );
  223. }
  224. /**
  225. * Setting dependencies which will be used one this page
  226. */
  227. private function set_dependencies() {
  228. // Setting the service object.
  229. $this->service = new WPSEO_GSC_Service( WPSEO_GSC_Settings::get_profile() );
  230. // Setting the platform.
  231. $this->platform = WPSEO_GSC_Mapper::get_current_platform( 'tab' );
  232. // Loading the issue counter.
  233. $issue_count = new WPSEO_GSC_Count( $this->service );
  234. $issue_count->fetch_counts();
  235. // Loading the category filters.
  236. $this->category_filter = new WPSEO_GSC_Category_Filters( $issue_count->get_platform_counts( $this->platform ) );
  237. // Setting the current category.
  238. $this->category = $this->category_filter->get_category();
  239. // Listing the issues.
  240. $issue_count->list_issues( $this->platform, $this->category );
  241. // Fetching the issues.
  242. $this->issue_fetch = new WPSEO_GSC_Issues( $this->platform, $this->category, $issue_count->get_issues() );
  243. }
  244. /**
  245. * Setting the tab help on top of the screen
  246. */
  247. public function set_help() {
  248. $screen = get_current_screen();
  249. $screen->add_help_tab(
  250. array(
  251. 'id' => 'basic-help',
  252. 'title' => __( 'Issue categories', 'wordpress-seo' ),
  253. 'content' => '<p><strong>' . __( 'Desktop', 'wordpress-seo' ) . '</strong><br />' . __( 'Errors that occurred when your site was crawled by Googlebot.', 'wordpress-seo' ) . '</p>'
  254. . '<p><strong>' . __( 'Smartphone', 'wordpress-seo' ) . '</strong><br />' . __( 'Errors that occurred only when your site was crawled by Googlebot-Mobile (errors didn\'t appear for desktop).', 'wordpress-seo' ) . '</p>'
  255. . '<p><strong>' . __( 'Feature phone', 'wordpress-seo' ) . '</strong><br />' . __( 'Errors that only occurred when your site was crawled by Googlebot for feature phones (errors didn\'t appear for desktop).', 'wordpress-seo' ) . '</p>',
  256. )
  257. );
  258. }
  259. }