Shoora
4/22/2019 - 10:12 AM

A comprehensive sitemap generation for WordPress.

A comprehensive sitemap generation for WordPress.

<?php

/**
 * Suggested default use:
 * add_action("publish_post", "wp_build_sitemap");
 * add_action("publish_page", "wp_build_sitemap");
 * add_action( "save_post", "wp_build_sitemap" );
 *
 * or manually with arguments: wp_build_sitemap( array('priority' => 1) );
 *
 * Build a complete sitemap including
 * all public post types, archive pages, terms and author pages
 */
function wp_build_sitemap($args = array()) {

    // get the options or set to default values
    $changeFreq = isset( $args['changefreq'] ) ? $args['changefreq'] : 'Daily';
    $priority = isset( $args['priority'] ) ? $args['priority'] : '0.8';
    $today = date( 'Y-m-d\TH:i:s+00:00' );

    // get all public post types
    // see: https://codex.wordpress.org/Function_Reference/get_post_types
    $post_types = get_post_types(array(
        'public' => true
    ), 'objects');

    // get all posts ordered by
    // descrending last modification date
    // // see: https://codex.wordpress.org/Function_Reference/get_posts
    $posts = get_posts(array(
        'numberposts' => -1,
        'post_type'   => array_keys($post_types),
        'orderby'     => 'modified',
        'order'       => 'DESC'
    ));

    // get all public taxonomies
    // see: https://codex.wordpress.org/Function_Reference/get_taxonomies
    $taxonomies = get_taxonomies(array(
        'public' => true
    ));

    // get all terms in public taxonomies
    // see: https://developer.wordpress.org/reference/functions/get_terms/
    $terms = get_terms(array(
        'taxonomy' => array_keys($taxonomies)
    ));

    // get all author users (user level greater than 0)
    // see: https://codex.wordpress.org/Function_Reference/get_users
    $users = get_users(array(
        // 'role' => '?',
        'orderby' => 'post_count',
        'order' => 'DESC',
        'who' => 'authors'
    ));

    // sitemap header
    $sitemap = '<?xml version="1.0" encoding="UTF-8"?>' . '<?xml-stylesheet type="text/xsl" href="' . esc_url( home_url( '/' ) ) . 'sitemap.xsl"?>' . "\n";

    // init urlset tag
    $sitemap .= '<urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' . "\n";

    // add home page location
    // with maximum priority by default
    $sitemap .= "\t" . '<url>' . "\n" .
        "\t\t" . '<loc>' . esc_url( home_url( '/' ) ) . '</loc>' .
        "\n\t\t" . '<lastmod>' . $today . '</lastmod>' .
        "\n\t\t" . '<changefreq>Daily</changefreq>' .
        "\n\t\t" . '<priority>1.0</priority>' .
        "\n\t" . '</url>' . "\n";

    // add all pages for public post types
    foreach( $posts as $post ) {

        $sitemap .= "\t" . '<url>' . "\n" .
            "\t\t" . '<loc>' . get_permalink( $post->ID ) . '</loc>' .
            "\n\t\t" . '<lastmod>' . date( 'Y-m-d\TH:i:s+00:00', strtotime($post->post_modified) ) . '</lastmod>' .
            "\n\t\t" . '<changefreq>' . $changeFreq . '</changefreq>' .
            "\n\t\t" . '<priority>' . $priority .'</priority>' .
            "\n\t" . '</url>' . "\n";

    }

    // add archive pages
    foreach ( $post_types as $post_type ) {

        if( $post_type->has_archive ) {

            $sitemap .= "\t" . '<url>' . "\n" .
                "\t\t" . '<loc>' . get_post_type_archive_link($post_type->name) . '</loc>' .
                "\n\t\t" . '<lastmod>' . $today . '</lastmod>' .
                "\n\t\t" . '<changefreq>' . $changeFreq . '</changefreq>' .
                "\n\t\t" . '<priority>' . $priority .'</priority>' .
                "\n\t" . '</url>' . "\n";

        }

    }

    // add public terms pages
    foreach ( $terms as $term ) {

        $sitemap .= "\t" . '<url>' . "\n" .
            "\t\t" . '<loc>' . get_term_link($term->term_id) . '</loc>' .
            "\n\t\t" . '<lastmod>' . $today . '</lastmod>' .
            "\n\t\t" . '<changefreq>' . $changeFreq . '</changefreq>' .
            "\n\t\t" . '<priority>' . $priority .'</priority>' .
            "\n\t" . '</url>' . "\n";

    }

    // finally add author pages
    foreach ( $users as $user ) {

        $sitemap .= "\t" . '<url>' . "\n" .
            "\t\t" . '<loc>' . get_author_posts_url( $user->ID ) . '</loc>' .
            "\n\t\t" . '<lastmod>' . $today . '</lastmod>' .
            "\n\t\t" . '<changefreq>' . $changeFreq . '</changefreq>' .
            "\n\t\t" . '<priority>' . $priority .'</priority>' .
            "\n\t" . '</url>' . "\n";

    }

    $sitemap .= '</urlset>';

    // write the sitemap to the site root
    $fp = fopen( ABSPATH . 'sitemap.xml', 'w' );
    fwrite( $fp, $sitemap );
    fclose( $fp );

}