123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330 |
- <?php
- /**
- * WPSEO plugin file.
- *
- * @package WPSEO\XML_Sitemaps
- */
- /**
- * Sitemap provider for author archives.
- */
- class WPSEO_Taxonomy_Sitemap_Provider implements WPSEO_Sitemap_Provider {
- /**
- * Holds image parser instance.
- *
- * @var WPSEO_Sitemap_Image_Parser
- */
- protected static $image_parser;
- /**
- * Determines whether images should be included in the XML sitemap.
- *
- * @var bool
- */
- private $include_images;
- /**
- * Set up object properties for data reuse.
- */
- public function __construct() {
- /**
- * Filter - Allows excluding images from the XML sitemap.
- *
- * @param bool unsigned True to include, false to exclude.
- */
- $this->include_images = apply_filters( 'wpseo_xml_sitemap_include_images', true );
- }
- /**
- * Check if provider supports given item type.
- *
- * @param string $type Type string to check for.
- *
- * @return boolean
- */
- public function handles_type( $type ) {
- $taxonomy = get_taxonomy( $type );
- if ( $taxonomy === false || ! $this->is_valid_taxonomy( $taxonomy->name ) || ! $taxonomy->public ) {
- return false;
- }
- return true;
- }
- /**
- * Retrieves the links for the sitemap.
- *
- * @param int $max_entries Entries per sitemap.
- *
- * @return array
- */
- public function get_index_links( $max_entries ) {
- $taxonomies = get_taxonomies( [ 'public' => true ], 'objects' );
- if ( empty( $taxonomies ) ) {
- return [];
- }
- $taxonomy_names = array_filter( array_keys( $taxonomies ), [ $this, 'is_valid_taxonomy' ] );
- $taxonomies = array_intersect_key( $taxonomies, array_flip( $taxonomy_names ) );
- // Retrieve all the taxonomies and their terms so we can do a proper count on them.
- /**
- * Filter the setting of excluding empty terms from the XML sitemap.
- *
- * @param boolean $exclude Defaults to true.
- * @param array $taxonomy_names Array of names for the taxonomies being processed.
- */
- $hide_empty = apply_filters( 'wpseo_sitemap_exclude_empty_terms', true, $taxonomy_names );
- $all_taxonomies = [];
- foreach ( $taxonomy_names as $taxonomy_name ) {
- /**
- * Filter the setting of excluding empty terms from the XML sitemap for a specific taxonomy.
- *
- * @param boolean $exclude Defaults to the sitewide setting.
- * @param string $taxonomy_name The name of the taxonomy being processed.
- */
- $hide_empty_tax = apply_filters( 'wpseo_sitemap_exclude_empty_terms_taxonomy', $hide_empty, $taxonomy_name );
- $term_args = [
- 'hide_empty' => $hide_empty_tax,
- 'fields' => 'ids',
- ];
- $taxonomy_terms = get_terms( $taxonomy_name, $term_args );
- if ( count( $taxonomy_terms ) > 0 ) {
- $all_taxonomies[ $taxonomy_name ] = $taxonomy_terms;
- }
- }
- $index = [];
- foreach ( $taxonomies as $tax_name => $tax ) {
- if ( ! isset( $all_taxonomies[ $tax_name ] ) ) { // No eligible terms found.
- continue;
- }
- $total_count = ( isset( $all_taxonomies[ $tax_name ] ) ) ? count( $all_taxonomies[ $tax_name ] ) : 1;
- $max_pages = 1;
- if ( $total_count > $max_entries ) {
- $max_pages = (int) ceil( $total_count / $max_entries );
- }
- $last_modified_gmt = WPSEO_Sitemaps::get_last_modified_gmt( $tax->object_type );
- for ( $page_counter = 0; $page_counter < $max_pages; $page_counter++ ) {
- $current_page = ( $max_pages > 1 ) ? ( $page_counter + 1 ) : '';
- if ( ! is_array( $tax->object_type ) || count( $tax->object_type ) === 0 ) {
- continue;
- }
- $terms = array_splice( $all_taxonomies[ $tax_name ], 0, $max_entries );
- if ( ! $terms ) {
- continue;
- }
- $args = [
- 'post_type' => $tax->object_type,
- 'tax_query' => [
- [
- 'taxonomy' => $tax_name,
- 'terms' => $terms,
- ],
- ],
- 'orderby' => 'modified',
- 'order' => 'DESC',
- 'posts_per_page' => 1,
- ];
- $query = new WP_Query( $args );
- if ( $query->have_posts() ) {
- $date = $query->posts[0]->post_modified_gmt;
- }
- else {
- $date = $last_modified_gmt;
- }
- $index[] = [
- 'loc' => WPSEO_Sitemaps_Router::get_base_url( $tax_name . '-sitemap' . $current_page . '.xml' ),
- 'lastmod' => $date,
- ];
- }
- }
- return $index;
- }
- /**
- * Get set of sitemap link data.
- *
- * @param string $type Sitemap type.
- * @param int $max_entries Entries per sitemap.
- * @param int $current_page Current page of the sitemap.
- *
- * @throws OutOfBoundsException When an invalid page is requested.
- *
- * @return array
- */
- public function get_sitemap_links( $type, $max_entries, $current_page ) {
- global $wpdb;
- $links = [];
- if ( ! $this->handles_type( $type ) ) {
- return $links;
- }
- $taxonomy = get_taxonomy( $type );
- $steps = $max_entries;
- $offset = ( $current_page > 1 ) ? ( ( $current_page - 1 ) * $max_entries ) : 0;
- /** This filter is documented in inc/sitemaps/class-taxonomy-sitemap-provider.php */
- $hide_empty = apply_filters( 'wpseo_sitemap_exclude_empty_terms', true, [ $taxonomy->name ] );
- /** This filter is documented in inc/sitemaps/class-taxonomy-sitemap-provider.php */
- $hide_empty_tax = apply_filters( 'wpseo_sitemap_exclude_empty_terms_taxonomy', $hide_empty, $taxonomy->name );
- $terms = get_terms( $taxonomy->name, [ 'hide_empty' => $hide_empty_tax ] );
- // If the total term count is lower than the offset, we are on an invalid page.
- if ( count( $terms ) < $offset ) {
- throw new OutOfBoundsException( 'Invalid sitemap page requested' );
- }
- $terms = array_splice( $terms, $offset, $steps );
- if ( empty( $terms ) ) {
- return $links;
- }
- $post_statuses = array_map( 'esc_sql', WPSEO_Sitemaps::get_post_statuses() );
- // Grab last modified date.
- $sql = "
- SELECT MAX(p.post_modified_gmt) AS lastmod
- FROM $wpdb->posts AS p
- INNER JOIN $wpdb->term_relationships AS term_rel
- ON term_rel.object_id = p.ID
- INNER JOIN $wpdb->term_taxonomy AS term_tax
- ON term_tax.term_taxonomy_id = term_rel.term_taxonomy_id
- AND term_tax.taxonomy = %s
- AND term_tax.term_id = %d
- WHERE p.post_status IN ('" . implode( "','", $post_statuses ) . "')
- AND p.post_password = ''
- ";
- /**
- * Filter: 'wpseo_exclude_from_sitemap_by_term_ids' - Allow excluding terms by ID.
- *
- * @api array $terms_to_exclude The terms to exclude.
- */
- $terms_to_exclude = apply_filters( 'wpseo_exclude_from_sitemap_by_term_ids', [] );
- foreach ( $terms as $term ) {
- if ( in_array( $term->term_id, $terms_to_exclude, true ) ) {
- continue;
- }
- $url = [];
- $tax_noindex = WPSEO_Taxonomy_Meta::get_term_meta( $term, $term->taxonomy, 'noindex' );
- if ( $tax_noindex === 'noindex' ) {
- continue;
- }
- $url['loc'] = WPSEO_Taxonomy_Meta::get_term_meta( $term, $term->taxonomy, 'canonical' );
- if ( ! is_string( $url['loc'] ) || $url['loc'] === '' ) {
- $url['loc'] = get_term_link( $term, $term->taxonomy );
- }
- $url['mod'] = $wpdb->get_var( $wpdb->prepare( $sql, $term->taxonomy, $term->term_id ) );
- if ( $this->include_images ) {
- $url['images'] = $this->get_image_parser()->get_term_images( $term );
- }
- // Deprecated, kept for backwards data compat. R.
- $url['chf'] = 'daily';
- $url['pri'] = 1;
- /** This filter is documented at inc/sitemaps/class-post-type-sitemap-provider.php */
- $url = apply_filters( 'wpseo_sitemap_entry', $url, 'term', $term );
- if ( ! empty( $url ) ) {
- $links[] = $url;
- }
- }
- return $links;
- }
- /**
- * Check if taxonomy by name is valid to appear in sitemaps.
- *
- * @param string $taxonomy_name Taxonomy name to check.
- *
- * @return bool
- */
- public function is_valid_taxonomy( $taxonomy_name ) {
- if ( WPSEO_Options::get( "noindex-tax-{$taxonomy_name}" ) === true ) {
- return false;
- }
- if ( in_array( $taxonomy_name, [ 'link_category', 'nav_menu' ], true ) ) {
- return false;
- }
- if ( 'post_format' === $taxonomy_name && WPSEO_Options::get( 'disable-post_format', false ) ) {
- return false;
- }
- /**
- * Filter to exclude the taxonomy from the XML sitemap.
- *
- * @param boolean $exclude Defaults to false.
- * @param string $taxonomy_name Name of the taxonomy to exclude..
- */
- if ( apply_filters( 'wpseo_sitemap_exclude_taxonomy', false, $taxonomy_name ) ) {
- return false;
- }
- return true;
- }
- /**
- * Get the Image Parser.
- *
- * @return WPSEO_Sitemap_Image_Parser
- */
- protected function get_image_parser() {
- if ( ! isset( self::$image_parser ) ) {
- self::$image_parser = new WPSEO_Sitemap_Image_Parser();
- }
- return self::$image_parser;
- }
- /* ********************* DEPRECATED METHODS ********************* */
- /**
- * Get all the options.
- *
- * @deprecated 7.0
- * @codeCoverageIgnore
- */
- protected function get_options() {
- _deprecated_function( __METHOD__, 'WPSEO 7.0', 'WPSEO_Options::get' );
- }
- }
|