class-taxonomy-sitemap-provider.php 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. <?php
  2. /**
  3. * WPSEO plugin file.
  4. *
  5. * @package WPSEO\XML_Sitemaps
  6. */
  7. /**
  8. * Sitemap provider for author archives.
  9. */
  10. class WPSEO_Taxonomy_Sitemap_Provider implements WPSEO_Sitemap_Provider {
  11. /** @var WPSEO_Sitemap_Image_Parser $image_parser Holds image parser instance. */
  12. protected static $image_parser;
  13. /**
  14. * Check if provider supports given item type.
  15. *
  16. * @param string $type Type string to check for.
  17. *
  18. * @return boolean
  19. */
  20. public function handles_type( $type ) {
  21. return taxonomy_exists( $type );
  22. }
  23. /**
  24. * Get all the options
  25. *
  26. * @deprecated 7.0
  27. */
  28. protected function get_options() {
  29. _deprecated_function( __METHOD__, 'WPSEO 7.0', 'WPSEO_Options::get' );
  30. }
  31. /**
  32. * @param int $max_entries Entries per sitemap.
  33. *
  34. * @return array
  35. */
  36. public function get_index_links( $max_entries ) {
  37. $taxonomies = get_taxonomies( array( 'public' => true ), 'objects' );
  38. if ( empty( $taxonomies ) ) {
  39. return array();
  40. }
  41. $taxonomy_names = array_filter( array_keys( $taxonomies ), array( $this, 'is_valid_taxonomy' ) );
  42. $taxonomies = array_intersect_key( $taxonomies, array_flip( $taxonomy_names ) );
  43. // Retrieve all the taxonomies and their terms so we can do a proper count on them.
  44. /**
  45. * Filter the setting of excluding empty terms from the XML sitemap.
  46. *
  47. * @param boolean $exclude Defaults to true.
  48. * @param array $taxonomy_names Array of names for the taxonomies being processed.
  49. */
  50. $hide_empty = apply_filters( 'wpseo_sitemap_exclude_empty_terms', true, $taxonomy_names );
  51. $all_taxonomies = array();
  52. foreach ( $taxonomy_names as $taxonomy_name ) {
  53. $taxonomy_terms = get_terms( $taxonomy_name, array(
  54. 'hide_empty' => $hide_empty,
  55. 'fields' => 'ids',
  56. ) );
  57. if ( count( $taxonomy_terms ) > 0 ) {
  58. $all_taxonomies[ $taxonomy_name ] = $taxonomy_terms;
  59. }
  60. }
  61. $index = array();
  62. foreach ( $taxonomies as $tax_name => $tax ) {
  63. if ( ! isset( $all_taxonomies[ $tax_name ] ) ) { // No eligible terms found.
  64. continue;
  65. }
  66. $total_count = ( isset( $all_taxonomies[ $tax_name ] ) ) ? count( $all_taxonomies[ $tax_name ] ) : 1;
  67. $max_pages = 1;
  68. if ( $total_count > $max_entries ) {
  69. $max_pages = (int) ceil( $total_count / $max_entries );
  70. }
  71. $last_modified_gmt = WPSEO_Sitemaps::get_last_modified_gmt( $tax->object_type );
  72. for ( $page_counter = 0; $page_counter < $max_pages; $page_counter++ ) {
  73. $current_page = ( $max_pages > 1 ) ? ( $page_counter + 1 ) : '';
  74. if ( ! is_array( $tax->object_type ) || count( $tax->object_type ) === 0 ) {
  75. continue;
  76. }
  77. $terms = array_splice( $all_taxonomies[ $tax_name ], 0, $max_entries );
  78. if ( ! $terms ) {
  79. continue;
  80. }
  81. $args = array(
  82. 'post_type' => $tax->object_type,
  83. 'tax_query' => array(
  84. array(
  85. 'taxonomy' => $tax_name,
  86. 'terms' => $terms,
  87. ),
  88. ),
  89. 'orderby' => 'modified',
  90. 'order' => 'DESC',
  91. 'posts_per_page' => 1,
  92. );
  93. $query = new WP_Query( $args );
  94. if ( $query->have_posts() ) {
  95. $date = $query->posts[0]->post_modified_gmt;
  96. }
  97. else {
  98. $date = $last_modified_gmt;
  99. }
  100. $index[] = array(
  101. 'loc' => WPSEO_Sitemaps_Router::get_base_url( $tax_name . '-sitemap' . $current_page . '.xml' ),
  102. 'lastmod' => $date,
  103. );
  104. }
  105. }
  106. return $index;
  107. }
  108. /**
  109. * Get set of sitemap link data.
  110. *
  111. * @param string $type Sitemap type.
  112. * @param int $max_entries Entries per sitemap.
  113. * @param int $current_page Current page of the sitemap.
  114. *
  115. * @return array
  116. */
  117. public function get_sitemap_links( $type, $max_entries, $current_page ) {
  118. global $wpdb;
  119. $links = array();
  120. $taxonomy = get_taxonomy( $type );
  121. if ( $taxonomy === false || ! $this->is_valid_taxonomy( $taxonomy->name ) || ! $taxonomy->public ) {
  122. return $links;
  123. }
  124. $steps = $max_entries;
  125. $offset = ( $current_page > 1 ) ? ( ( $current_page - 1 ) * $max_entries ) : 0;
  126. /** This filter is documented in inc/sitemaps/class-taxonomy-sitemap-provider.php */
  127. $hide_empty = apply_filters( 'wpseo_sitemap_exclude_empty_terms', true, array( $taxonomy->name ) );
  128. $terms = get_terms( $taxonomy->name, array( 'hide_empty' => $hide_empty ) );
  129. $terms = array_splice( $terms, $offset, $steps );
  130. if ( empty( $terms ) ) {
  131. $terms = array();
  132. }
  133. // Grab last modified date.
  134. $sql = "
  135. SELECT MAX(p.post_modified_gmt) AS lastmod
  136. FROM $wpdb->posts AS p
  137. INNER JOIN $wpdb->term_relationships AS term_rel
  138. ON term_rel.object_id = p.ID
  139. INNER JOIN $wpdb->term_taxonomy AS term_tax
  140. ON term_tax.term_taxonomy_id = term_rel.term_taxonomy_id
  141. AND term_tax.taxonomy = %s
  142. AND term_tax.term_id = %d
  143. WHERE p.post_status IN ('publish','inherit')
  144. AND p.post_password = ''
  145. ";
  146. foreach ( $terms as $term ) {
  147. $url = array();
  148. $tax_noindex = WPSEO_Taxonomy_Meta::get_term_meta( $term, $term->taxonomy, 'noindex' );
  149. if ( $tax_noindex === 'noindex' ) {
  150. continue;
  151. }
  152. $url['loc'] = WPSEO_Taxonomy_Meta::get_term_meta( $term, $term->taxonomy, 'canonical' );
  153. if ( ! is_string( $url['loc'] ) || $url['loc'] === '' ) {
  154. $url['loc'] = get_term_link( $term, $term->taxonomy );
  155. }
  156. $url['mod'] = $wpdb->get_var( $wpdb->prepare( $sql, $term->taxonomy, $term->term_id ) );
  157. $url['images'] = $this->get_image_parser()->get_term_images( $term );
  158. // Deprecated, kept for backwards data compat. R.
  159. $url['chf'] = 'daily';
  160. $url['pri'] = 1;
  161. /** This filter is documented at inc/sitemaps/class-post-type-sitemap-provider.php */
  162. $url = apply_filters( 'wpseo_sitemap_entry', $url, 'term', $term );
  163. if ( ! empty( $url ) ) {
  164. $links[] = $url;
  165. }
  166. }
  167. return $links;
  168. }
  169. /**
  170. * Check if taxonomy by name is valid to appear in sitemaps.
  171. *
  172. * @param string $taxonomy_name Taxonomy name to check.
  173. *
  174. * @return bool
  175. */
  176. public function is_valid_taxonomy( $taxonomy_name ) {
  177. if ( WPSEO_Options::get( "noindex-tax-{$taxonomy_name}" ) === true ) {
  178. return false;
  179. }
  180. if ( in_array( $taxonomy_name, array( 'link_category', 'nav_menu' ), true ) ) {
  181. return false;
  182. }
  183. if ( 'post_format' === $taxonomy_name && WPSEO_Options::get( 'disable-post_format', false ) ) {
  184. return false;
  185. }
  186. /**
  187. * Filter to exclude the taxonomy from the XML sitemap.
  188. *
  189. * @param boolean $exclude Defaults to false.
  190. * @param string $taxonomy_name Name of the taxonomy to exclude..
  191. */
  192. if ( apply_filters( 'wpseo_sitemap_exclude_taxonomy', false, $taxonomy_name ) ) {
  193. return false;
  194. }
  195. return true;
  196. }
  197. /**
  198. * Get the Image Parser
  199. *
  200. * @return WPSEO_Sitemap_Image_Parser
  201. */
  202. protected function get_image_parser() {
  203. if ( ! isset( self::$image_parser ) ) {
  204. self::$image_parser = new WPSEO_Sitemap_Image_Parser();
  205. }
  206. return self::$image_parser;
  207. }
  208. }