0

I have updated to Wordpress 5.5 and want to remove Yoast from the install as its pretty much only used for sitemaps, however need to create a couple of custom sitemaps based on different post types, which I am currently doing with Yoast.

I am adding a custom provider as seen below which overrides both needed abstract functions. Both of these are working and the new entry is being added to the sitemap index at wp-sitemap.xml

However when clicking on /wp-sitemap-range-1.xml I get resolved with the latest blog post on the site instead of the expected site map with the three post types together.

I cannot find any documentation in the Wordpress API spec or codex yet so am at a bit of a loss at the moment - Any help is appreciated. A link with an example working provider would also be appreciated, as I have searched far to try and find something with no luck.

My next steps to to check all the 404 handlers and rewrite handlers in my theme to see if anything is sending it to the wrong place. I have much more complex sitemaps to produce, but want this one simple aggregation of the three post types to work first.

<?php
//Add provider for post types 'cast', 'keg', 'cider' to create a sitemap called 'range'
add_action('init', function() {
  $rangeProvider = new key_sitemapProvider('range', array('cask', 'keg', 'cider'));
  wp_register_sitemap_provider('pmrs-range', $rangeProvider);
});
​
/*---------------------*/
class key_sitemapProvider extends WP_Sitemaps_Provider {  
  public $postTypes = array();
​
  /*---------------------*/
  public function __construct($name, $postTypes) {
    $this->name        = $name;
    $this->postTypes   = $postTypes;    
    $this->object_type = 'post';
  }
​
  /*---------------------*/
  private function queryArgs(){
    return array(
      'post_type'      => $this->postTypes, 
      'post_status'    => 'publish',
      'posts_per_page' => -1,
      'orderby'        => 'post_date',
      'order'          => 'DESC'
    );
  }
​
  /*--OVERRIDE-----------*/
  public function get_url_list($page_num, $post_type = '') {
    $query = new WP_Query($this->queryArgs());
    $urlList = array();     
​
    foreach($query->posts as $post) {
      $sitemapEntry = array(
        'chf' => 'weekly',
        'pri' => 1.0,
        'loc' => get_permalink($post),
        'mod' => get_the_modified_time('Y-m-d H:i:s', $post)
      );
      
      $sitemapEntry = apply_filters('wp_sitemaps_posts_entry', $sitemapEntry, $post, $post_type);
      $urlList[] = $sitemapEntry;
    }
​
    return $urlList;
  }
​
  /*--OVERRIDE-----------*/
  public function get_max_num_pages($post_type = '') {    
    return 1;
  }
  
  /*---------------------*/
}
​

SOLUTION

Thanks to Matt Jaworski's answer below found a way to get this to work, with couple other issues.

  • Name property of your WP_Sitemaps_Provider extension needs to match the name you are registering with Wordpress. Also this should not contain any special chars
  • Supported values in the sitemap entries are : changefreq, priority, loc, and lastmod. This is opposed to the shortened version I had before.

Working Example

/*---------------------*/
add_action('init', function() {
  $rangeProvider = new key_sitemapProvidor('range', array('cask', 'keg', 'cider'));
  wp_register_sitemap_provider('range', $rangeProvider);
});

/*---------------------*/
class key_sitemapProvidor extends WP_Sitemaps_Provider {  
  public $postTypes = array();

  /*---------------------*/
  public function __construct($name, $postTypes) {
    $this->name        = $name;
    $this->postTypes   = $postTypes;    
    $this->object_type = 'post';
  }

  /*---------------------*/
  private function queryArgs(){
    return array(
      'post_type'      => $this->postTypes, 
      'post_status'    => 'publish',
      'posts_per_page' => -1,
      'orderby'        => 'post_date',
      'order'          => 'DESC'
    );
  }

  /*--OVERRIDE-----------*/
  public function get_url_list($page_num, $post_type = '') {
    $query = new WP_Query($this->queryArgs());
    $urlList = array();     

    foreach($query->posts as $post) {
      $sitemapEntry = array(
        'changefreq' => 'weekly',
        'priority' => 1.0,
        'loc' => get_permalink($post),
        'lastmod' => get_the_modified_time('Y-m-d H:i:s', $post)
      );
      
      $sitemapEntry = apply_filters('wp_sitemaps_posts_entry', $sitemapEntry, $post, $post_type);
      $urlList[] = $sitemapEntry;
    }

    return $urlList;
  }

  /*--OVERRIDE-----------*/
  public function get_max_num_pages($post_type = '') {    
    return 1;
  }
  
  /*---------------------*/
}
Captain Wizard
  • 331
  • 2
  • 9

1 Answers1

2

I had the same issue, and docs simply don't exist.

Through several trials and errors I figured out most likely WordPress does not like any special chars inside the names.

In my case replacing community-posts with communityposts helped.

Here's the very rough (but working) proof of concept we are working on now:

class PeepSo3_Sitemap_Provider extends WP_Sitemaps_Provider {
        
    private $limit = 10; // @TODO CONFIGURABLE

    public function __construct() {
        $this->name        = 'communityposts';
        $this->object_type = 'communityposts';
    }

    private function sql($page_num) {

        $sql =""; // your queries here;

        return $wpdb->get_results($sql);
    }

    // retrieve a page of results
    public function get_url_list( $page_num, $object_subtype = '' ) {

        $url_list = [];


        $posts = $this->sql($page_num);

        foreach($posts as $post)  {
            $url_list[] = ['loc' => $post->url; // depends on your item structure
        }

        return $url_list;
    }

    // estimate how many pages are available
    public function get_max_num_pages( $object_subtype = '' ) {
        $posts = $this->sql(-1);
        return ceil($posts[0]->count_posts/$this->limit);
    }
}

// Register XML Sitemap Provider
add_filter('init', function() {
    $provider = new PeepSo3_Sitemap_Provider();
    wp_register_sitemap_provider( 'communityposts', $provider );
});
  • Cheers Matt, I'll give that ta try and let you know if it works – Captain Wizard Oct 16 '20 at 08:32
  • I just updated my reply with some sample code. Our stuff does not use WP_Query, but you should be fine adjusting it. – Matt Jaworski Oct 17 '20 at 09:40
  • Cheers for the code Matt. I'll take a look over the next few days, if you have it working with this code, then I'm fairly confident I can tweak it to get it working. I'll let you know how I get on and accept your answer :-) – Captain Wizard Oct 19 '20 at 19:05
  • Quick question. I already have several existing my-custom-sitemap1.xml, my-custom-sitemap2.xml, etc files and I was trying to determine how/where in the above code I would simply put each of my custom sitemap entries into the main wp-sitemap.xml top level sitemap? Really appreciate the help! – l_r Apr 20 '21 at 11:46