Private Posts in WordPress

In WordPress, post visibility can be set to Public, Private or Password Protected, in the Gutenberg editor under the Document menu. Password Protected is out of scope for this article; it’s not a feature I’ve used much. I do however often make Private posts, useful for keeping educational notes and information, for example.

By default, Private posts have a front-end view of the post only logged-in users can see, the post title prefixed with ‘Private:’ . Other than that, the post behaves normally, appearing in the main posts query, and in archives, nestled amongst public posts in whatever order your theme specifies.

Can this feature be improved? In my case, I would prefer not to have my private posts displayed in this way: I’d much rather have my Private posts in their own archive, their own view for users authorised to see them, separate from the public blog. Imagined this way, anyone wanting to keep a private journal alongside their public blog might find this a preferable arrangement.

Sounds like a perfect idea for a custom plugin.

Private Posts Keep

Modifying Private Posts in a custom plugin

I broke down my plugin design with three goals in mind:

  • removing private posts from the main posts view and archives
  • creating a new archive-style view exclusively for private posts
  • creating a Private Posts Widget, for an alternative view and easy front-end access.

I decided to call the plugin Private Posts Keep. In giving Private posts their own area, I was reminded of keep within a castle, hence the perhaps obscure name based on this metaphor. The most straightforward title, to be honest, might be ‘Segregate Private Posts’ since that’s a clear and accurate description of both the intent, and the effect, of the plugin. Hmm, maybe a compromise title would be ‘Private Posts Sanctum’?

Enough of what to call it; let’s get to work making it function. First, let’s make a start on our first two goals, by creating two classes.

Inside our main class, class-pp-keep.php, we’ll create a few functions:

public function rem_pp( $query ) {
  if( current_user_can( 'read_private_posts' ) ){
  /*affects main query on posts page or archives.			 
   *http://codex.wordpress.org/Function_Reference/is_main_query			 
   *http://codex.wordpress.org/Function_Reference/is_home			 
   *http://codex.wordpress.org/Function_Reference/is_archive*/
    if ( $query->is_main_query() &&  $query->is_home() || $query->is_archive() ) {
      $query->set( 'post_status', 'publish' );
    }
  }
}

That takes care of modifying the main query on the posts page or an archive page. However, we’ll find on single post views our navigation links to the next and previous posts won’t reflect this change of emphasis. Let’s fix this with another function to filter these navigation links:

public function get_adjacent_post_mod($where){
  if (is_single()){
    global $wpdb, $post;
    if ( get_post_status ( ) == 'private' ) {
      $where = str_replace( "AND ( p.post_status = 'publish' OR p.post_status = 'private' )", "AND p.post_status = 'private'", $where );
      return $where;	
    } else {
      $where = str_replace( "AND ( p.post_status = 'publish' OR p.post_status = 'private' )", "AND p.post_status = 'publish'", $where );
      return $where;	
    }
  }
}

And we need somewhere to display those now missing Private posts. It’s possible to programmatically insert posts in the database, so that’s what we’ll do. The function first checks a Page with our desired title doesn’t exist, and if not creates it, set to Private, and fills it with the specified content, including a shortcode, for outputting a list of Private posts. we’ll define elsewhere in the plugin.

public function create(){
			$post = '';
			if( get_page_by_title('Private Archive') == NULL )
			// Create post object
			$post = array(
			  'post_title'    => 'Private Archive',
			  'post_status'   => 'private',
			  'post_type'     => 'page',
			  'post_content'   => 'This page is intended for your private posts.
				
				[private-posts]'
			);

			// Insert the post into the database
			
			$insert_post = wp_insert_post( $post, true);//now you can use $post_id within add_post_meta or update_post_meta	
			return $insert_post;	
		}

The shortcode is defined in a function in a separate file. Finally we add our functions to the appropriate WordPress hooks, in our constructor function for the class, like so:

add_action( 'pre_get_posts', array(&$this, 'rem_pp'));
add_action( 'wp_loaded', array(&$this, 'create'));
add_filter( 'get_next_post_where', array(&$this, 'get_adjacent_post_mod'));
add_filter( 'get_previous_post_where', array(&$this, 'get_adjacent_post_mod'));

Our rem_pp() function is added to the pre_get_posts action hook. Note we need to add our navigation links filter to two separate hooks, get_next_post_where & get_previous_post_where

Our widget is created in a separate class, class-pp-keep-widget.php.

In our main plugin file, pp-keep.php, which runs the plugin, we’ll tie all this together:

/*
Plugin Name: Private Posts Keep
Description: Segregates Private Posts
License: GPL2
*/
/* exit if directly accessed */
defined( 'ABSPATH' ) || exit;
define( 'PPKEEP_PATH', plugin_dir_path( __FILE__ ) );

require_once( __DIR__ . '/pp-keep-shortcode.php' );
require_once( __DIR__ . '/class-pp-keep.php' );
require_once( __DIR__ . '/class-pp-keep-widget.php' );
if( class_exists( 'PP_Keep' ) ) {
	$PPKeep = new PP_Keep();// instantiate the plugin class
}

if ( class_exists( 'PP_Keep_Widget' ) ) {
	// Register and load the widget
	function pp_load_widget() {
		register_widget( 'PP_Keep_Widget' );
	}
	add_action( 'widgets_init', 'pp_load_widget' );
}

/**
 * Activate the plugin
 */
function ppkeep_activate()
{
	// Do nothing
} // END public static function activate
/**
 * Deactivate the plugin
 */
function ppkeep_deactivate()
{
	$page = get_page_by_title('Private Archive');
	if (isset($page)){
		$page_id= $page->ID;
	}
	wp_delete_post($page_id, true);
} // END public static function deactivate

function ppkeep_uninstall () {
	if ( ! current_user_can( 'activate_plugins' ) )
	    return;
} // END public static function uninstall
register_activation_hook(__FILE__, 'ppkeep_activate');
register_deactivation_hook(__FILE__, 'ppkeep_deactivate');
register_uninstall_hook(__FILE__, 'ppkeep_uninstall');

The file runs a basic security check, defined( 'ABSPATH' ) || exit; and loads up our shortcode and classes . The activation, deactivation, and uninstall hooks are features available to plugin authors so code can be triggered when the user performs these actions. Here they are standard, except for the deactivate hook, which I’ve set to delete the private Page the plugin creates.

Try it out for yourself

The plugin works and the full plugin source code is freely available on my github. To install in your WordPress site, you’ll have to download the .zip archive:

Then go to your WordPress Admin>Plugins, and hit ‘Add New’ then ‘Upload Plugin’. Uploading the .zip file will install the plugin for you to activate.

After activation, you will find private posts are now gone from your main posts page and archives, but are listed on a Private Posts Archive page the plugin has created for you, which should show up on your Dashboard under ‘Pages’. You can edit this page as normal, but ensure it keeps the shortcode which outputs a simple list of Private Posts by title, with their permalinks. Alternatively you can add the shortcode anywhere you like.

You will find a Widget available which you can add to your sidebar. The widget will only show up for users authorised to read private posts, and displays a short list of the latest, along with a link to the Private Posts Archive page the plugin creates.

How can the plugin be improved?

The code which delete the Archive page on deactivation, and the link to the page in the widget, use the title and url of the page to function. This depends on the user neither changing the title nor deleting the page, which cannot be guaranteed (see github issue for more details).

Moreover, there aren’t many options available to the user. The widget has no options other than the widget title, and there are no options to modify how the Archive page displays the private posts.

Finally, I have a suspicion the plugin wouldn’t be accepted into the Plugin directory without a good code review and some refactoring. The code works, and does what it says on the tin, but it isn’t necessarily elegantly written and designed.

I wrote it back during the turn of 2015/16, but life rather got in the way of me developing it further. Nevertheless it’s a useful plugin that adds value to the native private posts feature of WordPress, and well worth revisiting.

You can follow along with development of the plugin, or even help out yourself, at the following url:

https://github.com/KorvinM/pp-keep

PHP basics

As a kinesthetic learner, my preference when taking a course in code is to build what I’m shown, but tweak, improve, build on and document what I learn as I go along.

Returning to professional web development after a long break, I needed a refresher course in php, so I took a look at the php basics video series from codecourse:

With a series like this, where examples have a minimal front end, I like to build a suitable front-end as I go, shaping it to the needs of the project. To me this is an ideal way to build a site, but isn’t always possible in a client project. Personal projects are ideal for this kind of discipline, and it’s amazing what can come out of it.

Continue reading PHP basics

Uploading with html5/php

Resources on handling file uploads.

http://php.net/manual/en/features.file-upload.php
http://php.net/manual/en/reserved.variables.post.php#87512
https://www.sitepoint.com/file-uploads-with-php/
https://www.sitepoint.com/monitoring-file-integrity/

Front end

https://www.quirksmode.org/dom/inputfile.html

https://www.sitepoint.com/tracking-upload-progress-with-php-and-javascript/

http://stackoverflow.com/questions/29727436/upload-progress-bar-using-session-in-php-5-4-with-codeigniter

Related

https://www.sitepoint.com/monitoring-file-integrity/

https://www.sitepoint.com/html5-native-drag-and-drop-api/

Sulphur

https://github.com/KorvinM/sulphur

Hillary Clinton’s old website

On Sunday, Hillary Rodham Clinton announced she would definitely like to be the next President of the United States of America. Before that announcement HillaryClinton.com looked like this: a holding page linking to the website of her official office.

HillaryClinton.com on 27th March 2015, retrieved from archive.org
HillaryClinton.com on 27th March 2015, retrieved from archive.org

Blue, a notoriously popular colour in web design, seems deployed here according to colour theory:always reassuringly safe, friendly and almost frivolous when light, while the darker blue brings a more serious tone. The background gradient gives an abstract sense of a horizon; the ground and the sky; don’t stop thinking about tomorrow. We’re meant to be reassured. The contrasting darker blue used for the ‘Hillary’ headline – really a logo – fits it quite well: we’re on first name terms with Mrs Clinton, but we’re still encouraged to take her name seriously as a strong and powerful proposition. The colour contrast emphasises the seriousness of ‘Hillary’ as a concept. We’re meant to be impressed.
The gradient is deployed as a background image rather than modern css: old-fashioned but fine for a lightweight single page site. There’s a technical fail, however, whereby the bottom curve of the ‘y’ descender in the logo (also deployed as an image) has been truncated by over-zealous cropping. This could have been avoided with modern web typography – or a steadier hand.

But never mind because the typography itself is interesting. Continue reading Hillary Clinton’s old website

WordCamp Brum roundup – Sunday

Part Two of my report on WordCamp Birmingham 2015.

You can read Part One here .

As noted by Claire Brotherton in her round up of Day 2, Sunday morning seemed sparsely attended, the announcement that the previous night’s social was a record bar taking for a UK Wordcamp presumably no coincidence.

Despite a brisk and enjoyable late-night walk home, I confess I was one of those lunching out the morning, so I missed Petra Foster on how to Be a Brand, Not a Commodity (although I’d caught this presentation at the previous month’s WP Brum meetup) and Pauline Roche and Ted Ryan on WordPress for Small and Not For Profit Enterprises. 

I also missed Paul Cherry on Customers and the Web, who has put the slides from his talk online.

And the morning concluded with Ben Furfie on Why it’s time to stop using Photoshop for web design. But,  you can read useful summaries of all these talks in Claire Brotherton’s post.
Continue reading WordCamp Brum roundup – Sunday

WordCamp Brum Roundup – Saturday

WordCamp Birmingham (UK) 2015 happened last weekend, and seems to have been a great success for all concerned, putting the Birmingham WordPress community in, if you’ll excuse the pun, bullish mood. I certainly enjoyed myself. The event reignited my passion for WordPress and web-work in general, answering a few questions, confirming a few biases and giving me new energy and contacts. For anyone involved in WordPress, whether as a developer, designer, site manager or content creator, I would heartily recommend getting along to your nearest WordCamp. They tend to cater for all tastes and areas of this kind of work, and, as with most conferences and meet-ups, the most interesting conversations occur at the margins outside the programmed content.

But that’s another story. I thought here I’d gather all of the most relevant online stuff I can find from the event: slides of the talks, comments from myself on those talks I attended, comments and a sense of the buzz from others, as well as some of the photos available online. This will be a multi-part post, and in this one I’ll focus on day one.
Continue reading WordCamp Brum Roundup – Saturday