summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTheo Chatzimichos <tampakrap@gentoo.org>2013-10-08 17:47:47 +0200
committerTheo Chatzimichos <tampakrap@gentoo.org>2013-10-08 17:47:47 +0200
commit5a6e23c116b7d42b03ed646b1e5c08c7b43bfda3 (patch)
treeb279d9d0c8ce58d082b223491541668489255a5b /plugins/public-post-preview
parentAdd table-of-contents-plus plugin, requested by hwoarang (diff)
downloadblogs-gentoo-5a6e23c116b7d42b03ed646b1e5c08c7b43bfda3.tar.gz
blogs-gentoo-5a6e23c116b7d42b03ed646b1e5c08c7b43bfda3.tar.bz2
blogs-gentoo-5a6e23c116b7d42b03ed646b1e5c08c7b43bfda3.zip
Add public-post-preview plugin
Diffstat (limited to 'plugins/public-post-preview')
-rw-r--r--plugins/public-post-preview/js/public-post-preview.dev.js111
-rw-r--r--plugins/public-post-preview/js/public-post-preview.js108
-rw-r--r--plugins/public-post-preview/js/public-post-preview.min.js6
-rw-r--r--plugins/public-post-preview/lang/ds-public-post-preview-de_DE.mobin0 -> 1213 bytes
-rw-r--r--plugins/public-post-preview/lang/ds-public-post-preview-de_DE.po88
-rw-r--r--plugins/public-post-preview/lang/ds-public-post-preview-xx_XX.pot21
-rw-r--r--plugins/public-post-preview/public-post-preview.php465
-rw-r--r--plugins/public-post-preview/readme.txt126
8 files changed, 925 insertions, 0 deletions
diff --git a/plugins/public-post-preview/js/public-post-preview.dev.js b/plugins/public-post-preview/js/public-post-preview.dev.js
new file mode 100644
index 00000000..bdd8e371
--- /dev/null
+++ b/plugins/public-post-preview/js/public-post-preview.dev.js
@@ -0,0 +1,111 @@
+( function( $ ) {
+ DSPublicPostPreview = {
+
+ /**
+ * Initializes the plugin.
+ *
+ * @since 2.0.0
+ */
+ initialize : function() {
+ var t = this;
+
+ t.checkbox = $( '#public-post-preview' );
+ t.link = $( '#public-post-preview-link' );
+ t.nonce = $( '#public_post_preview_wpnonce' );
+ t.status = $( '#public-post-preview-ajax' );
+
+ if ( ! t.checkbox.prop( 'checked' ) )
+ t.link.hide();
+
+ t.checkbox.bind( 'change', function() {
+ t.change();
+ } );
+ },
+
+ /**
+ * Handles a checkbox change.
+ *
+ * @since 2.0.0
+ */
+ change : function() {
+ var t = this,
+ checked = t.checkbox.prop( 'checked' ) ? 1 : 0;
+
+ // Toggle visibility of the link
+ t.link.toggle();
+
+ // Disable the checkbox, to prevent double AJAX requests
+ t.checkbox.prop( 'disabled', 'disabled' );
+
+ t.request(
+ {
+ _ajax_nonce : t.nonce.val(),
+ checked : checked,
+ post_ID : $( '#post_ID' ).val()
+ },
+ function( data ) {
+ // data is '1' if it's a successful request
+ if ( data ) {
+ if ( checked ) {
+ t.status.text( DSPublicPostPreviewL10n.enabled );
+ t._pulsate( t.status, 'green' );
+ } else {
+ t.status.text( DSPublicPostPreviewL10n.disabled );
+ t._pulsate( t.status, 'red' );
+ }
+ }
+
+ // Enable the checkbox again
+ t.checkbox.prop('disabled', '');
+ }
+ );
+ },
+
+ /**
+ * Does the AJAX request.
+ *
+ * @since 2.0.0
+ *
+ * @param {Object} data The data to send.
+ * @param {Object} callback Callback function for a successfull request.
+ */
+ request : function( data, callback ) {
+ $.ajax( {
+ type: 'POST',
+ url: ajaxurl,
+ data: $.extend(
+ data,
+ {
+ action: 'public-post-preview'
+ }
+ ),
+ success : callback
+ } );
+ },
+
+ /**
+ * Helper for a pulse effect.
+ *
+ * @since 2.0.0
+ *
+ * @param {Object} e The element.
+ * @param {String} color The text color of the element.
+ */
+ _pulsate : function( e, color ) {
+ e.css( 'color', color )
+ .animate( { opacity: 0 }, 600, 'linear' )
+ .animate( { opacity: 1 }, 600, 'linear' )
+ .animate( { opacity: 0 }, 600, 'linear' )
+ .animate( { opacity: 1 }, 600, 'linear' )
+ .animate( { opacity: 0 }, 600, 'linear', function() {
+ e.text( '' );
+ } );
+ }
+ };
+
+ // Document is ready.
+ $( function() {
+ DSPublicPostPreview.initialize();
+ } );
+
+} )( jQuery );
diff --git a/plugins/public-post-preview/js/public-post-preview.js b/plugins/public-post-preview/js/public-post-preview.js
new file mode 100644
index 00000000..1ba65d81
--- /dev/null
+++ b/plugins/public-post-preview/js/public-post-preview.js
@@ -0,0 +1,108 @@
+( function( $ ) {
+ DSPublicPostPreview = {
+
+ /**
+ * Initializes the plugin.
+ *
+ * @since 2.0.0
+ */
+ initialize : function() {
+ var t = this;
+
+ t.checkbox = $( '#public-post-preview' );
+ t.link = $( '#public-post-preview-link' );
+ t.nonce = $( '#public_post_preview_wpnonce' );
+ t.status = $( '#public-post-preview-ajax' );
+
+ t.status.css( 'opacity', 0 );
+
+ if ( ! t.checkbox.prop( 'checked' ) )
+ t.link.hide();
+
+ t.checkbox.bind( 'change', function() {
+ t.change();
+ } );
+ },
+
+ /**
+ * Handles a checkbox change.
+ *
+ * @since 2.0.0
+ */
+ change : function() {
+ var t = this,
+ checked = t.checkbox.prop( 'checked' ) ? 1 : 0;
+
+ // Toggle visibility of the link
+ t.link.toggle();
+
+ // Disable the checkbox, to prevent double AJAX requests
+ t.checkbox.prop( 'disabled', 'disabled' );
+
+ t.request(
+ {
+ _ajax_nonce : t.nonce.val(),
+ checked : checked,
+ post_ID : $( '#post_ID' ).val()
+ },
+ function( data ) {
+ // data is '1' if it's a successful request
+ if ( data ) {
+ if ( checked ) {
+ t.status.text( DSPublicPostPreviewL10n.enabled );
+ t._pulsate( t.status, 'green' );
+ } else {
+ t.status.text( DSPublicPostPreviewL10n.disabled );
+ t._pulsate( t.status, 'red' );
+ }
+ }
+
+ // Enable the checkbox again
+ t.checkbox.prop( 'disabled', '' );
+ }
+ );
+ },
+
+ /**
+ * Does the AJAX request.
+ *
+ * @since 2.0.0
+ *
+ * @param {Object} data The data to send.
+ * @param {Object} callback Callback function for a successfull request.
+ */
+ request : function( data, callback ) {
+ $.ajax( {
+ type: 'POST',
+ url: ajaxurl,
+ data: $.extend(
+ data,
+ {
+ action: 'public-post-preview'
+ }
+ ),
+ success : callback
+ } );
+ },
+
+ /**
+ * Helper for a pulse effect.
+ *
+ * @since 2.0.0
+ *
+ * @param {Object} e The element.
+ * @param {String} color The text color of the element.
+ */
+ _pulsate : function( e, color ) {
+ e.css( 'color', color )
+ .animate( { opacity: 1 }, 600, 'linear' )
+ .animate( { opacity: 0 }, 600, 'linear', function() {
+ e.empty();
+ } );
+ }
+ };
+
+ // Document is ready.
+ $( DSPublicPostPreview.initialize() );
+
+} )( jQuery );
diff --git a/plugins/public-post-preview/js/public-post-preview.min.js b/plugins/public-post-preview/js/public-post-preview.min.js
new file mode 100644
index 00000000..0ff89e8e
--- /dev/null
+++ b/plugins/public-post-preview/js/public-post-preview.min.js
@@ -0,0 +1,6 @@
+(function(a){DSPublicPostPreview={initialize:function(){var b=this;b.checkbox=a("#public-post-preview");b.link=a("#public-post-preview-link");b.nonce=a("#public_post_preview_wpnonce");
+b.status=a("#public-post-preview-ajax");b.status.css("opacity",0);if(!b.checkbox.prop("checked")){b.link.hide();}b.checkbox.bind("change",function(){b.change();
+});},change:function(){var b=this,c=b.checkbox.prop("checked")?1:0;b.link.toggle();b.checkbox.prop("disabled","disabled");b.request({_ajax_nonce:b.nonce.val(),checked:c,post_ID:a("#post_ID").val()},function(d){if(d){if(c){b.status.text(DSPublicPostPreviewL10n.enabled);
+b._pulsate(b.status,"green");}else{b.status.text(DSPublicPostPreviewL10n.disabled);b._pulsate(b.status,"red");}}b.checkbox.prop("disabled","");});},request:function(b,c){a.ajax({type:"POST",url:ajaxurl,data:a.extend(b,{action:"public-post-preview"}),success:c});
+},_pulsate:function(c,b){c.css("color",b).animate({opacity:1},600,"linear").animate({opacity:0},600,"linear",function(){c.empty();});}};a(DSPublicPostPreview.initialize());
+})(jQuery); \ No newline at end of file
diff --git a/plugins/public-post-preview/lang/ds-public-post-preview-de_DE.mo b/plugins/public-post-preview/lang/ds-public-post-preview-de_DE.mo
new file mode 100644
index 00000000..6ab12472
--- /dev/null
+++ b/plugins/public-post-preview/lang/ds-public-post-preview-de_DE.mo
Binary files differ
diff --git a/plugins/public-post-preview/lang/ds-public-post-preview-de_DE.po b/plugins/public-post-preview/lang/ds-public-post-preview-de_DE.po
new file mode 100644
index 00000000..c13dcb2e
--- /dev/null
+++ b/plugins/public-post-preview/lang/ds-public-post-preview-de_DE.po
@@ -0,0 +1,88 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: Public Post Preview v2.2-beta\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: \n"
+"PO-Revision-Date: 2013-03-14 20:18:03+0000\n"
+"Last-Translator: Dominik Schilling <dominik.schilling@gmail.com>\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: CSL v1.x\n"
+"X-Poedit-Language: German\n"
+"X-Poedit-Country: GERMANY\n"
+"X-Poedit-SourceCharset: utf-8\n"
+"X-Poedit-KeywordsList: __;_e;__ngettext:1,2;_n:1,2;__ngettext_noop:1,2;_n_noop:1,2;_c,_nc:4c,1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;_nx_noop:4c,1,2;\n"
+"X-Poedit-Basepath: ../\n"
+"X-Poedit-Bookmarks: \n"
+"X-Poedit-SearchPath-0: .\n"
+"X-Textdomain-Support: yes"
+
+#. translators: plugin header field 'Name'
+#: public-post-preview.php:0
+#@ ds-public-post-preview
+msgid "Public Post Preview"
+msgstr "Öffentliche Vorschau"
+
+#. translators: plugin header field 'PluginURI'
+#: public-post-preview.php:0
+#@ ds-public-post-preview
+msgid "http://wpgrafie.de/wp-plugins/public-post-preview/en/"
+msgstr "http://wpgrafie.de/wp-plugins/public-post-preview/"
+
+#. translators: plugin header field 'Description'
+#: public-post-preview.php:0
+#@ ds-public-post-preview
+msgid "Enables you to give a link to anonymous users for public preview of any post type before it is published."
+msgstr "Bietet die Möglichkeit einen Link mit Dritten zu Teilen, um eine Vorschau eines bisher unveröffentlichten Inhaltstyp zu geben."
+
+#. translators: plugin header field 'Author'
+#: public-post-preview.php:0
+#@ ds-public-post-preview
+msgid "Dominik Schilling"
+msgstr "Dominik Schilling"
+
+#. translators: plugin header field 'AuthorURI'
+#: public-post-preview.php:0
+#@ ds-public-post-preview
+msgid "http://wphelper.de/"
+msgstr "http://wphelper.de/"
+
+#: public-post-preview.php:121
+#@ ds-public-post-preview
+msgid "Enabled!"
+msgstr "Aktiviert!"
+
+#: public-post-preview.php:122
+#@ ds-public-post-preview
+msgid "Disabled!"
+msgstr "Deaktiviert!"
+
+#: public-post-preview.php:168
+#@ ds-public-post-preview
+msgid "Enable public preview"
+msgstr "Öffentliche Vorschau aktivieren"
+
+#: public-post-preview.php:173
+#@ ds-public-post-preview
+msgid "(Copy and share this link.)"
+msgstr "(Kopiere und teile diesen Link.)"
+
+#: public-post-preview.php:329
+#@ ds-public-post-preview
+msgid "The link has been expired!"
+msgstr "Der Link ist nicht mehr gültig!"
+
+#: public-post-preview.php:332
+#@ ds-public-post-preview
+msgid "No Public Preview available!"
+msgstr "Keine öffentliche Vorschau verfügbar!"
+
+#. translators: plugin header field 'Version'
+#: public-post-preview.php:0
+#@ ds-public-post-preview
+msgid "2.2-beta"
+msgstr ""
+
diff --git a/plugins/public-post-preview/lang/ds-public-post-preview-xx_XX.pot b/plugins/public-post-preview/lang/ds-public-post-preview-xx_XX.pot
new file mode 100644
index 00000000..2c9e2f26
--- /dev/null
+++ b/plugins/public-post-preview/lang/ds-public-post-preview-xx_XX.pot
@@ -0,0 +1,21 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: PlaceHolder\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: \n"
+"PO-Revision-Date: 2012-07-21 23:01:26+0000\n"
+"Last-Translator: none\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Poedit-Language: English\n"
+"X-Poedit-Country: UNITED STATES\n"
+"X-Poedit-SourceCharset: utf-8\n"
+"X-Poedit-KeywordsList: __;_e;__ngettext:1,2;_n:1,2;__ngettext_noop:1,2;_n_noop:1,2;_c,_nc:4c,1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;_nx_noop:4c,1,2;\n"
+"X-Poedit-Basepath: ../\n"
+"X-Poedit-Bookmarks: \n"
+"X-Poedit-SearchPath-0: .\n"
+"X-Textdomain-Support: yes"
+
diff --git a/plugins/public-post-preview/public-post-preview.php b/plugins/public-post-preview/public-post-preview.php
new file mode 100644
index 00000000..ce2744be
--- /dev/null
+++ b/plugins/public-post-preview/public-post-preview.php
@@ -0,0 +1,465 @@
+<?php
+/**
+ * Plugin Name: Public Post Preview
+ * Version: 2.2
+ * Description: Enables you to give a link to anonymous users for public preview of any post type before it is published.
+ * Author: Dominik Schilling
+ * Author URI: http://wphelper.de/
+ * Plugin URI: http://wpgrafie.de/wp-plugins/public-post-preview/en/
+ *
+ * Text Domain: ds-public-post-preview
+ * Domain Path: /lang
+ *
+ * License: GPLv2 or later
+ *
+ * Previously (2009-2011) maintained by Jonathan Dingman and Matt Martz.
+ *
+ * Copyright (C) 2012-2013 Dominik Schilling
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * Don't call this file directly.
+ */
+if ( ! class_exists( 'WP' ) ) {
+ die();
+}
+
+/**
+ * The class which controls the plugin.
+ *
+ * Used hooks:
+ * - pre_get_posts
+ * - query_vars
+ * - init
+ * - post_submitbox_misc_actions
+ * - save_post
+ * - posts_results
+ * - wp_ajax_public-post-preview
+ * - admin_enqueue_scripts
+ *
+ * Inits at 'plugins_loaded' hook.
+ *
+ */
+class DS_Public_Post_Preview {
+
+ /**
+ * Hooks into 'pre_get_posts' to handle public preview, only nn-admin
+ * Hooks into 'add_meta_boxes' to register the meta box.
+ * Hooks into 'save_post' to handle the values of the meta box.
+ * Hooks into 'admin_enqueue_scripts' to register JavaScript.
+ *
+ * @since 1.0.0
+ */
+ public static function init() {
+ add_action( 'init', array( __CLASS__, 'load_textdomain' ) );
+
+ if ( ! is_admin() ) {
+ add_filter( 'pre_get_posts', array( __CLASS__, 'show_public_preview' ) );
+
+ add_filter( 'query_vars', array( __CLASS__, 'add_query_var' ) );
+ } else {
+ add_action( 'post_submitbox_misc_actions', array( __CLASS__, 'post_submitbox_misc_actions' ) );
+
+ add_action( 'save_post', array( __CLASS__, 'register_public_preview' ), 20, 2 );
+
+ add_action( 'wp_ajax_public-post-preview', array( __CLASS__, 'ajax_register_public_preview' ) );
+
+ add_action( 'admin_enqueue_scripts' , array( __CLASS__, 'enqueue_script' ) );
+ }
+ }
+
+ /**
+ * Registers the textdomain.
+ *
+ * @since 2.0.0
+ */
+ public static function load_textdomain() {
+ return load_plugin_textdomain(
+ 'ds-public-post-preview',
+ false,
+ dirname( plugin_basename( __FILE__ ) ) . '/lang'
+ );
+ }
+
+ /**
+ * Registers the JavaScript file for post(-new).php.
+ *
+ * @since 2.0.0
+ */
+ public static function enqueue_script( $hook_suffix ) {
+ if ( ! in_array( $hook_suffix, array( 'post.php', 'post-new.php' ) ) )
+ return;
+
+ $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
+
+ wp_enqueue_script(
+ 'ds-public-post-preview',
+ plugins_url( "js/public-post-preview$suffix.js", __FILE__ ),
+ array( 'jquery' ),
+ self::get_plugin_info( 'Version' ),
+ true
+ );
+
+ wp_localize_script(
+ 'ds-public-post-preview',
+ 'DSPublicPostPreviewL10n',
+ array(
+ 'enabled' => __( 'Enabled!', 'ds-public-post-preview' ),
+ 'disabled' => __( 'Disabled!', 'ds-public-post-preview' )
+ )
+ );
+ }
+
+ /**
+ * Adds the checkbox to the submit metabox
+ *
+ * @since 2.2.0
+ */
+ public static function post_submitbox_misc_actions() {
+ $post_types = get_post_types(
+ array(
+ 'public' => true
+ )
+ );
+
+ $post = get_post();
+
+ if ( ! in_array( $post->post_type, $post_types ) )
+ return false;
+
+ if ( ! in_array( $post->post_status, array( 'draft', 'pending', 'future' ) ) )
+ return false;
+
+ ?>
+ <div class="misc-pub-section public-post-preview">
+ <?php self::get_checkbox_html( $post ); ?>
+ </div>
+ <?php
+
+ }
+
+ /**
+ * Prints the checkbox if the is draft, pending or future.
+ *
+ */
+ private static function get_checkbox_html( $post ) {
+ if ( empty( $post ) )
+ $post = get_post();
+
+ wp_nonce_field( 'public_post_preview', 'public_post_preview_wpnonce' );
+
+ $preview_post_ids = self::get_preview_post_ids();
+ ?>
+ <label><input type="checkbox"<?php checked( in_array( $post->ID, $preview_post_ids ) ); ?> name="public_post_preview" id="public-post-preview" value="1" />
+ <?php _e( 'Enable public preview', 'ds-public-post-preview' ); ?> <span id="public-post-preview-ajax"></span></label>
+
+ <div id="public-post-preview-link" style="margin-top:6px">
+ <label>
+ <input type="text" name="public_post_preview_link" class="regular-text" value="<?php echo esc_attr( self::get_preview_link( $post->ID ) ); ?>" style="width:99%" readonly />
+ <span class="description"><?php _e( '(Copy and share this link.)', 'ds-public-post-preview' ); ?></span>
+ </label>
+ </div>
+ <?php
+ }
+
+ /**
+ * Returns the public preview link.
+ *
+ * The link is the permalink with these parameters:
+ * - preview, always true (query var for core)
+ * - _ppp, a custom nonce, see DS_Public_Post_Preview::create_nonce()
+ *
+ * @since 2.0.0
+ *
+ * @param int $post_id The post id.
+ * @return string The generated public preview link.
+ */
+ private static function get_preview_link( $post_id ) {
+ return add_query_arg(
+ array(
+ 'preview' => true,
+ '_ppp' => self::create_nonce( 'public_post_preview_' . $post_id ),
+ ),
+ get_permalink( $post_id )
+ );
+ }
+
+ /**
+ * (Un)Registers a post for a public preview.
+ *
+ * Don't runs on an autosave and ignores post revisions.
+ *
+ * @since 2.0.0
+ *
+ * @param int $post_id The post id.
+ * @param object $post The post object.
+ * @return bool Returns false on a failure, true on a success.
+ */
+ public static function register_public_preview( $post_id, $post ) {
+ if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
+ return false;
+
+ if ( wp_is_post_revision( $post_id ) )
+ return false;
+
+ if ( empty( $_POST['public_post_preview_wpnonce'] ) || ! wp_verify_nonce( $_POST['public_post_preview_wpnonce'], 'public_post_preview' ) )
+ return false;
+
+ $preview_post_ids = self::get_preview_post_ids();
+ $preview_post_id = $post->ID;
+
+ if ( empty( $_POST['public_post_preview'] ) && in_array( $preview_post_id, $preview_post_ids ) )
+ $preview_post_ids = array_diff( $preview_post_ids, (array) $preview_post_id );
+ elseif (
+ ! empty( $_POST['public_post_preview'] ) &&
+ ! empty( $_POST['original_post_status'] ) &&
+ 'publish' != $_POST['original_post_status'] &&
+ 'publish' == $post->post_status &&
+ in_array( $preview_post_id, $preview_post_ids )
+ )
+ $preview_post_ids = array_diff( $preview_post_ids, (array) $preview_post_id );
+ elseif ( ! empty( $_POST['public_post_preview'] ) && ! in_array( $preview_post_id, $preview_post_ids ) )
+ $preview_post_ids = array_merge( $preview_post_ids, (array) $preview_post_id );
+ else
+ return false; // Nothing changed.
+
+ return self::set_preview_post_ids( $preview_post_ids );
+ }
+
+ /**
+ * (Un)Registers a post for a public preview for an AJAX request.
+ *
+ * @since 2.0.0
+ *
+ * @return string Returns '0' on a failure, '1' on success.
+ */
+ public static function ajax_register_public_preview() {
+ check_ajax_referer( 'public_post_preview' );
+
+ $preview_post_id = (int) $_POST['post_ID'];
+ $post = get_post( $preview_post_id );
+
+ if ( ( 'page' == $post->post_type && ! current_user_can( 'edit_page', $preview_post_id ) ) || ! current_user_can( 'edit_post', $preview_post_id ) )
+ wp_die( 0 );
+
+ if ( ! in_array( $post->post_status, array( 'draft', 'pending', 'future' ) ) )
+ wp_die( 0 );
+
+ $preview_post_ids = self::get_preview_post_ids();
+
+ if ( empty( $_POST['checked'] ) && in_array( $preview_post_id, $preview_post_ids ) )
+ $preview_post_ids = array_diff( $preview_post_ids, (array) $preview_post_id );
+ elseif ( ! empty( $_POST['checked'] ) && ! in_array( $preview_post_id, $preview_post_ids ) )
+ $preview_post_ids = array_merge( $preview_post_ids, (array) $preview_post_id );
+ else
+ wp_die( 0 );
+
+ $ret = self::set_preview_post_ids( $preview_post_ids );
+
+ if ( ! $ret )
+ wp_die( 0 );
+
+ wp_die( 1 );
+ }
+
+ /**
+ * Registers the new query var `_ppp`.
+ *
+ * @since 2.1
+ *
+ * @return array List of query variables.
+ */
+ public static function add_query_var( $qv ) {
+ $qv[] = '_ppp';
+
+ return $qv;
+ }
+
+ /**
+ * Registers the filter to handle a public preview.
+ *
+ * Filter will be set if it's the main query, a preview, a singular page
+ * and the query var `_ppp` exists.
+ *
+ * @since 2.0.0
+ *
+ * @param object $query The WP_Query object.
+ * @return object The WP_Query object, unchanged.
+ */
+ public static function show_public_preview( $query ) {
+ if (
+ $query->is_main_query() &&
+ $query->is_preview() &&
+ $query->is_singular() &&
+ $query->get( '_ppp' )
+ )
+ add_filter( 'posts_results', array( __CLASS__, 'set_post_to_publish' ), 10, 2 );
+
+ return $query;
+ }
+
+ /**
+ * Checks if a public preview is available and allowed.
+ * Verifies the nonce and if the post id is registered for a public preview.
+ *
+ * @since 2.0.0
+ *
+ * @param int $post_id The post id.
+ * @return bool True if a public preview is allowed, false on a failure.
+ */
+ private static function public_preview_available( $post_id ) {
+ if ( empty( $post_id ) )
+ return false;
+
+ if( ! self::verify_nonce( get_query_var( '_ppp' ), 'public_post_preview_' . $post_id ) )
+ wp_die( __( 'The link has been expired!', 'ds-public-post-preview' ) );
+
+ if ( ! in_array( $post_id, get_option( 'public_post_preview', array() ) ) )
+ wp_die( __( 'No Public Preview available!', 'ds-public-post-preview' ) );
+
+ return true;
+ }
+
+ /**
+ * Sets the post status of the first post to publish, so we don't have to do anything
+ * *too* hacky to get it to load the preview.
+ *
+ * @since 2.0.0
+ *
+ * @param array $posts The post to preview.
+ */
+ public static function set_post_to_publish( $posts ) {
+ // Remove the filter again, otherwise it will be applied to other queries too.
+ remove_filter( 'posts_results', array( __CLASS__, 'set_post_to_publish' ), 10, 2 );
+
+ if ( empty( $posts ) )
+ return;
+
+ if ( self::public_preview_available( $posts[0]->ID ) )
+ $posts[0]->post_status = 'publish';
+
+ return $posts;
+ }
+
+ /**
+ * Get the time-dependent variable for nonce creation.
+ *
+ * @see wp_nonce_tick()
+ *
+ * @since 2.1
+ *
+ * @return int The time-dependent variable
+ */
+ private static function nonce_tick() {
+ $nonce_life = apply_filters( 'ppp_nonce_life', 60 * 60 * 48 ); // 48 hours
+
+ return ceil( time() / ( $nonce_life / 2 ) );
+ }
+
+ /**
+ * Creates a random, one time use token. Without an UID.
+ *
+ * @see wp_create_nonce()
+ *
+ * @since 1.0.0
+ *
+ * @param string|int $action Scalar value to add context to the nonce.
+ * @return string The one use form token
+ */
+ private static function create_nonce( $action = -1 ) {
+ $i = self::nonce_tick();
+
+ return substr( wp_hash( $i . $action, 'nonce' ), -12, 10 );
+ }
+
+ /**
+ * Verifies that correct nonce was used with time limit. Without an UID.
+ *
+ * @see wp_verify_nonce()
+ *
+ * @since 1.0.0
+ *
+ * @param string $nonce Nonce that was used in the form to verify
+ * @param string|int $action Should give context to what is taking place and be the same when nonce was created.
+ * @return bool Whether the nonce check passed or failed.
+ */
+ private static function verify_nonce( $nonce, $action = -1 ) {
+ $i = self::nonce_tick();
+
+ // Nonce generated 0-12 hours ago
+ if ( substr( wp_hash( $i . $action, 'nonce' ), -12, 10 ) == $nonce )
+ return 1;
+
+ // Nonce generated 12-24 hours ago
+ if ( substr( wp_hash( ( $i - 1 ) . $action, 'nonce' ), -12, 10 ) == $nonce )
+ return 2;
+
+ // Invalid nonce
+ return false;
+ }
+
+ /**
+ * Returns the post ids which are registered for a public preview.
+ *
+ * @since 2.0.0
+ *
+ * @return array The post ids. (Empty array if no ids are registered.)
+ */
+ private static function get_preview_post_ids() {
+ return get_option( 'public_post_preview', array() );
+ }
+
+ /**
+ * Saves the post ids which are registered for a public preview.
+ *
+ * @since 2.0.0
+ *
+ * @return array The post ids. (Empty array if no ids are registered.)
+ */
+ private static function set_preview_post_ids( $post_ids = array( )) {
+ return update_option( 'public_post_preview', $post_ids );
+ }
+
+ /**
+ * Small helper to get some plugin info.
+ *
+ * @since 2.0.0
+ *
+ * @param string $key The key to get the info from, see get_plugin_data().
+ * @return string|bool Either the value, or if the key doesn't exists false.
+ */
+ private static function get_plugin_info( $key = null ) {
+ $plugin_data = get_plugin_data( __FILE__);
+ if ( array_key_exists( $key, $plugin_data ) )
+ return $plugin_data[ $key ];
+
+ return false;
+ }
+
+ /**
+ * Delets the option 'public_post_preview' if the plugin will be uninstalled.
+ *
+ * @since 2.0.0
+ */
+ public static function uninstall() {
+ delete_option( 'public_post_preview' );
+ }
+}
+
+add_action( 'plugins_loaded', array( 'DS_Public_Post_Preview', 'init' ) );
+
+register_uninstall_hook( __FILE__, array( 'DS_Public_Post_Preview', 'uninstall' ) );
diff --git a/plugins/public-post-preview/readme.txt b/plugins/public-post-preview/readme.txt
new file mode 100644
index 00000000..9c144b84
--- /dev/null
+++ b/plugins/public-post-preview/readme.txt
@@ -0,0 +1,126 @@
+=== Public Post Preview ===
+Contributors: ocean90
+Tags: public, post, preview, posts, custom post types
+Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=VR8YU922B7K46
+Requires at least: 3.5
+Tested up to: 3.6
+Stable tag: 2.2
+License: GPLv2 or later
+License URI: http://www.gnu.org/licenses/gpl-2.0.html
+
+Enables you to give a link to anonymous users for public preview of a post before it is published.
+
+== Description ==
+
+Enables you to give a link to anonymous users for public preview of a post (or any other public post type) before it is published.
+
+Have you ever been writing a post with the help of someone who does not have access to your blog and needed to give them the ability to preview it before publishing? This plugin takes care of that by generating an URL with an expiring nonce that can be given out for public preview.
+
+**Sounds pretty good? Install now!**
+
+*Previously this plugin was maintained by [Matt Martz](http://profiles.wordpress.org/sivel/) and was an idea of [Jonathan Dingman](http://profiles.wordpress.org/jdingman/).*
+
+= Feedback =
+If you want, you can drop me a line @[ocean90](http://twitter.com/ocean90) on Twitter or @[Dominik Schilling](https://plus.google.com/101675293278434581718/) on Google+.
+
+= More =
+Try also some of my [other plugins](http://profiles.wordpress.org/users/ocean90) or visit my site [wpGrafie.de](http://wpgrafie.de/).
+
+*Thanks to Hans Dinkelberg for his [photo](http://www.flickr.com/photos/uitdragerij/7516234430/).*
+
+== Installation ==
+
+Note: There will be NO settings page.
+
+For an automatic installation through WordPress:
+
+1. Go to the 'Add New' plugins screen in your WordPress admin area
+1. Search for 'Public Post Preview'
+1. Click 'Install Now' and activate the plugin
+
+
+For a manual installation via FTP:
+
+1. Upload the `public-post-preview` directory to the `/wp-content/plugins/` directory
+1. Activate the plugin through the 'Plugins' screen in your WordPress admin area
+
+
+To upload the plugin through WordPress, instead of FTP:
+
+1. Upload the downloaded zip file on the 'Add New' plugins screen (see the 'Upload' tab) in your WordPress admin area and activate.
+
+== Screenshots ==
+
+1. Edit Posts Page
+
+== Upgrade Notice ==
+
+= 2.2 =
+Based on feedback: Removed the extra metabox and added preview link to the main Publish metabox. Requires now WordPress 3.5
+
+= 2.1 =
+The update fixes a rare issue which had created 404 errors.
+
+= 2.0 =
+New plugin maintainer, supports now all public post types, saves preview status via an AJAX request, ready for translation, requires at least WordPress 3.3.
+
+== Usage ==
+* To enable a public post preview check the box below the edit post box.
+* The link will be displayed if the checkbox is checked, just copy and share the link with your frieds.
+* To disable a preview just uncheck the box.
+
+== Frequently Asked Questions ==
+
+**I have activated the "WordPress SEO by Yoast" plugin and enabled the option "Redirect ugly URL's to clean permalinks.". The public preview doesn't work. What can I do?**
+
+Please add <strong>_ppp</strong> to the input field "Other variables not to clean:" on SEO -> Permalinks screen.
+
+
+**After some time the preview link returns the message "The link has been expired!". Why?**
+
+The plugin generates an URL with an expiring nonce. By default a link "lives" 48 hours. After 48 hours the link is expired and you need to copy and share a new link which is automatically generated on the same place under the editor.
+
+
+**48 hours are not enough to me. Can I extend the nonce time?**
+
+Yes, of course. You can use the filter `ppp_nonce_life`. Example for 5 days:
+
+`add_filter( 'ppp_nonce_life', 'my_nonce_life' );
+function my_nonce_life() {
+ return 60 * 60 * 24 * 5; // 5 days
+}`
+
+== Change Log ==
+= 2.2 (20013-03-15): =
+* Based on feedback I have removed the extra metabox and added the preview link to the main Publish metabox
+* Only shows the checkbox if the post status/post type is good
+* Requires now WordPress 3.5
+
+= 2.1.1 (20012-09-19): =
+* Sorry for the new update. Through a change in 2.1 a filter was applied to each query. The misplaced "The link has been expired!" message is now gone. Props Aki Björklund and Jonathan Channon.
+
+= 2.1 (20012-09-16): =
+* Introduces a filter `ppp_nonce_life`. With the filter you can adjust the expiration of a link. By default a link has a lifetime of 48 hours.
+* In some situations (still not sure when) the preview link is rewritten as a permalink which results in an error. The plugin now works in this situations too.
+
+= 2.0.1 (20012-07-25): =
+* Makes the preview link copyable again
+
+= 2.0 (20012-07-23): =
+* Support for all public post types
+* Saves public preview status via an AJAX request
+* I18n
+* Requires at least WordPress 3.3
+
+= 1.3 (2009-06-30): =
+* Hook in earlier in the post selection process to fix PHP notices
+* Add uninstall functionality to remove options from the options table
+
+= 1.2 (2009-03-30): =
+* Fix preview URL for scheduled posts on sites with a permalink other than default activated.
+
+= 1.1 (2009-03-11): =
+* Don't limit public previews to posts in draft or pending status. Just exclude posts in publish status.
+
+= 1.0 (2009-02-20): =
+* Initial Public Release