How To List All Posts Of An Archive, A Category Or A Search Result

Archive pages are usually paged according to your settings in options/reading. Sometimes you may want to offer a page with all posts for an archive (time, category, search result).

You need:

  • a separate address for the unpaged archive,
  • a filter for the internal WordPress query and
  • a link to your ‘all posts’ page.

We put everything into a class to avoid name collisions and to keep the global namespace clean.
We name the file class.View_All_Posts.php.

Let’s start with the class, the parameter and a checker, this is easy:

class View_All_Posts
{
    /**
     * GET parameter to trigger a complete, not paged archive.
     * @var string
     */
    protected $all_param = 'all';

    /**
     * Are we there already?
     *
     * @return bool
     */
    public function is_all_posts()
    {
        return isset ( $_GET[$this->all_param] );
    }
}

For the address I use a very simple approach: a GET parameter named all. You may change the name here; just stay with ASCII chars from a—z. все_сообщения will get you in trouble!

Next we need a constructor that manages our work:

    public function __construct()
    {
        /* Register the query argument. */
        add_filter('query_vars', array ( $this, 'add_query_arg') );

        /* Hook into the query. */
        add_action('pre_get_posts', array ( $this, 'view_all_posts') );
    }

The constructor references two internal functions – add_query_arg() and view_all_posts(), which we build next:

    /**
     * Registers the query arg in WordPress.
     * Otherwise it will be unset.
     *
     * @param  array $vars Already registered query args.
     * @return array
     */
    public function add_query_arg( array $vars )
    {
        return array_merge( $vars, array ( $this->query_arg ) );
    }

    /**
     * Alters the query to remove the paging.
     * @return void
     */
    public function view_all_posts()
    {
        if ( ! $this->is_all_posts() )
        {
            return;
        }

        $GLOBALS['wp_query']->query_vars['nopaging'] = TRUE;

        return;
    }

The first function just registers our GET parameter in WordPress. The second alters the query to the database and removes the paging.

We are almost done. A template tag for the link would be nice, wouldn’t it?

    /**
     * Creates the markup for the link.
     *
     * Usage in archive.php, category.php or search.php:
     * $GLOBALS['view_all_posts']->get_allposts_link();
     *
     * @param  string $text Linktext
     * @param  bool   $print echo or return
     * @return string|void
     */
    public function get_allposts_link(
        $text   = 'View all posts'
    ,   $before = '<p class="allpostslink">'
    ,   $after  = '</p>;'
    ,   $print  = TRUE
    )
    {
        if ( $this->is_all_posts()
         or $GLOBALS['wp_query']->found_posts <= get_option('posts_per_page')
        )
        {   // No link needed.
            return;
        }

        if ( isset ( $_SERVER['QUERY_STRING'] )
            && ! empty ( $_SERVER['QUERY_STRING'] )
        )
        {
            /* We have already visible GET parameters: /?hello=world. */
            $new_url = $_SERVER['REQUEST_URI'] . '&';
        }
        else
        {
            /* Note the difference: REQUEST_URL doesn't include
             * the query string while REQUEST_URI does. */
            $new_url = $_SERVER['REQUEST_URL'] . '?';
        }

        $link = "$before<a href='$new_url$this->all_param'>$text</a>$after";

        if ( $print )
        {
            print $link;
            return;
        }
        return $link;
    }

Note: $GLOBALS['wp_query']->found_posts holds the sum of all posts for a given query, not just for the current page. Useful if you want to print out the total number on a paged archive.

If you want to avoid duplicate content, hide the full archives from search engines in your header:

    /**
     * Prevents indexing from search engines.
     *
     * Add this as an action to 'wp_head'.
     *
     * @return void
     */
    public function meta_noindex()
    {
        if ( $this->is_all_posts() )
        {
             print '<meta name="robots" content="noindex">';
        }
    }

Our class is complete. Now we put an object of the class into the global namespace …

$GLOBALS['view_all_posts'] = new View_All_Posts;

… add an action to wp_head

add_action(
    'wp_head'
,   array ( $GLOBALS['view_all_posts'], 'meta_noindex' )
);

… and include the file into the functions.php of our theme:

require_once dirname(__FILE__) . DIRECTORY_SEPARATOR
    . 'class.View_All_Posts.php';

In our archive templates (archive.php, category.php, search.php) we print the link:

$GLOBALS['view_all_posts']->get_allposts_link();

Done.

Oh, wait … maybe you want to see the full code? And a download link?

Here’s the link: Download class.View_All_Posts.php

The complete code:

/**
 * Adds a view all posts page to any query.
 * @author Thomas Scholz http://toscho.de
 * @version 1.1
 */
class View_All_Posts
{
    /**
     * GET parameter to trigger a complete, not paged archive.
     * @var string
     */
    protected $all_param = 'all';

    public function __construct()
    {
        /* Register the query argument. */
        add_filter('query_vars', array ( $this, 'add_query_arg') );

        /* Hook into the query. */
        add_action('pre_get_posts', array ( $this, 'view_all_posts') );
    }

    /**
     * Registers the query arg in WordPress.
     * Otherwise it will be unset.
     *
     * @param  array $vars Already registered query args.
     * @return array
     */
    public function add_query_arg( array $vars )
    {
        return array_merge( $vars, array ( $this->query_arg ) );
    }

    /**
     * Alters the query to remove the paging.
     * @return void
     */
    public function view_all_posts()
    {
        if ( ! $this->is_all_posts() )
        {
            return;
        }

        $GLOBALS['wp_query']->query_vars['nopaging'] = TRUE;

        return;
    }

    /**
     * Are we there already?
     *
     * @return bool
     */
    public function is_all_posts()
    {
        return isset ( $_GET[$this->all_param] );
    }

    /**
     * Creates the markup for the link.
     *
     * Usage in archive.php, category.php or search.php:
     * $GLOBALS['view_all_posts']->get_allposts_link();
     *
     * @param  string $text Linktext
     * @param  bool   $print echo or return
     * @return string|void
     */
    public function get_allposts_link(
        $text   = 'View all posts'
    ,   $before = '<p class="allpostslink">'
    ,   $after  = '</p>'
    ,   $print  = TRUE
    )
    {
        if ( $this->is_all_posts()
        or $GLOBALS['wp_query']->found_posts <= get_option('posts_per_page')
        )
        {   // No link needed.
            return;
        }

        if ( isset ( $_SERVER['QUERY_STRING'] )
            && ! empty ( $_SERVER['QUERY_STRING'] )
        )
        {
            /* We have already visible GET parameters: /?hello=world. */
            $new_url = $_SERVER['REQUEST_URI'] . '&';
        }
        else
        {
            /* Note the difference: REQUEST_URL doesn't include
             * the query string while REQUEST_URI does. */
            $new_url = $_SERVER['REQUEST_URL'] . '?';
        }

         $link = "$before<a href='$new_url$this->all_param'>$text</a>$after";

        if ( $print )
        {
            print $link;
            return;
        }
        return $link;
    }
}

$GLOBALS['view_all_posts'] = new View_All_Posts;

Mission completed. Any suggestions?

Guest Post

Thomas ScholzThis post is written by Thomas Scholz toscho.de, a good friend of us and a web designer from Halle, Germany.

Thank you very much from our part to Thomas.

WordPress Plugin Development: Style Your Message Boxes

Displaying a message to the user after he started an action belongs to a good usability. In the era of Web 2.0 applications, the user is expecting such optical signal after his actions. Also WordPress Plugin developer should give the user a result message, if necessary, provided with further information.

The WordPress admin area often likes to show information at the top of the window. For developers, this has a great benefit: Tools for generating the error and information messages are integrated and can easily be implemented in Plugins - without any self-definitions or changes in the style sheet.

Automatically generated information in WordPress

wp_safe_redirect(
  add_query_arg(
    'updated',
    'true',
    wp_get_referer()
  )
);

Manual and more flexible solution to output a message box

<div id="message" class="updated">
  <p>
    Output
  </p>
</div>

Colorful: The availability of CSS classes

Messages within an application have to communicate different informations. For this purpose WordPress has numerous stylesheet classes available, which suits best to the message.

<div id="message" class="updated">...</div>

<div id="message" class="error">...</div>

<div id="message" class="updated highlight">...</div>

<div id="message" class="updated below-h2">...</div>

Recommendation

Don't use your own format. A common and familiar message box provides trust and increases the potential of perception.

Guest Post

This post is written by Sergej Müller wpseo.org, who created the popular WordPress Plugin to optimize your SEO.

Thank you very much from our part to Sergej.

If you also like to have your interesting post published on our website, please let us know on our contact page. Of course we will appreciate your contribution!

WordPress: Useful Default Configuration Settings Via Plugin

Everybody who installs WordPress quite often knows the problem: You always have to do the same adjustments, for example deleting the Hello World post. That cost time and money. Our friend Thomas Scholz alias toscho had a simple but genius idea, he puts all needed option settings in a Plugin. Just activate the Plugin, deactivate it and delete it. Done!

You can adjust and expand the options as you like. A good overview is the wp-admin/options.php.

<?php
/*
Plugin Name: Toscho's basic settings
Plugin URI: http://toscho.de/2010/wordpress-grundeinstellungen-per-plugin-setzen/
Description: Some useful default configuration settings. See 'wp-admin/options.php' for more options.
Version: 0.2
Author: Thomas Scholz
Author URI: http://toscho.de
*/

function set_toscho_defaults()
{
    $o = array(
        'avatar_default'            => 'blank',
        'avatar_rating'             => 'G',
        'category_base'             => '/thema',
        'comment_max_links'         => 0,
        'comments_per_page'         => 0,
        'date_format'               => 'd.m.Y',
        'default_ping_status'       => 'closed',
        'default_post_edit_rows'    => 30,
        'links_updated_date_format' => 'j. F Y, H:i',
        'permalink_structure'       => '/%year%/%postname%/',
        'rss_language'              => 'de',
        'timezone_string'           => 'Etc/GMT-1',
        'use_smilies'               => 0,
    );

    foreach ( $o as $k => $v )
    {
        update_option($k, $v);
    }

    // Delete dummy post and comment.
    wp_delete_post(1, TRUE);
    wp_delete_comment(1);

    return;
}
register_activation_hook(__FILE__, 'set_toscho_defaults');
?>

Here you can download the Plugin by toscho.