Using WordPress, MultiSite, P2 and More

Expanding on this tweet.

My department at work has been using WordPress with the P2 theme for discussion recently. It has helped manage stop bulky reply-all emails between the 4 of us.

Besides limiting email, it’s encouraged more discussion. Before, we knew email was annoying, so we limited what we contributed, and certain things went unsaid – and some discussions were never even started. But now we can quickly comment on posts, even if it’s just “+1,” and start new topics on a whim.

We really like what P2 has done for us, so we decided that this would be great to use with the entire office. And not just for general discussion, but for planning bigger projects, keeping track of tasks, asking for help, sharing news, and anything else we can think of. We’re working in some CRM features, but we’re still planning that part (using the P2 of course).

Without getting in to too much of the boring details, we’ve setup a MultiSite to host multiple blogs – one for each department, and then some office-wide blogs like “news” and “help.”

Blogs are also kept private – only logged-in users can get in

<?php
add_action( 'template_redirect', 'logged_in_users_only' );
function logged_in_users_only() {
	if ( !is_user_logged_in() )
	wp_redirect( wp_login_url( home_url() ) );
}
?>

Out-of the-box, there are some great features such as front-end posting and @ mentions (usernames used as terms in a ‘mentions’ taxonomy). But there were a some additional features that we wanted. Here’s some of what we’ve added so far:

  • email notifications for mentions
  • add posts to a ‘todo’ list
  • keep track of un/read posts

Email notifications

Mentions are built in, so I won’t get into those details. ‘Mentions’ is a taxonomy, and terms are usernames. When a term is added, use get_user_by(‘login’) to get the mentioned user’s details (specifically email address) and send them an email.

I modified p2_at_name() in functions.php:

<?php
function p2_at_names( $content ) {
	global $post, $comment;
	$name_map = p2_get_at_name_map(); // get users user_login and display_name map

	$content_original = $content; // save content before @names are found
	$users_to_add = array();

	foreach ( $name_map as $name => $values ) { //loop and...
		$content = preg_replace( "/B" . preg_quote( $name, '/' ) . "(?![^<]*</a)b/i", $values['replacement'], $content );
		$content = strtr( $content, $name, $name ); // Replaces keys with values longest to shortest, without re-replacing pieces it's already done
		if ( $content != $content_original ) // if the content has changed, an @name has been found.
 			$users_to_add[] = get_userdata( $name_map[$name]['id'] )->user_login; // add that user to an array
		$content_original = $content;
	}

	$terms = wp_get_post_terms($post->ID, 'mentions');
	$ts = array();
 	foreach ($terms as $to) {
		$ts[] = $to->name;
 	}
 	foreach($users_to_add as $u) {
 		if (in_array($u,$ts)) { //if they're in_array, then they've already been pinged
 		}
 		else {
 			$email = get_user_by('login',$u)->user_email;
 			$message = "You have been pinged in this post:n{$post->guid}";
 			wp_mail($email, 'You've been pinged in an internal InsideOut blog',$message);
 		}
 	}

	if ( !empty( $users_to_add ) )
		$cache_data = implode($users_to_add); // if we've got an array, make it a comma delimited string
	if ( isset($cache_data) && $cache_data != wp_cache_get( 'mentions', $post->ID) ) {
		wp_set_object_terms( $post->ID, $users_to_add, 'mentions', true ); // tag the post.
		wp_cache_set( 'mentions', $cache_data, $post->ID);
	}
	return $content;
}
?>

Todo Lists

For the todos (and un/read posts), I started with the Simple Post Ratings sample plugin. I don’t know a lot about wp-ajax, so I used SPR to make the front-end integration easier.

First I registered a new taxonomy, ‘todo,’ and like mentions, usernames are used for terms. While technically multiple terms can be added in the admin, only the first will be used (and only one can be added from the front).

There’s a ‘make your todo’ link with each post, and when clicked the current user’s username will be added as the term (if another username is present, it will be removed).

Then, I swapped out the get/update meta functions with the appropriate add/remove term functions.

Once things are up and running, I can get my todo items by getting posts in the todo taxonomy that match my username. Make sense?

Make-Todo.zip

Un/Read Posts

Very similar to the todo-lists. For this one, though, we aren’t limited to one term in the taxonomy for each post. If you’ve read the post (viewed the single post or clicked ‘mark as read’), your username is added to the ‘been_read’ taxonomy for the post.

Been-Read.zip

Can easily loop through different sites to get the unread counts and display them wherever you need.

<?php
$blogs = get_blogs_of_user( get_current_user_id() );
		foreach($blogs as $blog) {
			switch_to_blog( $blog->userblog_id );
			$unread = get_posts( array(
									'tax_query' => array(
										array(
											'taxonomy' => 'been_read',
											'field' => 'slug',
											'terms' => get_userdata( get_current_user_id() )->user_login,
											'operator' => 'NOT IN'
										)
									),
									'posts_per_page' => -1
								)
							);
			restore_current_blog();
 			$unread = count($unread);
			$unread = ($unread < 1) ? '' : '<span class="unread">'.$unread.'</span>';
		}
?>

Some other additions

A few widgets to display network-wide todos and mentions

Update user meta with a timestamp indicating when the user was last active.

 

It’s now very late (well, early…). I’ll be happy to expand upon anything here if you post your questions 🙂

15 thoughts on “Using WordPress, MultiSite, P2 and More”

  1. Paul

    Hi Kailey

    Found your blog through one of your plugins in WP.org, Just want to say thank you for making all the great plugins. I was wondering if your have any plan on sharing some tips about WP multisite ? Would be great if you do.

    🙂

  2. Russell Heimlich

    I just love P2. I sort of wish I had some sort of use for it or a group to keep track of links, updates, comments, and things.

    The email notification for mentioned usernames is great idea. Bookmarked this post in case I need it some day when I find a need for P2.

  3. Sylwia

    Thank you so much for sharing, Kailey! I’m setting a P2 site right now, and I’m going to try your ideas. It all sounds great!

    However, I can’t make the @ mentions work for the life of me. @admin works just as it should, but no other @username. They do get hinted during typing, and they show as links after publishing, but they point out to a failed page.

    What were your experiences? Did you have any problems with them and, hopefully, some good advice for me?

    1. Kailey

      I don’t recall mentions giving me any particular trouble, but if clicking on a mention sends you to a 404, try resaving your permalinks (or setting to a non-default option).

      1. Sylwia

        Thanks for letting me know! It actually helped me once I knew it did work for someone. There was a conflict with some other plugin.

        I’m trying to implement your email notifications but there’s no p2_at_name() in my p2’s functions.php Either I misunderstood you or they changed something during today’s update. Could you tell me which is the case?

        1. Kailey

          Looks like there were significant changes in the recent P2 updates.

          All the mentions-related functions have been moved to /inc/mentions.php which contains a class that extends what’s in /inc/terms-in-comment.php.

          You’d probably need to take lines 17-30 of my modified function and add it to the update_post() function in
          /inc/terms-in-comment.php (with a few little changes).

          At the moment, I’m unable to provide anything more specific, but perhaps that’ll get you pointed in the right direction.

  4. Stéphane

    We had to code against the SVN version of P2 and they changed quite a bit of stuff in the new version. Here is how I implemented email notification in the trunk branch. Hope it can be as useful as your code was to me:

    add_action(‘publish_post’,’send_email_notification_once’,9);
    function send_email_notification_once($postID){
    $post = get_post($postID);
    global $p2;
    $mentions = $p2->components[‘mentions’]->find_mentions($post->post_content);
    $permalink = get_the_permalink($postID);
    foreach($mentions as $match) {
    $email = get_user_by(‘slug’,$match)->user_email;
    $message = “You have been pinged in this post:n $permalink nn {$post->post_content} “;
    wp_mail($email, ‘You’ve been pinged in a P2 Post’,$message);
    }
    }
    add_action(‘comment_post’,’send_email_notification_once_comment’,9);
    function send_email_notification_once_comment($commentID){
    $comment = get_comment($commentID);
    global $p2;
    $mentions = $p2->components[‘mentions’]->find_mentions($comment->comment_content);
    $permalink = get_the_permalink($comment->comment_post_ID);
    foreach($mentions as $match) {
    $email = get_user_by(‘slug’,$match)->user_email;
    $message = “You have been pinged in this comment:n $permalink nn {$comment->comment_content} “;
    wp_mail($email, ‘You’ve been pinged in a P2 Comment’,$message);
    }
    }

    1. Stéphane

      I see thta I completely failed as following simple guidelines, let’s hope this ends better

      add_action('publish_post','send_email_notification_once',9);
      function send_email_notification_once($postID){
      $post = get_post($postID);
      global $p2;
      $mentions = $p2->components['mentions']->find_mentions($post->post_content);
      $permalink = get_the_permalink($postID);
      foreach($mentions as $match) {
      $email = get_user_by('slug',$match)->user_email;
      $message = "You have been pinged in this post:n $permalink nn {$post->post_content} ";
      wp_mail($email, 'You've been pinged in a Liberal P2 Post',$message);
      }
      }
      add_action('comment_post','send_email_notification_once_comment',9);
      function send_email_notification_once_comment($commentID){
      $comment = get_comment($commentID);
      global $p2;
      $mentions = $p2->components['mentions']->find_mentions($comment->comment_content);
      $permalink = get_the_permalink($comment->comment_post_ID);
      foreach($mentions as $match) {
      $email = get_user_by('slug',$match)->user_email;
      $message = "You have been pinged in this post:n $permalink nn {$comment->comment_content} ";
      wp_mail($email, 'You've been pinged in a Liberal P2 Post',$message);
      }
      }

      1. Taylor Barr

        Hey Stéphane,

        Thanks for snippet of code. Did you put that in Functions.php or mentions.php and if so where?

        I have found no solutions for this so any help would be great!

        1. Mario Berges

          Add these to the bottom of your functions.php file, and:

          (a) Replace get_the_permalink with get_permalink
          (b) Replace n and nn in the $message with \n and \n\n, respectively.

  5. Meagan Hanes

    Great article! Your code snippets will make it easy and fun to extend P2’s functionality, even if they need a bit of massaging. I’m enjoying playing with its capabilities right now as a CRM. It’s quite powerful eh?

    Bonus thanks to Stéphane for following up with even more working code! 😀

Leave a Reply

Your email address will not be published. Required fields are marked *