Public Post Preview - Version 2.5.0

Version Description

(2016-04-05): = * Auto select preview link on focus. Props @JeroenSormani. * Remove preview status from posts which are trashed or after scheduled posts are published. * Add support for paged posts.

Download this release

Release Info

Developer ocean90
Plugin Icon 128x128 Public Post Preview
Version 2.5.0
Comparing to
See all releases

Code changes from version 2.4.1 to 2.5.0

js/public-post-preview.js CHANGED
@@ -19,6 +19,10 @@
19
  t.checkbox.bind( 'change', function() {
20
  t.change();
21
  } );
 
 
 
 
22
  },
23
 
24
  /**
@@ -66,7 +70,7 @@
66
  * @since 2.0.0
67
  *
68
  * @param {Object} data The data to send.
69
- * @param {Object} callback Callback function for a successfull request.
70
  */
71
  request : function( data, callback ) {
72
  $.ajax( {
19
  t.checkbox.bind( 'change', function() {
20
  t.change();
21
  } );
22
+
23
+ t.link.find( 'input' ).on( 'focus', function() {
24
+ $( this ).select();
25
+ } );
26
  },
27
 
28
  /**
70
  * @since 2.0.0
71
  *
72
  * @param {Object} data The data to send.
73
+ * @param {Object} callback Callback function for a successful request.
74
  */
75
  request : function( data, callback ) {
76
  $.ajax( {
js/public-post-preview.min.js CHANGED
@@ -1 +1 @@
1
- (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);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);
1
+ (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);b.checkbox.bind("change",function(){b.change();});b.link.find("input").on("focus",function(){a(this).select();});},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);
public-post-preview.php CHANGED
@@ -1,7 +1,7 @@
1
  <?php
2
  /**
3
  * Plugin Name: Public Post Preview
4
- * Version: 2.4.1
5
  * Description: Enables you to give a link to anonymous users for public preview of any post type before it is published.
6
  * Author: Dominik Schilling
7
  * Author URI: http://wphelper.de/
@@ -13,7 +13,7 @@
13
  *
14
  * Previously (2009-2011) maintained by Jonathan Dingman and Matt Martz.
15
  *
16
- * Copyright (C) 2012-2014 Dominik Schilling
17
  *
18
  * This program is free software; you can redistribute it and/or
19
  * modify it under the terms of the GNU General Public License
@@ -40,50 +40,30 @@ if ( ! class_exists( 'WP' ) ) {
40
  /**
41
  * The class which controls the plugin.
42
  *
43
- * Used hooks:
44
- * - pre_get_posts
45
- * - query_vars
46
- * - init
47
- * - post_submitbox_misc_actions
48
- * - save_post
49
- * - posts_results
50
- * - wp_ajax_public-post-preview
51
- * - admin_enqueue_scripts
52
- * - comments_open
53
- * - pings_open
54
- *
55
  * Inits at 'plugins_loaded' hook.
56
- *
57
  */
58
  class DS_Public_Post_Preview {
59
 
60
  /**
61
- * Hooks into 'pre_get_posts' to handle public preview, only nn-admin
62
- * Hooks into 'add_meta_boxes' to register the meta box.
63
- * Hooks into 'save_post' to handle the values of the meta box.
64
- * Hooks into 'admin_enqueue_scripts' to register JavaScript.
65
  *
66
  * @since 1.0.0
67
  */
68
  public static function init() {
69
  add_action( 'init', array( __CLASS__, 'load_textdomain' ) );
 
 
70
 
71
  if ( ! is_admin() ) {
72
  add_filter( 'pre_get_posts', array( __CLASS__, 'show_public_preview' ) );
73
-
74
  add_filter( 'query_vars', array( __CLASS__, 'add_query_var' ) );
75
-
76
  // Add the query var to WordPress SEO by Yoast whitelist.
77
  add_filter( 'wpseo_whitelist_permalink_vars', array( __CLASS__, 'add_query_var' ) );
78
  } else {
79
  add_action( 'post_submitbox_misc_actions', array( __CLASS__, 'post_submitbox_misc_actions' ) );
80
-
81
  add_action( 'save_post', array( __CLASS__, 'register_public_preview' ), 20, 2 );
82
-
83
  add_action( 'wp_ajax_public-post-preview', array( __CLASS__, 'ajax_register_public_preview' ) );
84
-
85
  add_action( 'admin_enqueue_scripts' , array( __CLASS__, 'enqueue_script' ) );
86
-
87
  add_filter( 'display_post_states', array( __CLASS__, 'display_preview_state' ), 20, 2 );
88
  }
89
  }
@@ -101,6 +81,8 @@ class DS_Public_Post_Preview {
101
  * Registers the JavaScript file for post(-new).php.
102
  *
103
  * @since 2.0.0
 
 
104
  */
105
  public static function enqueue_script( $hook_suffix ) {
106
  if ( ! in_array( $hook_suffix, array( 'post.php', 'post-new.php' ) ) ) {
@@ -113,7 +95,7 @@ class DS_Public_Post_Preview {
113
  'public-post-preview',
114
  plugins_url( "js/public-post-preview$suffix.js", __FILE__ ),
115
  array( 'jquery' ),
116
- self::get_plugin_info( 'Version' ),
117
  true
118
  );
119
 
@@ -122,7 +104,7 @@ class DS_Public_Post_Preview {
122
  'DSPublicPostPreviewL10n',
123
  array(
124
  'enabled' => __( 'Enabled!', 'public-post-preview' ),
125
- 'disabled' => __( 'Disabled!', 'public-post-preview' )
126
  )
127
  );
128
  }
@@ -131,6 +113,10 @@ class DS_Public_Post_Preview {
131
  * Adds "Public Preview" to the list of display states used in the Posts list table.
132
  *
133
  * @since 2.4.0
 
 
 
 
134
  */
135
  public static function display_preview_state( $post_states, $post ) {
136
  if ( in_array( $post->ID, self::get_preview_post_ids() ) ) {
@@ -148,7 +134,7 @@ class DS_Public_Post_Preview {
148
  public static function post_submitbox_misc_actions() {
149
  $post_types = get_post_types(
150
  array(
151
- 'public' => true
152
  )
153
  );
154
 
@@ -158,12 +144,12 @@ class DS_Public_Post_Preview {
158
  return false;
159
  }
160
 
161
- // Do nothing for auto drafts
162
- if ( $post->post_status == 'auto-draft' ) {
163
  return false;
164
  }
165
 
166
- // Post is already published
167
  if ( in_array( $post->post_status, self::get_published_statuses() ) ) {
168
  return false;
169
  }
@@ -179,7 +165,7 @@ class DS_Public_Post_Preview {
179
  /**
180
  * Returns post statuses which represent a published post.
181
  *
182
- * @since 2.4.0
183
  *
184
  * @return array List with post statuses.
185
  */
@@ -192,9 +178,9 @@ class DS_Public_Post_Preview {
192
  /**
193
  * Prints the checkbox with the input field for the preview link.
194
  *
195
- * @since 2.0.0
196
  *
197
- * @param WP_Post $post The post object.
198
  */
199
  private static function get_checkbox_html( $post ) {
200
  if ( empty( $post ) ) {
@@ -204,12 +190,12 @@ class DS_Public_Post_Preview {
204
  wp_nonce_field( 'public_post_preview', 'public_post_preview_wpnonce' );
205
 
206
  $preview_post_ids = self::get_preview_post_ids();
207
- $enabeld = in_array( $post->ID, $preview_post_ids );
208
  ?>
209
- <label><input type="checkbox"<?php checked( $enabeld ); ?> name="public_post_preview" id="public-post-preview" value="1" />
210
  <?php _e( 'Enable public preview', 'public-post-preview' ); ?> <span id="public-post-preview-ajax"></span></label>
211
 
212
- <div id="public-post-preview-link" style="margin-top:6px"<?php echo $enabeld ? '' : ' class="hidden"'; ?>>
213
  <label>
214
  <input type="text" name="public_post_preview_link" class="regular-text" value="<?php echo esc_attr( self::get_preview_link( $post ) ); ?>" style="width:99%" readonly />
215
  <span class="description"><?php _e( '(Copy and share this link.)', 'public-post-preview' ); ?></span>
@@ -219,18 +205,18 @@ class DS_Public_Post_Preview {
219
  }
220
 
221
  /**
222
- * Returns the public preview link.
223
- *
224
- * The link is the home link with these parameters:
225
- * - preview, always true (query var for core)
226
- * - _ppp, a custom nonce, see DS_Public_Post_Preview::create_nonce()
227
- * - page_id or p or p and post_type to specify the post.
228
- *
229
- * @since 2.0.0
230
- *
231
- * @param WP_Post $post The post object.
232
- * @return string The generated public preview link.
233
- */
234
  private static function get_preview_link( $post ) {
235
  if ( 'page' == $post->post_type ) {
236
  $args = array(
@@ -260,11 +246,11 @@ class DS_Public_Post_Preview {
260
  *
261
  * Don't runs on an autosave and ignores post revisions.
262
  *
263
- * @since 2.0.0
264
  *
265
- * @param int $post_id The post id.
266
- * @param object $post The post object.
267
- * @return bool Returns false on a failure, true on a success.
268
  */
269
  public static function register_public_preview( $post_id, $post ) {
270
  if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
@@ -285,12 +271,11 @@ class DS_Public_Post_Preview {
285
  if ( empty( $_POST['public_post_preview'] ) && in_array( $preview_post_id, $preview_post_ids ) ) {
286
  $preview_post_ids = array_diff( $preview_post_ids, (array) $preview_post_id );
287
  } elseif (
288
- ! empty( $_POST['public_post_preview'] ) &&
289
- ! empty( $_POST['original_post_status'] ) &&
290
- 'publish' != $_POST['original_post_status'] &&
291
- 'publish' == $post->post_status &&
292
- in_array( $preview_post_id, $preview_post_ids )
293
- ) {
294
  $preview_post_ids = array_diff( $preview_post_ids, (array) $preview_post_id );
295
  } elseif ( ! empty( $_POST['public_post_preview'] ) && ! in_array( $preview_post_id, $preview_post_ids ) ) {
296
  $preview_post_ids = array_merge( $preview_post_ids, (array) $preview_post_id );
@@ -301,12 +286,74 @@ class DS_Public_Post_Preview {
301
  return self::set_preview_post_ids( $preview_post_ids );
302
  }
303
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
304
  /**
305
  * (Un)Registers a post for a public preview for an AJAX request.
306
  *
307
- * @since 2.0.0
308
  *
309
- * @return string Returns '0' on a failure, '1' on success.
310
  */
311
  public static function ajax_register_public_preview() {
312
  check_ajax_referer( 'public_post_preview' );
@@ -344,8 +391,9 @@ class DS_Public_Post_Preview {
344
  /**
345
  * Registers the new query var `_ppp`.
346
  *
347
- * @since 2.1.0
348
  *
 
349
  * @return array List of query variables.
350
  */
351
  public static function add_query_var( $qv ) {
@@ -360,10 +408,10 @@ class DS_Public_Post_Preview {
360
  * Filter will be set if it's the main query, a preview, a singular page
361
  * and the query var `_ppp` exists.
362
  *
363
- * @since 2.0.0
364
  *
365
- * @param object $query The WP_Query object.
366
- * @return object The WP_Query object, unchanged.
367
  */
368
  public static function show_public_preview( $query ) {
369
  if (
@@ -382,10 +430,10 @@ class DS_Public_Post_Preview {
382
  * Checks if a public preview is available and allowed.
383
  * Verifies the nonce and if the post id is registered for a public preview.
384
  *
385
- * @since 2.0.0
386
  *
387
- * @param int $post_id The post id.
388
- * @return bool True if a public preview is allowed, false on a failure.
389
  */
390
  private static function is_public_preview_available( $post_id ) {
391
  if ( empty( $post_id ) ) {
@@ -403,17 +451,40 @@ class DS_Public_Post_Preview {
403
  return true;
404
  }
405
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
406
  /**
407
  * Sets the post status of the first post to publish, so we don't have to do anything
408
  * *too* hacky to get it to load the preview.
409
  *
410
  * @since 2.0.0
411
  *
412
- * @param array $posts The post to preview.
 
413
  */
414
  public static function set_post_to_publish( $posts ) {
415
  // Remove the filter again, otherwise it will be applied to other queries too.
416
- remove_filter( 'posts_results', array( __CLASS__, 'set_post_to_publish' ), 10, 2 );
417
 
418
  if ( empty( $posts ) ) {
419
  return;
@@ -421,16 +492,17 @@ class DS_Public_Post_Preview {
421
 
422
  $post_id = $posts[0]->ID;
423
 
424
- // If the post has gone live, redirect to it's proper permalink
425
  self::maybe_redirect_to_published_post( $post_id );
426
 
427
  if ( self::is_public_preview_available( $post_id ) ) {
428
- // Set post status to publish so that it's visible
429
  $posts[0]->post_status = 'publish';
430
 
431
- // Disable comments and pings for this post
432
  add_filter( 'comments_open', '__return_false' );
433
  add_filter( 'pings_open', '__return_false' );
 
434
  }
435
 
436
  return $posts;
@@ -441,7 +513,8 @@ class DS_Public_Post_Preview {
441
  *
442
  * @since 2.0.0
443
  *
444
- * @param int $post_id The post id.
 
445
  */
446
  private static function maybe_redirect_to_published_post( $post_id ) {
447
  if ( ! in_array( get_post_status( $post_id ), self::get_published_statuses() ) ) {
@@ -455,11 +528,11 @@ class DS_Public_Post_Preview {
455
  /**
456
  * Get the time-dependent variable for nonce creation.
457
  *
458
- * @see wp_nonce_tick()
459
  *
460
- * @since 2.1
461
  *
462
- * @return int The time-dependent variable
463
  */
464
  private static function nonce_tick() {
465
  $nonce_life = apply_filters( 'ppp_nonce_life', 60 * 60 * 48 ); // 48 hours
@@ -470,12 +543,12 @@ class DS_Public_Post_Preview {
470
  /**
471
  * Creates a random, one time use token. Without an UID.
472
  *
473
- * @see wp_create_nonce()
474
  *
475
- * @since 1.0.0
476
  *
477
  * @param string|int $action Scalar value to add context to the nonce.
478
- * @return string The one use form token
479
  */
480
  private static function create_nonce( $action = -1 ) {
481
  $i = self::nonce_tick();
@@ -486,35 +559,35 @@ class DS_Public_Post_Preview {
486
  /**
487
  * Verifies that correct nonce was used with time limit. Without an UID.
488
  *
489
- * @see wp_verify_nonce()
490
  *
491
- * @since 1.0.0
492
  *
493
- * @param string $nonce Nonce that was used in the form to verify
494
- * @param string|int $action Should give context to what is taking place and be the same when nonce was created.
495
  * @return bool Whether the nonce check passed or failed.
496
  */
497
  private static function verify_nonce( $nonce, $action = -1 ) {
498
  $i = self::nonce_tick();
499
 
500
- // Nonce generated 0-12 hours ago
501
  if ( substr( wp_hash( $i . $action, 'nonce' ), -12, 10 ) == $nonce ) {
502
  return 1;
503
  }
504
 
505
- // Nonce generated 12-24 hours ago
506
  if ( substr( wp_hash( ( $i - 1 ) . $action, 'nonce' ), -12, 10 ) == $nonce ) {
507
  return 2;
508
  }
509
 
510
- // Invalid nonce
511
  return false;
512
  }
513
 
514
  /**
515
  * Returns the post ids which are registered for a public preview.
516
  *
517
- * @since 2.0.0
518
  *
519
  * @return array The post ids. (Empty array if no ids are registered.)
520
  */
@@ -525,33 +598,17 @@ class DS_Public_Post_Preview {
525
  /**
526
  * Saves the post ids which are registered for a public preview.
527
  *
528
- * @since 2.0.0
529
  *
 
530
  * @return array The post ids. (Empty array if no ids are registered.)
531
  */
532
- private static function set_preview_post_ids( $post_ids = array( )) {
533
  return update_option( 'public_post_preview', $post_ids );
534
  }
535
 
536
  /**
537
- * Small helper to get some plugin info.
538
- *
539
- * @since 2.0.0
540
- *
541
- * @param string $key The key to get the info from, see get_plugin_data().
542
- * @return string|bool Either the value, or if the key doesn't exists false.
543
- */
544
- private static function get_plugin_info( $key = null ) {
545
- $plugin_data = get_plugin_data( __FILE__);
546
- if ( array_key_exists( $key, $plugin_data ) ) {
547
- return $plugin_data[ $key ];
548
- }
549
-
550
- return false;
551
- }
552
-
553
- /**
554
- * Delets the option 'public_post_preview' if the plugin will be uninstalled.
555
  *
556
  * @since 2.0.0
557
  */
1
  <?php
2
  /**
3
  * Plugin Name: Public Post Preview
4
+ * Version: 2.5.0
5
  * Description: Enables you to give a link to anonymous users for public preview of any post type before it is published.
6
  * Author: Dominik Schilling
7
  * Author URI: http://wphelper.de/
13
  *
14
  * Previously (2009-2011) maintained by Jonathan Dingman and Matt Martz.
15
  *
16
+ * Copyright (C) 2012-2016 Dominik Schilling
17
  *
18
  * This program is free software; you can redistribute it and/or
19
  * modify it under the terms of the GNU General Public License
40
  /**
41
  * The class which controls the plugin.
42
  *
 
 
 
 
 
 
 
 
 
 
 
 
43
  * Inits at 'plugins_loaded' hook.
 
44
  */
45
  class DS_Public_Post_Preview {
46
 
47
  /**
48
+ * Registers actions and filters.
 
 
 
49
  *
50
  * @since 1.0.0
51
  */
52
  public static function init() {
53
  add_action( 'init', array( __CLASS__, 'load_textdomain' ) );
54
+ add_action( 'transition_post_status', array( __CLASS__, 'unregister_public_preview_on_status_change' ), 20, 3 );
55
+ add_action( 'post_updated', array( __CLASS__, 'unregister_public_preview_on_edit' ), 20, 2 );
56
 
57
  if ( ! is_admin() ) {
58
  add_filter( 'pre_get_posts', array( __CLASS__, 'show_public_preview' ) );
 
59
  add_filter( 'query_vars', array( __CLASS__, 'add_query_var' ) );
 
60
  // Add the query var to WordPress SEO by Yoast whitelist.
61
  add_filter( 'wpseo_whitelist_permalink_vars', array( __CLASS__, 'add_query_var' ) );
62
  } else {
63
  add_action( 'post_submitbox_misc_actions', array( __CLASS__, 'post_submitbox_misc_actions' ) );
 
64
  add_action( 'save_post', array( __CLASS__, 'register_public_preview' ), 20, 2 );
 
65
  add_action( 'wp_ajax_public-post-preview', array( __CLASS__, 'ajax_register_public_preview' ) );
 
66
  add_action( 'admin_enqueue_scripts' , array( __CLASS__, 'enqueue_script' ) );
 
67
  add_filter( 'display_post_states', array( __CLASS__, 'display_preview_state' ), 20, 2 );
68
  }
69
  }
81
  * Registers the JavaScript file for post(-new).php.
82
  *
83
  * @since 2.0.0
84
+ *
85
+ * @param string $hook_suffix Unique page identifier.
86
  */
87
  public static function enqueue_script( $hook_suffix ) {
88
  if ( ! in_array( $hook_suffix, array( 'post.php', 'post-new.php' ) ) ) {
95
  'public-post-preview',
96
  plugins_url( "js/public-post-preview$suffix.js", __FILE__ ),
97
  array( 'jquery' ),
98
+ '20160403',
99
  true
100
  );
101
 
104
  'DSPublicPostPreviewL10n',
105
  array(
106
  'enabled' => __( 'Enabled!', 'public-post-preview' ),
107
+ 'disabled' => __( 'Disabled!', 'public-post-preview' ),
108
  )
109
  );
110
  }
113
  * Adds "Public Preview" to the list of display states used in the Posts list table.
114
  *
115
  * @since 2.4.0
116
+ *
117
+ * @param array $post_states An array of post display states.
118
+ * @param WP_Post $post The current post object.
119
+ * @return Filtered array of post display states.
120
  */
121
  public static function display_preview_state( $post_states, $post ) {
122
  if ( in_array( $post->ID, self::get_preview_post_ids() ) ) {
134
  public static function post_submitbox_misc_actions() {
135
  $post_types = get_post_types(
136
  array(
137
+ 'public' => true,
138
  )
139
  );
140
 
144
  return false;
145
  }
146
 
147
+ // Do nothing for auto drafts.
148
+ if ( 'auto-draft' === $post->post_status ) {
149
  return false;
150
  }
151
 
152
+ // Post is already published.
153
  if ( in_array( $post->post_status, self::get_published_statuses() ) ) {
154
  return false;
155
  }
165
  /**
166
  * Returns post statuses which represent a published post.
167
  *
168
+ * @since 2.4.0
169
  *
170
  * @return array List with post statuses.
171
  */
178
  /**
179
  * Prints the checkbox with the input field for the preview link.
180
  *
181
+ * @since 2.0.0
182
  *
183
+ * @param WP_Post $post The post object.
184
  */
185
  private static function get_checkbox_html( $post ) {
186
  if ( empty( $post ) ) {
190
  wp_nonce_field( 'public_post_preview', 'public_post_preview_wpnonce' );
191
 
192
  $preview_post_ids = self::get_preview_post_ids();
193
+ $enabled = in_array( $post->ID, $preview_post_ids );
194
  ?>
195
+ <label><input type="checkbox"<?php checked( $enabled ); ?> name="public_post_preview" id="public-post-preview" value="1" />
196
  <?php _e( 'Enable public preview', 'public-post-preview' ); ?> <span id="public-post-preview-ajax"></span></label>
197
 
198
+ <div id="public-post-preview-link" style="margin-top:6px"<?php echo $enabled ? '' : ' class="hidden"'; ?>>
199
  <label>
200
  <input type="text" name="public_post_preview_link" class="regular-text" value="<?php echo esc_attr( self::get_preview_link( $post ) ); ?>" style="width:99%" readonly />
201
  <span class="description"><?php _e( '(Copy and share this link.)', 'public-post-preview' ); ?></span>
205
  }
206
 
207
  /**
208
+ * Returns the public preview link.
209
+ *
210
+ * The link is the home link with these parameters:
211
+ * - preview, always true (query var for core)
212
+ * - _ppp, a custom nonce, see DS_Public_Post_Preview::create_nonce()
213
+ * - page_id or p or p and post_type to specify the post.
214
+ *
215
+ * @since 2.0.0
216
+ *
217
+ * @param WP_Post $post The post object.
218
+ * @return string The generated public preview link.
219
+ */
220
  private static function get_preview_link( $post ) {
221
  if ( 'page' == $post->post_type ) {
222
  $args = array(
246
  *
247
  * Don't runs on an autosave and ignores post revisions.
248
  *
249
+ * @since 2.0.0
250
  *
251
+ * @param int $post_id The post id.
252
+ * @param object $post The post object.
253
+ * @return bool Returns false on a failure, true on a success.
254
  */
255
  public static function register_public_preview( $post_id, $post ) {
256
  if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
271
  if ( empty( $_POST['public_post_preview'] ) && in_array( $preview_post_id, $preview_post_ids ) ) {
272
  $preview_post_ids = array_diff( $preview_post_ids, (array) $preview_post_id );
273
  } elseif (
274
+ ! empty( $_POST['public_post_preview'] ) &&
275
+ ! empty( $_POST['original_post_status'] ) &&
276
+ ! in_array( $_POST['original_post_status'], self::get_published_statuses() ) &&
277
+ in_array( $post->post_status, self::get_published_statuses() )
278
+ ) {
 
279
  $preview_post_ids = array_diff( $preview_post_ids, (array) $preview_post_id );
280
  } elseif ( ! empty( $_POST['public_post_preview'] ) && ! in_array( $preview_post_id, $preview_post_ids ) ) {
281
  $preview_post_ids = array_merge( $preview_post_ids, (array) $preview_post_id );
286
  return self::set_preview_post_ids( $preview_post_ids );
287
  }
288
 
289
+ /**
290
+ * Unregisters a post for public preview when a (scheduled) post gets published
291
+ * or trashed.
292
+ *
293
+ * @since 2.5.0
294
+ *
295
+ * @param string $new_status New post status.
296
+ * @param string $old_status Old post status.
297
+ * @param WP_Post $post Post object.
298
+ * @return bool Returns false on a failure, true on a success.
299
+ */
300
+ public static function unregister_public_preview_on_status_change( $new_status, $old_status, $post ) {
301
+ $disallowed_status = self::get_published_statuses();
302
+ $disallowed_status[] = 'trash';
303
+
304
+ if ( in_array( $new_status, $disallowed_status ) ) {
305
+ return self::unregister_public_preview( $post->ID );
306
+ }
307
+
308
+ return false;
309
+ }
310
+
311
+ /**
312
+ * Unregisters a post for public preview when a post gets published or trashed.
313
+ *
314
+ * @since 2.5.0
315
+ *
316
+ * @param int $post_id Post ID.
317
+ * @param WP_Post $post Post object.
318
+ * @return bool Returns false on a failure, true on a success.
319
+ */
320
+ public static function unregister_public_preview_on_edit( $post_id, $post ) {
321
+ $disallowed_status = self::get_published_statuses();
322
+ $disallowed_status[] = 'trash';
323
+
324
+ if ( in_array( $post->post_status, $disallowed_status ) ) {
325
+ return self::unregister_public_preview( $post_id );
326
+ }
327
+
328
+ return false;
329
+ }
330
+
331
+ /**
332
+ * Unregisters a post for public preview.
333
+ *
334
+ * @since 2.5.0
335
+ *
336
+ * @param int $post_id Post ID.
337
+ * @return bool Returns false on a failure, true on a success.
338
+ */
339
+ private static function unregister_public_preview( $post_id ) {
340
+ $preview_post_ids = self::get_preview_post_ids();
341
+
342
+ if ( ! in_array( $post_id, $preview_post_ids ) ) {
343
+ return false;
344
+ }
345
+
346
+ $preview_post_ids = array_diff( $preview_post_ids, (array) $post_id );
347
+
348
+ return self::set_preview_post_ids( $preview_post_ids );
349
+ }
350
+
351
  /**
352
  * (Un)Registers a post for a public preview for an AJAX request.
353
  *
354
+ * Returns '0' on a failure, '1' on success.
355
  *
356
+ * @since 2.0.0
357
  */
358
  public static function ajax_register_public_preview() {
359
  check_ajax_referer( 'public_post_preview' );
391
  /**
392
  * Registers the new query var `_ppp`.
393
  *
394
+ * @since 2.1.0
395
  *
396
+ * @param array $qv Existing list of query variables.
397
  * @return array List of query variables.
398
  */
399
  public static function add_query_var( $qv ) {
408
  * Filter will be set if it's the main query, a preview, a singular page
409
  * and the query var `_ppp` exists.
410
  *
411
+ * @since 2.0.0
412
  *
413
+ * @param object $query The WP_Query object.
414
+ * @return object The WP_Query object, unchanged.
415
  */
416
  public static function show_public_preview( $query ) {
417
  if (
430
  * Checks if a public preview is available and allowed.
431
  * Verifies the nonce and if the post id is registered for a public preview.
432
  *
433
+ * @since 2.0.0
434
  *
435
+ * @param int $post_id The post id.
436
+ * @return bool True if a public preview is allowed, false on a failure.
437
  */
438
  private static function is_public_preview_available( $post_id ) {
439
  if ( empty( $post_id ) ) {
451
  return true;
452
  }
453
 
454
+ /**
455
+ * Filters the HTML output of individual page number links to use the
456
+ * preview link.
457
+ *
458
+ * @since 2.5.0
459
+ *
460
+ * @param string $link The page number HTML output.
461
+ * @param int $page_number Page number for paginated posts' page links.
462
+ * @return string The filtered HTML output.
463
+ */
464
+ public static function filter_wp_link_pages_link( $link, $page_number ) {
465
+ $post = get_post();
466
+ if ( ! $post ) {
467
+ return $link;
468
+ }
469
+
470
+ $preview_link = self::get_preview_link( $post );
471
+ $preview_link = add_query_arg( 'page', $page_number, $preview_link );
472
+
473
+ return preg_replace( '~href=(["|\'])(.+?)\1~', 'href=$1' . $preview_link . '$1', $link );
474
+ }
475
+
476
  /**
477
  * Sets the post status of the first post to publish, so we don't have to do anything
478
  * *too* hacky to get it to load the preview.
479
  *
480
  * @since 2.0.0
481
  *
482
+ * @param array $posts The post to preview.
483
+ * @return array The post that is being previewed.
484
  */
485
  public static function set_post_to_publish( $posts ) {
486
  // Remove the filter again, otherwise it will be applied to other queries too.
487
+ remove_filter( 'posts_results', array( __CLASS__, 'set_post_to_publish' ), 10 );
488
 
489
  if ( empty( $posts ) ) {
490
  return;
492
 
493
  $post_id = $posts[0]->ID;
494
 
495
+ // If the post has gone live, redirect to it's proper permalink.
496
  self::maybe_redirect_to_published_post( $post_id );
497
 
498
  if ( self::is_public_preview_available( $post_id ) ) {
499
+ // Set post status to publish so that it's visible.
500
  $posts[0]->post_status = 'publish';
501
 
502
+ // Disable comments and pings for this post.
503
  add_filter( 'comments_open', '__return_false' );
504
  add_filter( 'pings_open', '__return_false' );
505
+ add_filter( 'wp_link_pages_link', array( __CLASS__, 'filter_wp_link_pages_link' ), 10, 2 );
506
  }
507
 
508
  return $posts;
513
  *
514
  * @since 2.0.0
515
  *
516
+ * @param int $post_id The post id.
517
+ * @return false False of post status is not a published status.
518
  */
519
  private static function maybe_redirect_to_published_post( $post_id ) {
520
  if ( ! in_array( get_post_status( $post_id ), self::get_published_statuses() ) ) {
528
  /**
529
  * Get the time-dependent variable for nonce creation.
530
  *
531
+ * @see wp_nonce_tick()
532
  *
533
+ * @since 2.1.0
534
  *
535
+ * @return int The time-dependent variable.
536
  */
537
  private static function nonce_tick() {
538
  $nonce_life = apply_filters( 'ppp_nonce_life', 60 * 60 * 48 ); // 48 hours
543
  /**
544
  * Creates a random, one time use token. Without an UID.
545
  *
546
+ * @see wp_create_nonce()
547
  *
548
+ * @since 1.0.0
549
  *
550
  * @param string|int $action Scalar value to add context to the nonce.
551
+ * @return string The one use form token.
552
  */
553
  private static function create_nonce( $action = -1 ) {
554
  $i = self::nonce_tick();
559
  /**
560
  * Verifies that correct nonce was used with time limit. Without an UID.
561
  *
562
+ * @see wp_verify_nonce()
563
  *
564
+ * @since 1.0.0
565
  *
566
+ * @param string $nonce Nonce that was used in the form to verify.
567
+ * @param string|int $action Should give context to what is taking place and be the same when nonce was created.
568
  * @return bool Whether the nonce check passed or failed.
569
  */
570
  private static function verify_nonce( $nonce, $action = -1 ) {
571
  $i = self::nonce_tick();
572
 
573
+ // Nonce generated 0-12 hours ago.
574
  if ( substr( wp_hash( $i . $action, 'nonce' ), -12, 10 ) == $nonce ) {
575
  return 1;
576
  }
577
 
578
+ // Nonce generated 12-24 hours ago.
579
  if ( substr( wp_hash( ( $i - 1 ) . $action, 'nonce' ), -12, 10 ) == $nonce ) {
580
  return 2;
581
  }
582
 
583
+ // Invalid nonce.
584
  return false;
585
  }
586
 
587
  /**
588
  * Returns the post ids which are registered for a public preview.
589
  *
590
+ * @since 2.0.0
591
  *
592
  * @return array The post ids. (Empty array if no ids are registered.)
593
  */
598
  /**
599
  * Saves the post ids which are registered for a public preview.
600
  *
601
+ * @since 2.0.0
602
  *
603
+ * @param array $post_ids List of post IDs that have a preview.
604
  * @return array The post ids. (Empty array if no ids are registered.)
605
  */
606
+ private static function set_preview_post_ids( $post_ids = array() ) {
607
  return update_option( 'public_post_preview', $post_ids );
608
  }
609
 
610
  /**
611
+ * Deletes the option 'public_post_preview' if the plugin will be uninstalled.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
612
  *
613
  * @since 2.0.0
614
  */
readme.txt CHANGED
@@ -3,8 +3,8 @@ Contributors: ocean90
3
  Tags: public, post, preview, posts, custom post types, draft
4
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=VR8YU922B7K46
5
  Requires at least: 3.5
6
- Tested up to: 4.4
7
- Stable tag: 2.4.1
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -16,17 +16,7 @@ Enables you to give a link to anonymous users for public preview of a post (or a
16
 
17
  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.
18
 
19
- **Sounds pretty good? Install now!**
20
-
21
- *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/).*
22
-
23
- = Feedback =
24
- If you want, you can drop me a line @[ocean90](http://twitter.com/ocean90) on Twitter or @[Dominik Schilling](https://plus.google.com/+DominikSchilling/) on Google+.
25
-
26
- = More =
27
- Try also some of my [other plugins](http://profiles.wordpress.org/users/ocean90) or visit my site [wpGrafie.de](http://wpgrafie.de/).
28
-
29
- *Thanks to Hans Dinkelberg for his [photo](http://www.flickr.com/photos/uitdragerij/7516234430/).*
30
 
31
  == Installation ==
32
 
@@ -60,6 +50,11 @@ To upload the plugin through WordPress, instead of FTP:
60
 
61
  == Frequently Asked Questions ==
62
 
 
 
 
 
 
63
  **After some time the preview link returns the message "The link has been expired!". Why?**
64
 
65
  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.
@@ -77,6 +72,11 @@ function my_nonce_life() {
77
  Or use the [Public Post Preview Configurator](https://wordpress.org/plugins/public-post-preview-configurator/).
78
 
79
  == Change Log ==
 
 
 
 
 
80
  = 2.4.1 (2015-10-13): =
81
  * Update text domain to support language packs. Translations are now managed via http://translate.wordpress.org/projects/wp-plugins/public-post-preview.
82
 
3
  Tags: public, post, preview, posts, custom post types, draft
4
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=VR8YU922B7K46
5
  Requires at least: 3.5
6
+ Tested up to: 4.7
7
+ Stable tag: 2.5.0
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
16
 
17
  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.
18
 
19
+ *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/). Thanks to Hans Dinkelberg for his [photo](http://www.flickr.com/photos/uitdragerij/7516234430/).*
 
 
 
 
 
 
 
 
 
 
20
 
21
  == Installation ==
22
 
50
 
51
  == Frequently Asked Questions ==
52
 
53
+ **I can't find the option for preview links. Where is it?**
54
+
55
+ The checkbox is only available for non-published posts and once a post was saved as a draft.
56
+
57
+
58
  **After some time the preview link returns the message "The link has been expired!". Why?**
59
 
60
  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.
72
  Or use the [Public Post Preview Configurator](https://wordpress.org/plugins/public-post-preview-configurator/).
73
 
74
  == Change Log ==
75
+ = 2.5.0 (2016-04-05): =
76
+ * Auto select preview link on focus. Props [@JeroenSormani](https://github.com/JeroenSormani).
77
+ * Remove preview status from posts which are trashed or after scheduled posts are published.
78
+ * Add support for paged posts.
79
+
80
  = 2.4.1 (2015-10-13): =
81
  * Update text domain to support language packs. Translations are now managed via http://translate.wordpress.org/projects/wp-plugins/public-post-preview.
82