/inc/sitemaps/class-author-sitemap-provider.php

  1. <?php 
  2. /** 
  3. * @package WPSEO\XML_Sitemaps 
  4. */ 
  5.  
  6. /** 
  7. * Sitemap provider for author archives. 
  8. */ 
  9. class WPSEO_Author_Sitemap_Provider implements WPSEO_Sitemap_Provider { 
  10.  
  11. /** 
  12. * Check if provider supports given item type. 
  13. * 
  14. * @param string $type Type string to check for. 
  15. * 
  16. * @return boolean 
  17. */ 
  18. public function handles_type( $type ) { 
  19.  
  20. return $type === 'author'; 
  21.  
  22. /** 
  23. * @param int $max_entries Entries per sitemap. 
  24. * 
  25. * @return array 
  26. */ 
  27. public function get_index_links( $max_entries ) { 
  28.  
  29. $options = WPSEO_Options::get_all(); 
  30.  
  31. if ( $options['disable-author'] || $options['disable_author_sitemap'] ) { 
  32. return array(); 
  33.  
  34. // TODO Consider doing this less often / when necessary. R. 
  35. $this->update_user_meta(); 
  36.  
  37. $has_exclude_filter = has_filter( 'wpseo_sitemap_exclude_author' ); 
  38.  
  39. $query_arguments = array(); 
  40.  
  41. if ( ! $has_exclude_filter ) { // We only need full users if legacy filter(s) hooked to exclusion logic. R. 
  42. $query_arguments['fields'] = 'ID'; 
  43.  
  44. $users = $this->get_users( $query_arguments ); 
  45.  
  46. if ( $has_exclude_filter ) { 
  47. $users = $this->exclude_users( $users ); 
  48. $users = wp_list_pluck( $users, 'ID' ); 
  49.  
  50. if ( empty( $users ) ) { 
  51. return array(); 
  52.  
  53. $index = array(); 
  54. $page = 1; 
  55. $user_pages = array_chunk( $users, $max_entries ); 
  56.  
  57. if ( count( $user_pages ) === 1 ) { 
  58. $page = ''; 
  59.  
  60. foreach ( $user_pages as $users_page ) { 
  61.  
  62. $user_id = array_shift( $users_page ); // Time descending, first user on page is most recently updated. 
  63. $user = get_user_by( 'id', $user_id ); 
  64. $index[] = array( 
  65. 'loc' => WPSEO_Sitemaps_Router::get_base_url( 'author-sitemap' . $page . '.xml' ),  
  66. 'lastmod' => '@' . $user->_yoast_wpseo_profile_updated, // @ for explicit timestamp format 
  67. ); 
  68.  
  69. $page++; 
  70.  
  71. return $index; 
  72.  
  73. /** 
  74. * Retrieve users, taking account of all necessary exclusions. 
  75. * 
  76. * @param array $arguments Arguments to add. 
  77. * 
  78. * @return array 
  79. */ 
  80. protected function get_users( $arguments = array() ) { 
  81.  
  82. global $wpdb; 
  83.  
  84. $options = WPSEO_Options::get_all(); 
  85.  
  86. $defaults = array( 
  87. // TODO re-enable after plugin requirements raised to WP 4.6 with the fix. 
  88. // 'who' => 'authors', Breaks meta keys, see https://core.trac.wordpress.org/ticket/36724#ticket R. 
  89. 'meta_key' => '_yoast_wpseo_profile_updated',  
  90. 'orderby' => 'meta_value_num',  
  91. 'order' => 'DESC',  
  92. 'meta_query' => array( 
  93. 'relation' => 'AND',  
  94. array( 
  95. 'key' => $wpdb->get_blog_prefix() . 'user_level',  
  96. 'value' => '0',  
  97. 'compare' => '!=',  
  98. ),  
  99. array( 
  100. 'relation' => 'OR',  
  101. array( 
  102. 'key' => 'wpseo_excludeauthorsitemap',  
  103. 'value' => 'on',  
  104. 'compare' => '!=',  
  105. ),  
  106. array( 
  107. 'key' => 'wpseo_excludeauthorsitemap',  
  108. 'compare' => 'NOT EXISTS',  
  109. ),  
  110. ),  
  111. ),  
  112. ); 
  113.  
  114. if ( $options['disable_author_noposts'] === true ) { 
  115. // $defaults['who'] = ''; // Otherwise it cancels out next argument. 
  116. $defaults['has_published_posts'] = true; 
  117.  
  118. $excluded_roles = $this->get_excluded_roles(); 
  119.  
  120. if ( ! empty( $excluded_roles ) ) { 
  121. // $defaults['who'] = ''; // Otherwise it cancels out next argument. 
  122. $defaults['role__not_in'] = $excluded_roles; 
  123.  
  124. return get_users( array_merge( $defaults, $arguments ) ); 
  125.  
  126. /** 
  127. * Retrieve array of roles, excluded in settings. 
  128. * 
  129. * @return array 
  130. */ 
  131. protected function get_excluded_roles() { 
  132.  
  133. static $excluded_roles; 
  134.  
  135. if ( isset( $excluded_roles ) ) { 
  136. return $excluded_roles; 
  137.  
  138. $options = WPSEO_Options::get_all(); 
  139. $roles = WPSEO_Utils::get_roles(); 
  140.  
  141. foreach ( $roles as $role_slug => $role_name ) { 
  142.  
  143. if ( ! empty( $options[ "user_role-{$role_slug}-not_in_sitemap" ] ) ) { 
  144. $excluded_roles[] = $role_name; 
  145.  
  146. if ( ! empty( $excluded_roles ) ) { // Otherwise it's handled by who=>authors query. 
  147. $excluded_roles[] = 'Subscriber'; 
  148.  
  149. return $excluded_roles; 
  150.  
  151. /** 
  152. * Get set of sitemap link data. 
  153. * 
  154. * @param string $type Sitemap type. 
  155. * @param int $max_entries Entries per sitemap. 
  156. * @param int $current_page Current page of the sitemap. 
  157. * 
  158. * @return array 
  159. */ 
  160. public function get_sitemap_links( $type, $max_entries, $current_page ) { 
  161.  
  162. $options = WPSEO_Options::get_all(); 
  163.  
  164. $links = array(); 
  165.  
  166. if ( $options['disable-author'] === true || $options['disable_author_sitemap'] === true ) { 
  167. return $links; 
  168.  
  169. $users = $this->get_users( array( 
  170. 'offset' => ( $current_page - 1 ) * $max_entries,  
  171. 'number' => $max_entries,  
  172. ) ); 
  173.  
  174. $users = $this->exclude_users( $users ); 
  175.  
  176. if ( empty( $users ) ) { 
  177. $users = array(); 
  178.  
  179. $time = time(); 
  180.  
  181. foreach ( $users as $user ) { 
  182.  
  183. $author_link = get_author_posts_url( $user->ID ); 
  184.  
  185. if ( empty( $author_link ) ) { 
  186. continue; 
  187.  
  188. $mod = $time; 
  189.  
  190. if ( isset( $user->_yoast_wpseo_profile_updated ) ) { 
  191. $mod = $user->_yoast_wpseo_profile_updated; 
  192.  
  193. $url = array( 
  194. 'loc' => $author_link,  
  195. 'mod' => date( DATE_W3C, $mod ),  
  196.  
  197. // Deprecated, kept for backwards data compat. R. 
  198. 'chf' => 'daily',  
  199. 'pri' => 1,  
  200. ); 
  201.  
  202. /** This filter is documented at inc/sitemaps/class-post-type-sitemap-provider.php */ 
  203. $url = apply_filters( 'wpseo_sitemap_entry', $url, 'user', $user ); 
  204.  
  205. if ( ! empty( $url ) ) { 
  206. $links[] = $url; 
  207.  
  208. return $links; 
  209.  
  210. /** 
  211. * Update any users that don't have last profile update timestamp. 
  212. * 
  213. * @return int Count of users updated. 
  214. */ 
  215. protected function update_user_meta() { 
  216.  
  217. $users = get_users( array( 
  218. 'who' => 'authors',  
  219. 'meta_query' => array( 
  220. array( 
  221. 'key' => '_yoast_wpseo_profile_updated',  
  222. 'compare' => 'NOT EXISTS',  
  223. ),  
  224. ),  
  225. ) ); 
  226.  
  227. $time = time(); 
  228.  
  229. foreach ( $users as $user ) { 
  230. update_user_meta( $user->ID, '_yoast_wpseo_profile_updated', $time ); 
  231.  
  232. return count( $users ); 
  233.  
  234. /** 
  235. * Wrap legacy filter to deduplicate calls. 
  236. * 
  237. * @param array $users Array of user objects to filter. 
  238. * 
  239. * @return array 
  240. */ 
  241. protected function exclude_users( $users ) { 
  242.  
  243. /** 
  244. * Filter the authors, included in XML sitemap. 
  245. * 
  246. * @param array $users Array of user objects to filter. 
  247. */ 
  248. return apply_filters( 'wpseo_sitemap_exclude_author', $users ); 
  249.  
  250. /** 
  251. * Sorts an array of WP_User by the _yoast_wpseo_profile_updated meta field. 
  252. * 
  253. * @since 1.6 
  254. * 
  255. * @deprecated 3.3 User meta sort can now be done by queries. 
  256. * 
  257. * @param WP_User $first The first WP user. 
  258. * @param WP_User $second The second WP user. 
  259. * 
  260. * @return int 0 if equal, 1 if $a is larger else or -1; 
  261. */ 
  262. public function user_map_sorter( $first, $second ) { 
  263. _deprecated_function( __METHOD__, 'WPSEO 3.3', __( 'Use queries instead', 'wordpress-seo' ) ); 
  264.  
  265. if ( ! isset( $first->_yoast_wpseo_profile_updated ) ) { 
  266. $first->_yoast_wpseo_profile_updated = time(); 
  267.  
  268. if ( ! isset( $second->_yoast_wpseo_profile_updated ) ) { 
  269. $second->_yoast_wpseo_profile_updated = time(); 
  270.  
  271. if ( $first->_yoast_wpseo_profile_updated === $second->_yoast_wpseo_profile_updated ) { 
  272. return 0; 
  273.  
  274. return ( ( $first->_yoast_wpseo_profile_updated > $second->_yoast_wpseo_profile_updated ) ? 1 : -1 ); 
.