Created
January 24, 2014 13:05
-
-
Save gmazzap/8596870 to your computer and use it in GitHub Desktop.
A WordPress plugin that generate and handle urls that allow access to posts in non-public status.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Plugin Name: Private Post Access | |
* Plugin URI: http://wordpress.stackexchange.com/questions/130967/get-full-page-html-for-a-non-public-wordpress-page | |
* Description: Generate and handle urls that allow access to posts in non-public status. | |
* Author: G. M. | |
* Author URI: http://wordpress.stackexchange.com/users/35541/g-m | |
* | |
*/ | |
/** | |
* HOW TO USE | |
* | |
* First of all | |
* - install this file as a plugin and activate | |
* - OR just include this file in theme functions.php or in another plugin. | |
* | |
* After that, the url to use to show the post even if in private state should be get using: | |
* | |
* PrivatePostAccess::url( $post ); instead of get_permalink( $post ); | |
* | |
* The variable $post can be a post id or a post object. | |
* | |
* Sending a request using that url will show the post even if in a not public state, e.g. draft or pending. | |
* that url can also be used to retrieve a post html using HTTP API or raw cUrl | |
* | |
* Example: | |
* | |
* | |
* $url = PrivatePostAccess::url( 605 ); // 605 is the post ID | |
* | |
* if ( filter_var( $url, FILTER_VALIDATE_URL ) ) { | |
* $response = wp_remote_get( $url ); | |
* $post_full_body = $response ? wp_remote_retrieve_body( $response ) : FALSE; | |
* } | |
* | |
*/ | |
class PrivatePostAccess { | |
// change this string to whatever you want | |
const SECRET = 'ASlajADFA71scfas57dFsdtfgasd897Vsd'; | |
private static $hooksdone = array(); | |
private $requested_status; | |
private $requested_was_public = TRUE; | |
/** | |
* Get the url of a post that will allow to get post even if it has a not public status | |
* | |
* @param mixed $post post id, post object or null (inside the loop) | |
* @return string post url | |
* @access public | |
*/ | |
static function url( $post = NULL ) { | |
if ( empty($post) ) global $post; | |
if ( is_numeric($post) ) $post = get_post( $post ); | |
if ( ! $post instanceof WP_Post ) return FALSE; | |
if ( self::isPublic($post) ) return get_permalink($post); | |
$nonce = wp_create_nonce( __CLASS__ ); | |
$vars = array('nonce' => $nonce, 'key' => self::SECRET ); | |
return add_query_arg( $vars, get_permalink($post) ); | |
} | |
/** | |
* Check if the status of a post is public or not | |
* | |
* @param WP_Post $post post object | |
* @return bool true if post status is public, false otherwise | |
* @access protected | |
*/ | |
protected static function isPublic( WP_Post $post = NULL ) { | |
if ( $post instanceof WP_Post ) { | |
$status = get_post_status( $post ); | |
$post_status_obj = get_post_status_object( $status ); | |
return $post_status_obj->public; | |
} | |
} | |
/** | |
* Init the plugin | |
* | |
* @return null | |
* @access public | |
*/ | |
function init() { | |
add_action('pre_get_posts', array($this, 'hooks') ); | |
} | |
/** | |
* Add the hook needed to allow not public post to be visible | |
* | |
* @param WP_Query $query current main query | |
* @return null | |
* @access public | |
*/ | |
function hooks( WP_Query $query ) { | |
if ( current_filter() !== 'pre_get_posts' || isset( self::$hooksdone[current_filter()] ) ) return; | |
self::$hooksdone[current_filter()] = 1; | |
if ( ! is_admin() && $query->is_main_query() && is_singular() ) { | |
add_filter('posts_results', array($this, 'enable') ); | |
add_filter('the_posts', array($this, 'enable') ); | |
} | |
} | |
/** | |
* Run on two hooks, 'posts_results' and 'the_posts' | |
* on first fake global $wp_post_statuses to make current post status appear public, | |
* on second restore the status | |
* | |
* @param WP_Post $results the current queried post | |
* @return WP_Post | |
* @access public | |
*/ | |
function enable( $results ) { | |
if ( isset( self::$hooksdone[current_filter()] ) ) return $results; | |
self::$hooksdone[current_filter()] = 1; | |
if ( ! is_admin() && $this->checkRequest() ) { | |
global $wp_post_statuses; | |
if ( current_filter() === 'posts_results' && ! $this->isPublic($results[0]) ) { | |
$this->requested_status = get_post_status( $results[0] ); | |
$this->requested_was_public = FALSE; | |
$wp_post_statuses[$this->requested_status]->public = TRUE; | |
} elseif ( ( current_filter() === 'the_posts' ) && ! $this->requested_was_public ) { | |
$wp_post_statuses[$this->requested_status]->public = FALSE; | |
} | |
} | |
return $results; | |
} | |
/** | |
* Check the request to verify query vars | |
* | |
* @return null|bool | |
* @access protected | |
*/ | |
protected function checkRequest() { | |
static $good; | |
if ( is_null($good) ) { | |
$good = $this->checkNonce() && $this->checkSecret(); | |
} | |
return $good; | |
} | |
/** | |
* Check the request to verify nonce | |
* | |
* @return bool | |
* @access protected | |
*/ | |
protected function checkNonce() { | |
$nonce = filter_input( INPUT_GET, 'nonce', FILTER_SANITIZE_STRING ); | |
return ( ! empty($nonce) && wp_verify_nonce($nonce, __CLASS__) ); | |
} | |
/** | |
* Check the request to verify nonce | |
* | |
* @return bool | |
* @access protected | |
*/ | |
protected function checkSecret() { | |
$key = filter_input( INPUT_GET, 'key', FILTER_SANITIZE_STRING ); | |
return ( ! empty($key) && $key === self::SECRET ); | |
} | |
} | |
add_action( 'init', array( new PrivatePostAccess, 'init' ) ); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment