How do I: display network posts, ordered by site?

I'm converting a Drupal site to WordPress. One of the most crucial features is best seen by looking at the current homepage:

http://cityofsanctuary.org/

If you scroll down to the heading "What’s happening around the country?" in the right hand column, you'll see I'm displaying a list of recent "posts" from various "sites". That list is displaying things as follows (using WP terminology):

1. Show all Posts from across the Network, created in the last 3 months, most recent first;
2. Group them by Site, where the Site heading links to that Site;
3. Don't show more than 2 Posts per Site.
4. Exclude some types/categories of Sites from the display.

This has been working well for the community, as they're encouraged to create Posts often to keep their Site's presence on the home page. They're also rewarded for adding Featured Images, as their Posts are more visible. And no Site can flood the listing as only the most recent two Posts from any Site is shown.

And it's my job to recreate this with WordPress :slight_smile:

I've had a play with your Site Categories plugin. It's not providing the front-end interface I want, as we only have 3 or 4 parent categories of site, but perhaps it'll be a good way of categorising our Sites (currently I'm categorising with a Theme Setting).

I've also tried your Recent Network Posts plugin. It doesn't come very near to the functionality I want out of the box. If it made it possible to show the Site name, along with the Title and Excerpt, that might be useable, but would still be a big compromise on what we're currently doing.

So I'm guessing I'm going to need to write a custom query to leverage Post Indexer to get what we need. Problem is I might need a bit of hand-holding with that, as my PHP/MySQL foo is not very advanced.

Do you think there are any obvious solutions I'm missing? And if not, and you think a custom-built thing using Post Indexer is the best way forward, would you be prepared to hold my hand a bit as I try to work out the Post Indexer API and WP custom queries?

Cheers :slight_smile:
M.

  • Patrick

    Hi there @Mina

    Welcome to WPMU DEV, glad to have you aboard!

    There's a bunch of useful information in this thread for creating a custom network query, leveraging the power of the Post Indexer plugin, to help you get the custom display you're after:
    https://premium.wpmudev.org/forums/topic/how-to-add-global-marketpress-products-to-a-site-loop?replies=11#post-629747

    Please let us know if this helps, and don't hesitate to post again for more hand-holding. :slight_smile:

  • Mina

    Thanks, Patrick. I did spot that post yesterday, and did a little playing around. However, I think I found a simpler way to get me started, using built-in WordPress functions.

    It seems WP keeps the wp_blogs table updated with a last_updated record every time a site is updated, and provides the get_last_updated() function to return an array of sites, in order of most recently updated.

    So I wrote a function to get the 10 most recently updated sites, and then to loop through those, "become" each site in turn (with switch_to_blog()), and then just use a normal get_posts() to return the two most recent posts for that site.

    This could be database intensive as I imagine I'm firing off at least 11 database queries (1 for the sites, and 10 for the individual sites' posts). But it's working well enough that I can demo to the client, and I can look at maybe using transients to cache the array the function returns.

    I guess I could use Post Indexer (or query its table directly) in future, but I suspect that would need just as many DB queries (I'd get the list of posts in one go, but then have to fire off queries for each post to get its site details). Either that, or I'd need to use SQL joins which are beyond me right now.

    Just in case it's helpful for others, here's the function I've written to solve this problem (so far without any caching - so it comes with a performance warning):

    function cofs_get_network_latest() {
    	$blogs = get_last_updated(' ', 0, 10); // gets the last 10 updated blogs
    	$output = array();
    	foreach ($blogs as $blog) {
    		$id = $blog['blog_id'];
    		// $output[$id]['test_key'] = 'test string';
    		// $output[$id]['test_key_2'] = 'second test string';
    		switch_to_blog($id);
    
    		$theme_mods = get_theme_mods();
    		$output[$id]['shortname'] = $theme_mods['shortname'];
    		$output[$id]['site_name'] = get_bloginfo('name');
    		$output[$id]['site_url'] = get_bloginfo('url').'/';
    
    		$args = array(
    			'posts_per_page'   => 2,
    			'post_type'        => 'post'
    		);
    		$posts = get_posts($args);
    		foreach ($posts as $post) {
    			$excerpt = cofs_trim_excerpt($post->post_content);
    			$post = (array) $post;
    			$post['post_excerpt'] = $excerpt;
    			if (has_post_thumbnail($post->ID)) {
    				$thumb = get_the_post_thumbnail( $post->ID );
    				$post['thumb'] = $thumb;
    			}
    			$output[$id]['posts'][] = $post;
    		}
    
    		restore_current_blog();
    	}
    	return $output;
    }

    * cofs_trim_excerpt() is my own small function for getting the excerpt in this situation, as it can't be depended on being set explicitly, and this function is creating an array which can be used "outside the loop" where the_excerpt() won't work.

    ** Also worth noting, I've been using theme customisation settings for categorising sites - because the category has an affect on that site's branding/logo, and because it seems to make sense from a UI perspective to put category info in the same place as site title, tagline, etc. With this function, as I'm "becoming" each site in turn, I can easily grab its theme settings as I go, extract that info, and store it in the array along with the other data. Hence use of get_theme_mods().

Thank NAME, for their help.

Let NAME know exactly why they deserved these points.

Gift a custom amount of points.