Admin Post Navigation - Version 2.1

Version Description

Recommended update: added screen option for users to customize post navigation order for each post type, fixed bug where navigation didn't appear for posts with apostrophe in title, updated unit test bootstrap file, noted compatibility is now WP 4.7-4.9+, and updated copyright date (2018)

Download this release

Release Info

Developer coffee2code
Plugin Icon 128x128 Admin Post Navigation
Version 2.1
Comparing to
See all releases

Code changes from version 2.0 to 2.1

README.md ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Admin Post Navigation
2
+
3
+ A plugin for WordPress that adds links to navigate to the next and previous posts when editing a post in the WordPress admin.
4
+
5
+ This plugin can be found in the WordPress Plugin Directory: https://wordpress.org/plugins/admin-post-navigation/
6
+
7
+ ## Installation
8
+
9
+ 1. Install via the built-in WordPress plugin installer. Or install the plugin code inside the plugins directory for your site (typically `/wp-content/plugins/`).
10
+ 2. Activate the plugin through the 'Plugins' admin menu in WordPress
11
+
12
+
13
+ ## Additional Documentation
14
+
15
+ See [readme.txt](https://github.com/coffee2code/admin-post-navigation/blob/master/readme.txt) for additional usage information.
16
+
17
+
18
+ ## Support
19
+
20
+ Commercial support and custom development are not presently available. You can raise an [issue](https://github.com/coffee2code/admin-post-navigation/issues) on GitHub or post in the [plugin's support forum on WordPress.org](https://wordpress.org/support/plugin/admin-post-navigation/). If the plugin has been of benefit to you, how about [submitting a review](https://wordpress.org/support/plugin/admin-post-navigation/reviews/) for it in the WordPress Plugin Directory or considerating a [donation](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=6ARCFJ9TX3522)?
21
+
22
+
23
+ ## License
24
+
25
+ This plugin is free software; you can redistribute it and/or modify it under the terms of the [GNU General Public License](http://www.gnu.org/licenses/gpl-2.0.html) as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
admin-post-navigation.php CHANGED
@@ -1,7 +1,7 @@
1
  <?php
2
  /**
3
  * Plugin Name: Admin Post Navigation
4
- * Version: 2.0
5
  * Plugin URI: http://coffee2code.com/wp-plugins/admin-post-navigation/
6
  * Author: Scott Reilly
7
  * Author URI: http://coffee2code.com/
@@ -10,7 +10,7 @@
10
  * License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
  * Description: Adds links to navigate to the next and previous posts when editing a post in the WordPress admin.
12
  *
13
- * Compatible with WordPress 3.0 through 4.5+.
14
  *
15
  * =>> Read the accompanying readme.txt file for instructions and documentation.
16
  * =>> Also, visit the plugin's homepage for additional information and updates.
@@ -18,21 +18,24 @@
18
  *
19
  * @package Admin_Post_Navigation
20
  * @author Scott Reilly
21
- * @version 2.0
22
  */
23
 
24
  /*
25
  * TODO:
26
  * - Add ability for navigation to save current post before navigating away.
27
- * - Hide screen option checkbox for metabox if metabox is being hidden
28
  * - Add screen option allowing user selection of post navigation order
29
  * - Add more unit tests
30
  * - Add dropdown to post nav links to allow selecting different types of things
31
  * to navigate to (e.g. next draft (if looking at a draft), next in category X)
 
 
 
 
32
  */
33
 
34
  /*
35
- Copyright (c) 2008-2016 by Scott Reilly (aka coffee2code)
36
 
37
  This program is free software; you can redistribute it and/or
38
  modify it under the terms of the GNU General Public License
@@ -74,24 +77,28 @@ class c2c_AdminPostNavigation {
74
  private static $next_text = '';
75
 
76
  /**
77
- * Default post statuses for navigation.
78
  *
79
- * Filterable later.
 
80
  *
81
  * @access private
 
82
  *
83
  * @var array
84
  */
85
- private static $post_statuses = array( 'draft', 'future', 'pending', 'private', 'publish', 'inherit' );
86
 
87
  /**
88
- * Post status query fragment.
 
 
89
  *
90
  * @access private
91
  *
92
- * @var string
93
  */
94
- private static $post_statuses_sql = '';
95
 
96
  /**
97
  * Returns version of the plugin.
@@ -99,14 +106,15 @@ class c2c_AdminPostNavigation {
99
  * @since 1.7
100
  */
101
  public static function version() {
102
- return '2.0';
103
  }
104
 
105
  /**
106
  * Class constructor: initializes class variables and adds actions and filters.
107
  */
108
  public static function init() {
109
- add_action( 'load-post.php', array( __CLASS__, 'register_post_page_hooks' ) );
 
110
  }
111
 
112
  /**
@@ -115,7 +123,6 @@ class c2c_AdminPostNavigation {
115
  * @since 1.7
116
  */
117
  public static function register_post_page_hooks() {
118
-
119
  // Load textdomain.
120
  load_plugin_textdomain( 'admin-post-navigation' );
121
 
@@ -126,6 +133,9 @@ class c2c_AdminPostNavigation {
126
  // Register hooks.
127
  add_action( 'admin_enqueue_scripts', array( __CLASS__, 'admin_enqueue_scripts_and_styles' ) );
128
  add_action( 'do_meta_boxes', array( __CLASS__, 'do_meta_box' ), 10, 3 );
 
 
 
129
  }
130
 
131
  /**
@@ -138,13 +148,61 @@ class c2c_AdminPostNavigation {
138
  wp_enqueue_style( 'admin-post-navigation-admin' );
139
 
140
  wp_register_script( 'admin-post-navigation-admin', plugins_url( 'assets/admin-post-navigation.js', __FILE__ ), array( 'jquery' ), self::version(), true );
141
- // Localize script.
142
- wp_localize_script( 'admin-post-navigation-admin', 'c2c_apn', array(
143
- 'tag' => version_compare( $GLOBALS['wp_version'], '4.3', '>=' ) ? 'h1' : 'h2',
144
- ) );
145
  wp_enqueue_script( 'admin-post-navigation-admin' );
146
  }
147
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
148
  /**
149
  * Register meta box.
150
  *
@@ -156,16 +214,11 @@ class c2c_AdminPostNavigation {
156
  * @param WP_Post $post The post.
157
  */
158
  public static function do_meta_box( $post_type, $type, $post ) {
159
- $post_types = apply_filters( 'c2c_admin_post_navigation_post_types', get_post_types() );
160
- if ( ! in_array( $post_type, $post_types ) ) {
161
  return;
162
  }
163
 
164
- $post_statuses = (array) apply_filters( 'c2c_admin_post_navigation_post_statuses', self::$post_statuses, $post_type, $post );
165
- if ( $post_statuses ) {
166
- foreach( $post_statuses as $i => $v ) { $GLOBALS['wpdb']->escape_by_ref( $v ); $post_statuses[ $i ] = $v; }
167
- self::$post_statuses_sql = "'" . implode( "', '", $post_statuses ) . "'";
168
- }
169
 
170
  if ( in_array( $post->post_status, $post_statuses ) ) {
171
  add_meta_box(
@@ -192,10 +245,13 @@ class c2c_AdminPostNavigation {
192
 
193
  $prev = self::previous_post();
194
  if ( $prev ) {
195
- $post_title = the_title_attribute( array( 'echo' => false, 'post' => $prev->ID ) );
196
- $display .= '<a href="' . get_edit_post_link( $prev->ID ) . '" id="admin-post-nav-prev" title="' .
197
- esc_attr( sprintf( __( 'Previous %1$s: %2$s', 'admin-post-navigation' ), $context, $post_title ) ) .
198
- '" class="admin-post-nav-prev add-new-h2">' . self::$prev_text . '</a>';
 
 
 
199
  }
200
 
201
  $next = self::next_post();
@@ -203,11 +259,13 @@ class c2c_AdminPostNavigation {
203
  if ( $display ) {
204
  $display .= ' ';
205
  }
206
- $post_title = the_title_attribute( array( 'echo' => false, 'post' => $next->ID ) );
207
- $display .= '<a href="' . get_edit_post_link( $next->ID ) .
208
- '" id="admin-post-nav-next" title="' .
209
- esc_attr( sprintf( __( 'Next %1$s: %2$s', 'admin-post-navigation' ), $context, $post_title ) ).
210
- '" class="admin-post-nav-next add-new-h2">' . self::$next_text . '</a>';
 
 
211
  }
212
 
213
  $display = '<span id="admin-post-nav">' . $display . '</span>';
@@ -233,6 +291,110 @@ class c2c_AdminPostNavigation {
233
  return strtolower( $label );
234
  }
235
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
236
  /**
237
  * Returns the previous or next post relative to the current post.
238
  *
@@ -259,28 +421,24 @@ class c2c_AdminPostNavigation {
259
 
260
  $post = get_post( $post_ID );
261
 
262
- if ( ! $post || ! self::$post_statuses_sql ) {
 
 
 
 
263
  return false;
264
  }
265
 
266
- $post_type = esc_sql( get_post_type( $post_ID ) );
 
267
 
268
- $sql = "SELECT ID, post_title FROM $wpdb->posts WHERE post_type = '$post_type' AND post_status IN (" . self::$post_statuses_sql . ') ';
269
 
270
  // Determine order.
271
- if ( is_post_type_hierarchical( $post_type ) ) {
272
- $orderby = 'post_title';
273
- } else {
274
- $orderby = 'post_date';
275
- }
276
- $default_orderby = $orderby;
277
- // Restrict orderby to actual post fields.
278
- $orderby = esc_sql( apply_filters( 'c2c_admin_post_navigation_orderby', $orderby, $post_type ) );
279
- if ( ! in_array( $orderby, array( 'comment_count', 'ID', 'menu_order', 'post_author', 'post_content', 'post_content_filtered', 'post_date', 'post_excerpt', 'post_date_gmt', 'post_mime_type', 'post_modified', 'post_modified_gmt', 'post_name', 'post_parent', 'post_status', 'post_title', 'post_type' ) ) ) {
280
- $orderby = $default_orderby;
281
- }
282
 
283
- $sql .= "AND {$orderby} {$type} '{$post->$orderby}' ";
 
284
 
285
  $sort = $type == '<' ? 'DESC' : 'ASC';
286
  $sql .= "ORDER BY {$orderby} {$sort} LIMIT {$offset}, {$limit}";
1
  <?php
2
  /**
3
  * Plugin Name: Admin Post Navigation
4
+ * Version: 2.1
5
  * Plugin URI: http://coffee2code.com/wp-plugins/admin-post-navigation/
6
  * Author: Scott Reilly
7
  * Author URI: http://coffee2code.com/
10
  * License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
  * Description: Adds links to navigate to the next and previous posts when editing a post in the WordPress admin.
12
  *
13
+ * Compatible with WordPress 4.7 through 4.9+.
14
  *
15
  * =>> Read the accompanying readme.txt file for instructions and documentation.
16
  * =>> Also, visit the plugin's homepage for additional information and updates.
18
  *
19
  * @package Admin_Post_Navigation
20
  * @author Scott Reilly
21
+ * @version 2.1
22
  */
23
 
24
  /*
25
  * TODO:
26
  * - Add ability for navigation to save current post before navigating away.
 
27
  * - Add screen option allowing user selection of post navigation order
28
  * - Add more unit tests
29
  * - Add dropdown to post nav links to allow selecting different types of things
30
  * to navigate to (e.g. next draft (if looking at a draft), next in category X)
31
+ * - When navigating via menu_order, respect hierarchy and navigate siblings.
32
+ * - Add filter to allow customizing the list of orderby options in screen options?
33
+ * - Add post status as series of checkboxes in Screen Options
34
+ * - Add support for secondary orderby
35
  */
36
 
37
  /*
38
+ Copyright (c) 2008-2018 by Scott Reilly (aka coffee2code)
39
 
40
  This program is free software; you can redistribute it and/or
41
  modify it under the terms of the GNU General Public License
77
  private static $next_text = '';
78
 
79
  /**
80
+ * Post fields available as orderby options.
81
  *
82
+ * Note: not meant to be an exhaustive list, just the ones available to users
83
+ * via dropdown in Screen Options panel.
84
  *
85
  * @access private
86
+ * @since 2.1
87
  *
88
  * @var array
89
  */
90
+ private static $orderby_fields = array( 'ID', 'menu_order', 'post_date', 'post_modified', 'post_name', 'post_title' );
91
 
92
  /**
93
+ * Default post statuses for navigation.
94
+ *
95
+ * Filterable later.
96
  *
97
  * @access private
98
  *
99
+ * @var array
100
  */
101
+ private static $post_statuses = array( 'draft', 'future', 'pending', 'private', 'publish' );
102
 
103
  /**
104
  * Returns version of the plugin.
106
  * @since 1.7
107
  */
108
  public static function version() {
109
+ return '2.1';
110
  }
111
 
112
  /**
113
  * Class constructor: initializes class variables and adds actions and filters.
114
  */
115
  public static function init() {
116
+ add_filter( 'set-screen-option', array( __CLASS__, 'save_screen_settings' ), 10, 3 );
117
+ add_action( 'load-post.php', array( __CLASS__, 'register_post_page_hooks' ) );
118
  }
119
 
120
  /**
123
  * @since 1.7
124
  */
125
  public static function register_post_page_hooks() {
 
126
  // Load textdomain.
127
  load_plugin_textdomain( 'admin-post-navigation' );
128
 
133
  // Register hooks.
134
  add_action( 'admin_enqueue_scripts', array( __CLASS__, 'admin_enqueue_scripts_and_styles' ) );
135
  add_action( 'do_meta_boxes', array( __CLASS__, 'do_meta_box' ), 10, 3 );
136
+
137
+ // Screen options.
138
+ add_filter( 'screen_settings', array( __CLASS__, 'screen_settings' ), 10, 2 );
139
  }
140
 
141
  /**
148
  wp_enqueue_style( 'admin-post-navigation-admin' );
149
 
150
  wp_register_script( 'admin-post-navigation-admin', plugins_url( 'assets/admin-post-navigation.js', __FILE__ ), array( 'jquery' ), self::version(), true );
 
 
 
 
151
  wp_enqueue_script( 'admin-post-navigation-admin' );
152
  }
153
 
154
+ /**
155
+ * Outputs screen settings.
156
+ *
157
+ * @since 2.1
158
+ *
159
+ * @param string $screen_settings Screen settings markup.
160
+ * @param WP_Screen $screen WP_Screen object.
161
+ * @return string
162
+ */
163
+ public static function screen_settings( $screen_settings, $screen ) {
164
+ if ( empty( $screen->post_type ) || ! self::is_post_type_navigable( $screen->post_type ) ) {
165
+ return $screen_settings;
166
+ }
167
+
168
+ $option = self::get_setting_name( $screen->post_type );
169
+ $value = self::get_post_type_orderby( $screen->post_type, get_current_user_id() );
170
+
171
+ $screen_settings .= '<fieldset class="">'
172
+ . '<legend>' . __( 'Admin Post Navigation', 'admin-post-navigation' ) . '</legend>'
173
+ . '<input type="hidden" name="wp_screen_options[option]" value="' . $option . '" />' . "\n"
174
+ . '<label for="' . $option . '">'
175
+ . sprintf( __( 'Navigation order for this post type (%s)', 'admin-post-navigation' ), $screen->post_type )
176
+ . ' <select name="wp_screen_options[value]">';
177
+ foreach ( self::$orderby_fields as $orderby ) {
178
+ $screen_settings .= '<option value="' . $orderby . '" ' . selected( $value, $orderby, false ) . '>' . $orderby . '</option>';
179
+ }
180
+ $screen_settings .= '</select>'
181
+ . '</label>' . "\n"
182
+ . get_submit_button( __( 'Apply', 'admin-post-navigation' ), 'button', 'screen-options-apply', false )
183
+ . '</fieldset>';
184
+
185
+ return $screen_settings;
186
+ }
187
+
188
+ /**
189
+ * Saves screen option values.
190
+ *
191
+ * @since 2.1
192
+ *
193
+ * @param bool|int $status Screen option value. Default false to skip.
194
+ * @param string $option The option name.
195
+ * @param int $value The number of rows to use.
196
+ * @return bool|string
197
+ */
198
+ public static function save_screen_settings( $status, $option, $value ) {
199
+ if ( 'c2c_apn_' == substr( $option, 0, 8 ) ) {
200
+ $status = $value;
201
+ }
202
+
203
+ return $status;
204
+ }
205
+
206
  /**
207
  * Register meta box.
208
  *
214
  * @param WP_Post $post The post.
215
  */
216
  public static function do_meta_box( $post_type, $type, $post ) {
217
+ if ( ! self::is_post_type_navigable( $post_type ) ) {
 
218
  return;
219
  }
220
 
221
+ $post_statuses = self::get_post_statuses( $post_type );
 
 
 
 
222
 
223
  if ( in_array( $post->post_status, $post_statuses ) ) {
224
  add_meta_box(
245
 
246
  $prev = self::previous_post();
247
  if ( $prev ) {
248
+ $post_title = strip_tags( get_the_title( $prev ) );
249
+ $display .= sprintf(
250
+ '<a href="%s" id="admin-post-nav-prev" title="%s" class="admin-post-nav-prev add-new-h2">%s</a>',
251
+ get_edit_post_link( $prev->ID ),
252
+ esc_attr( sprintf( __( 'Previous %1$s: %2$s', 'admin-post-navigation' ), $context, $post_title ) ),
253
+ self::$prev_text
254
+ );
255
  }
256
 
257
  $next = self::next_post();
259
  if ( $display ) {
260
  $display .= ' ';
261
  }
262
+ $post_title = strip_tags( get_the_title( $next ) );
263
+ $display .= sprintf(
264
+ '<a href="%s" id="admin-post-nav-next" title="%s" class="admin-post-nav-next add-new-h2">%s</a>',
265
+ get_edit_post_link( $next->ID ),
266
+ esc_attr( sprintf( __( 'Next %1$s: %2$s', 'admin-post-navigation' ), $context, $post_title ) ),
267
+ self::$next_text
268
+ );
269
  }
270
 
271
  $display = '<span id="admin-post-nav">' . $display . '</span>';
291
  return strtolower( $label );
292
  }
293
 
294
+ /**
295
+ * Returns the name of the screen option setting for the orderby setting for
296
+ * the given post type.
297
+ *
298
+ * @since 2.1
299
+ *
300
+ * @param string $post_type The post type.
301
+ * @return string
302
+ */
303
+ public static function get_setting_name( $post_type ) {
304
+ return 'c2c_apn_' . $post_type . '_orderby';
305
+ }
306
+
307
+ /**
308
+ * Determines if a post type has admin navigation enabled.
309
+ *
310
+ * By default, the navigation is enabled for all post types. Filter
311
+ * 'c2c_admin_post_navigation_post_types' to limit its use.
312
+ *
313
+ * @since 2.1
314
+ *
315
+ * @param string $post_type The post type.
316
+ * @return bool True if post type has admin navigation enabled, else false.
317
+ */
318
+ public static function is_post_type_navigable( $post_type ) {
319
+ $post_types = (array) apply_filters( 'c2c_admin_post_navigation_post_types', get_post_types() );
320
+
321
+ return in_array( $post_type, $post_types );
322
+ }
323
+
324
+ /**
325
+ * Determines if a given orderby field value is valid.
326
+ *
327
+ * Only post table fields are valid.
328
+ *
329
+ * @since 2.1
330
+ *
331
+ * @param string $orderby The orderby.
332
+ * @return bool. True if valid, false if not.
333
+ */
334
+ public static function is_valid_orderby( $orderby ) {
335
+ // By default, restrict orderby to actual post fields.
336
+ $valid = array(
337
+ 'comment_count', 'ID', 'menu_order', 'post_author', 'post_content', 'post_content_filtered',
338
+ 'post_date', 'post_excerpt', 'post_date_gmt', 'post_mime_type', 'post_modified',
339
+ 'post_modified_gmt', 'post_name', 'post_parent', 'post_status', 'post_title', 'post_type',
340
+ );
341
+
342
+ // Filter the value.
343
+ //$valid = (array) apply_filters( 'c2c_admin_post_navigation_valid_orderbys', $valid );
344
+
345
+ return in_array( $orderby, $valid );
346
+ }
347
+
348
+ /**
349
+ * Determines the orderby value to use for a given post type's navigation.
350
+ *
351
+ * @since 2.1
352
+ *
353
+ * @param string $post_type The post type.
354
+ * @param int $user_id Optional. User ID of user, to account for the
355
+ * value the set via screen options.
356
+ * @return string
357
+ */
358
+ public static function get_post_type_orderby( $post_type, $user_id = false ) {
359
+ if ( ! $user_id ) {
360
+ $user_id = get_current_user_id();
361
+ }
362
+
363
+ if ( is_post_type_hierarchical( $post_type ) ) {
364
+ $orderby = 'post_title';
365
+ } else {
366
+ $orderby = 'post_date';
367
+ }
368
+
369
+ // Get user-selected order for this post type.
370
+ if ( $user_id ) {
371
+ $user_orderby = get_user_meta( $user_id, self::get_setting_name( $post_type ), true );
372
+ if ( $user_orderby && self::is_valid_orderby( $user_orderby ) ) {
373
+ $orderby = $user_orderby;
374
+ }
375
+ }
376
+
377
+ // Filter orderby value.
378
+ $filter_orderby = apply_filters( 'c2c_admin_post_navigation_orderby', $orderby, $post_type, $user_id );
379
+ if ( $filter_orderby && self::is_valid_orderby( $filter_orderby ) ) {
380
+ $orderby = $filter_orderby;
381
+ }
382
+
383
+ return $orderby;
384
+ }
385
+
386
+ /**
387
+ * Returns the post statuses valid for navigation of the post type.
388
+ *
389
+ * @since 2.1
390
+ *
391
+ * @param string $post_type The post type.
392
+ * @return array
393
+ */
394
+ public static function get_post_statuses( $post_type ) {
395
+ return (array) apply_filters( 'c2c_admin_post_navigation_post_statuses', self::$post_statuses, $post_type );
396
+ }
397
+
398
  /**
399
  * Returns the previous or next post relative to the current post.
400
  *
421
 
422
  $post = get_post( $post_ID );
423
 
424
+ $post_type = esc_sql( get_post_type( $post->ID ) );
425
+
426
+ $post_statuses = self::get_post_statuses( $post_type );
427
+
428
+ if ( ! $post || ! $post_statuses ) {
429
  return false;
430
  }
431
 
432
+ foreach( $post_statuses as $i => $v ) { $GLOBALS['wpdb']->escape_by_ref( $v ); $post_statuses[ $i ] = $v; }
433
+ $post_statuses_sql = "'" . implode( "', '", $post_statuses ) . "'";
434
 
435
+ $sql = "SELECT ID, post_title FROM $wpdb->posts WHERE post_type = '$post_type' AND post_status IN (" . $post_statuses_sql . ') ';
436
 
437
  // Determine order.
438
+ $orderby = self::get_post_type_orderby( $post_type );
 
 
 
 
 
 
 
 
 
 
439
 
440
+ $datatype = in_array( $orderby, array( 'comment_count', 'ID', 'menu_order', 'post_parent' ) ) ? '%d' : '%s';
441
+ $sql .= $wpdb->prepare( "AND {$orderby} {$type} {$datatype} ", $post->$orderby );
442
 
443
  $sort = $type == '<' ? 'DESC' : 'ASC';
444
  $sql .= "ORDER BY {$orderby} {$sort} LIMIT {$offset}, {$limit}";
assets/admin-post-navigation.js CHANGED
@@ -1,4 +1,4 @@
1
  jQuery(document).ready(function($) {
2
- $('#admin-post-nav').appendTo($('#wpbody-content .wrap:first ' + c2c_apn.tag + ':first'));
3
  $('#adminpostnav, label[for="adminpostnav-hide"]').hide();
4
  });
1
  jQuery(document).ready(function($) {
2
+ $('#admin-post-nav').appendTo($('#wpbody-content .wrap:first h1:first'));
3
  $('#adminpostnav, label[for="adminpostnav-hide"]').hide();
4
  });
readme.txt CHANGED
@@ -4,9 +4,9 @@ Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_i
4
  Tags: admin, navigation, post, next, previous, edit, post types, coffee2code
5
  License: GPLv2 or later
6
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
7
- Requires at least: 4.0
8
- Tested up to: 4.5
9
- Stable tag: 2.0
10
 
11
  Adds links to navigate to the next and previous posts when editing a post in the WordPress admin.
12
 
@@ -15,18 +15,21 @@ Adds links to navigate to the next and previous posts when editing a post in the
15
 
16
  This plugin adds "&larr; Previous" and "Next &rarr;" links to the "Edit Post" admin page if a previous and next post are present, respectively. The link titles (visible when hovering over the links) reveal the title of the previous/next post. The links link to the "Edit Post" admin page for the previous/next posts so that you may edit them.
17
 
18
- By default, a previous/next post is determined by the next lower/higher valid post based on relative sequential post ID and which the user can edit. Other post criteria such as post type (draft, pending, etc), publish date, post author, category, etc, are not taken into consideration when determining the previous or next post. How posts are navigated, and post types and post statuses to restrict navigation can be customized via filters (see Filters section).
19
 
20
- NOTE: Be sure to save the post currently being edited before navigating away to the previous/next post.
21
 
22
- Links: [Plugin Homepage](http://coffee2code.com/wp-plugins/admin-post-navigation/) | [Plugin Directory Page](https://wordpress.org/plugins/admin-post-navigation/) | [Author Homepage](http://coffee2code.com)
 
 
23
 
24
 
25
  == Installation ==
26
 
27
  1. Unzip `admin-post-navigation.zip` inside the `/wp-content/plugins/` directory for your site (or install via the built-in WordPress plugin installer)
28
- 1. Activate the plugin through the 'Plugins' admin menu in WordPress
29
- 1. See documentation for available customizations, if so inclined
 
30
 
31
 
32
  == Screenshots ==
@@ -48,36 +51,39 @@ Yes. See the Filters section for the `c2c_admin_post_navigation_prev_text` and/o
48
 
49
  == Filters ==
50
 
51
- The plugin is further customizable via six filters. Typically, these customizations would be put into your active theme's functions.php file, or used by another plugin.
52
 
53
  = c2c_admin_post_navigation_orderby (filter) =
54
 
55
- The 'c2c_admin_post_navigation_orderby' filter allows you to change the post field used in the ORDER BY clause for the SQL to find the previous/next post. By default this is 'ID' for non-hierarchical post types (such as posts) and 'post_title' for hierarchical post types (such as pages). If you wish to change this, hook this filter. This is not typical usage for most users.
56
 
57
  Arguments:
58
 
59
  * $field (string) The current ORDER BY field
60
  * $post_type (string) The post type being navigated
 
61
 
62
  Example:
63
 
64
  `
65
  /**
66
- * Modify how Admin Post Navigation orders posts for navigation by ordering
67
- * pages by 'menu_order' and posts by 'post_date'.
68
  *
69
  * @param string $field The field used to order posts for navigation.
70
  * @param string $post_type The post type being navigated.
 
71
  * @return string
72
  */
73
- function custom_order_apn( $field, $post_type ) {
 
74
  if ( 'page' === $post_type ) {
75
- return 'menu_order';
76
- } else {
77
- return 'post_date';
78
  }
 
 
79
  }
80
- add_filter( 'c2c_admin_post_navigation_orderby', 'custom_order_apn', 10, 2 );
81
  `
82
 
83
  = c2c_admin_post_navigation_post_statuses (filter) =
@@ -87,6 +93,7 @@ The 'c2c_admin_post_navigation_post_statuses' filter allows you to modify the li
87
  Arguments:
88
 
89
  * $post_statuses (array) The array of valid post_statuses
 
90
 
91
  Example:
92
 
@@ -94,25 +101,29 @@ Example:
94
  /**
95
  * Modify Admin Post Navigation to allow and disallow certain post statuses from being navigated.
96
  *
97
- * @param array $post_statuses Post statuses permitted for admin navigation.
 
98
  * @return array
99
  */
100
- function change_apn_post_status( $post_statuses ) {
101
  // Add a post status.
102
  // Note: by default these are already in the $post_statuses array: 'draft', 'future', 'pending', 'private', 'publish'
103
  $post_statuses[] = 'trash';
104
 
105
  // Remove post status(es).
106
  $post_statuses_to_remove = array( 'draft' ); // Customize here.
 
 
 
107
  foreach ( $post_statuses_to_remove as $remove ) {
108
  if ( false !== $index = array_search( $remove, $post_statuses ) ) {
109
  unset( $post_statuses[ $index ] );
110
  }
111
  }
112
 
113
- return $post_statuses;
114
  }
115
- add_filter( 'c2c_admin_post_navigation_post_statuses', 'change_apn_post_status' );
116
  `
117
 
118
  = c2c_admin_post_navigation_post_types (filter) =
@@ -227,6 +238,31 @@ add_filter( 'c2c_admin_post_navigation_display', 'override_apn_display' );
227
 
228
  == Changelog ==
229
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
230
  = 2.0 (2016-01-14) =
231
  * New: Add support for RTL display.
232
  * New: Enable post navigation for media when viewed/edited from list mode.
@@ -386,6 +422,9 @@ add_filter( 'c2c_admin_post_navigation_display', 'override_apn_display' );
386
 
387
  == Upgrade Notice ==
388
 
 
 
 
389
  = 2.0 =
390
  Recommended update: added RTL support, moved CSS & JS into enqueueable files, enabled navigation for media files, adjustments to utilize language packs, minor unit test tweaks, noted compatibility through WP 4.4+, and updated copyright date
391
 
4
  Tags: admin, navigation, post, next, previous, edit, post types, coffee2code
5
  License: GPLv2 or later
6
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
7
+ Requires at least: 4.7
8
+ Tested up to: 4.9
9
+ Stable tag: 2.1
10
 
11
  Adds links to navigate to the next and previous posts when editing a post in the WordPress admin.
12
 
15
 
16
  This plugin adds "&larr; Previous" and "Next &rarr;" links to the "Edit Post" admin page if a previous and next post are present, respectively. The link titles (visible when hovering over the links) reveal the title of the previous/next post. The links link to the "Edit Post" admin page for the previous/next posts so that you may edit them.
17
 
18
+ By default, a previous/next post is determined by the next lower/higher valid post based on the date the post was created and which is also a post the user can edit. Other post criteria such as post type (draft, pending, etc), publish date, post author, category, etc, are not taken into consideration when determining the previous or next post.
19
 
20
+ Users can customize how post navigation ordering is handled via the "Screen Options" panel available at the top of every page when editing a post. A dropdown presents options to order navigation by: 'ID', 'menu_order', 'post_date', 'post_modified', 'post_name', and 'post_title'. Post navigation can further be customized via filters (see Filters section).
21
 
22
+ NOTE: Be sure to save the post currently being edited (if you've made any changes) before navigating away to the previous/next post!
23
+
24
+ Links: [Plugin Homepage](http://coffee2code.com/wp-plugins/admin-post-navigation/) | [Plugin Directory Page](https://wordpress.org/plugins/admin-post-navigation/) | [GitHub](https://github.com/coffe2code/admin-post-navigation/) | [Author Homepage](http://coffee2code.com)
25
 
26
 
27
  == Installation ==
28
 
29
  1. Unzip `admin-post-navigation.zip` inside the `/wp-content/plugins/` directory for your site (or install via the built-in WordPress plugin installer)
30
+ 2. Activate the plugin through the 'Plugins' admin menu in WordPress
31
+ 3. Optional: When editing a post type that supports admin navigation (which are all post types by default), use the "Screen Options" menu to customize how navigation is handled.
32
+ 4. Optional: See documentation for available programmatic customizations
33
 
34
 
35
  == Screenshots ==
51
 
52
  == Filters ==
53
 
54
+ The plugin is further customizable via six filters. Such code should ideally be put into a mu-plugin or site-specific plugin (which is beyond the scope of this readme to explain).
55
 
56
  = c2c_admin_post_navigation_orderby (filter) =
57
 
58
+ The 'c2c_admin_post_navigation_orderby' filter allows you to change the post field used in the ORDER BY clause for the SQL to find the previous/next post. By default this is 'post_date' for non-hierarchical post types (such as posts) and 'post_title' for hierarchical post types (such as pages). If you wish to change this, hook this filter. Note: users can customize the post navigation order field for themselves on a per-post type basis via "Screen Options" (see FAQ and screenshot for more info).
59
 
60
  Arguments:
61
 
62
  * $field (string) The current ORDER BY field
63
  * $post_type (string) The post type being navigated
64
+ * $user_id (int) The user's ID
65
 
66
  Example:
67
 
68
  `
69
  /**
70
+ * Modify how Admin Post Navigation orders posts for navigation by changing the
71
+ * ordering of pages by 'menu_order'.
72
  *
73
  * @param string $field The field used to order posts for navigation.
74
  * @param string $post_type The post type being navigated.
75
+ * @param int $user_id. The user's ID.
76
  * @return string
77
  */
78
+ function custom_order_apn( $field, $post_type, $user_id ) {
79
+ // Only change the order for the 'page' post type.
80
  if ( 'page' === $post_type ) {
81
+ $field = 'menu_order';
 
 
82
  }
83
+
84
+ return $field;
85
  }
86
+ add_filter( 'c2c_admin_post_navigation_orderby', 'custom_order_apn', 10, 3 );
87
  `
88
 
89
  = c2c_admin_post_navigation_post_statuses (filter) =
93
  Arguments:
94
 
95
  * $post_statuses (array) The array of valid post_statuses
96
+ * $post_type (string) The post type
97
 
98
  Example:
99
 
101
  /**
102
  * Modify Admin Post Navigation to allow and disallow certain post statuses from being navigated.
103
  *
104
+ * @param array $post_statuses Post statuses permitted for admin navigation.
105
+ * @param string $post_type The post type.
106
  * @return array
107
  */
108
+ function change_apn_post_status( $post_statuses, $post_type ) {
109
  // Add a post status.
110
  // Note: by default these are already in the $post_statuses array: 'draft', 'future', 'pending', 'private', 'publish'
111
  $post_statuses[] = 'trash';
112
 
113
  // Remove post status(es).
114
  $post_statuses_to_remove = array( 'draft' ); // Customize here.
115
+ if ( 'page' === $post_type ) {
116
+ $post_statuses_to_remove[] = 'pending';
117
+ }
118
  foreach ( $post_statuses_to_remove as $remove ) {
119
  if ( false !== $index = array_search( $remove, $post_statuses ) ) {
120
  unset( $post_statuses[ $index ] );
121
  }
122
  }
123
 
124
+ return array_values( $post_statuses );
125
  }
126
+ add_filter( 'c2c_admin_post_navigation_post_statuses', 'change_apn_post_status', 10, 2 );
127
  `
128
 
129
  = c2c_admin_post_navigation_post_types (filter) =
238
 
239
  == Changelog ==
240
 
241
+ = 2.1 (2017-12-26) =
242
+ * New: Add ability for users to customize the navigation order via a Screen Options dropdown.
243
+ * Add optional `$user_id` arg to `get_post_type_orderby()`, and use it, to take into account user preference.
244
+ * Add `$user_id` arg to 'c2c_admin_post_navigation_orderby' filter.
245
+ * Add `get_setting_name()` helper function for getting the setting name for the given post type.
246
+ * Add `screen_settings()` to output the dropdown.
247
+ * Add `save_screen_settings()` to save user's preference.
248
+ * Fix: Resolve issue where navigation links failed to appear on posts with an apostrophe in their titles.
249
+ * New: Add `is_valid_orderby()` helper function to verify a given orderby value is valid.
250
+ * New: Add `get_post_statuses()` for getting post statuses valid for navigation of a given post type.
251
+ * New: Abstract logic for determining the orderby for a given post type into `get_post_type_orderby()`.
252
+ * New: Abstract logic for determining if a post type has admin navigation enabled into `is_post_type_navigable()`.
253
+ * New: Add README.md.
254
+ * Change: Use `get_the_title()` instead of `the_title_attribute()` to get post titles.
255
+ * Change: Discontinue sending `$user_id` arg to 'c2c_admin_post_navigation_post_statuses' filter.
256
+ * Change: Remove pre-WP 4.3 support for JS relocation of prev/next links.
257
+ * Change: Use `sprintf()` to format output markup rather than concatenating strings, variables, and function calls.
258
+ * Change: For unit tests, enable more error output.
259
+ * Change: For unit tests, default `WP_TESTS_DIR` to `/tmp/wordpress-tests-lib` rather than erroring out if not defined via environment variable.
260
+ * Change: Add GitHub link to readme.
261
+ * Change: Note compatibility through WP 4.9+.
262
+ * Change: Remove support for WordPress older than 4.7 (should still work for earlier versions)
263
+ * Change: Update copyright date (2018).
264
+ * Change: Minor whitespace tweaks in unit test bootstrap
265
+
266
  = 2.0 (2016-01-14) =
267
  * New: Add support for RTL display.
268
  * New: Enable post navigation for media when viewed/edited from list mode.
422
 
423
  == Upgrade Notice ==
424
 
425
+ = 2.1 =
426
+ Recommended update: added screen option for users to customize post navigation order for each post type, fixed bug where navigation didn't appear for posts with apostrophe in title, updated unit test bootstrap file, noted compatibility is now WP 4.7-4.9+, and updated copyright date (2018)
427
+
428
  = 2.0 =
429
  Recommended update: added RTL support, moved CSS & JS into enqueueable files, enabled navigation for media files, adjustments to utilize language packs, minor unit test tweaks, noted compatibility through WP 4.4+, and updated copyright date
430
 
tests/bootstrap.php CHANGED
@@ -1,10 +1,28 @@
1
  <?php
 
 
 
 
 
2
 
3
- require_once getenv( 'WP_TESTS_DIR' ) . '/includes/functions.php';
 
4
 
 
 
 
 
 
 
 
 
 
 
 
5
  function _manually_load_plugin() {
6
- require dirname( __FILE__ ) . '/../admin-post-navigation.php';
7
  }
8
  tests_add_filter( 'muplugins_loaded', '_manually_load_plugin' );
9
 
10
- require getenv( 'WP_TESTS_DIR' ) . '/includes/bootstrap.php';
 
1
  <?php
2
+ /**
3
+ * PHPUnit bootstrap file
4
+ *
5
+ * @package Admin_Post_Navigation
6
+ */
7
 
8
+ ini_set( 'display_errors', 'on' );
9
+ error_reporting( E_ALL );
10
 
11
+ $_tests_dir = getenv( 'WP_TESTS_DIR' );
12
+ if ( ! $_tests_dir ) {
13
+ $_tests_dir = '/tmp/wordpress-tests-lib';
14
+ }
15
+
16
+ // Give access to tests_add_filter() function.
17
+ require_once $_tests_dir . '/includes/functions.php';
18
+
19
+ /**
20
+ * Manually load the plugin being tested.
21
+ */
22
  function _manually_load_plugin() {
23
+ require dirname( dirname( __FILE__ ) ) . '/admin-post-navigation.php';
24
  }
25
  tests_add_filter( 'muplugins_loaded', '_manually_load_plugin' );
26
 
27
+ // Start up the WP testing environment.
28
+ require $_tests_dir . '/includes/bootstrap.php';
tests/test-admin-post-navigation.php CHANGED
@@ -9,7 +9,7 @@ class Admin_Post_Navigation_Test extends WP_UnitTestCase {
9
  public function setUp() {
10
  parent::setUp();
11
 
12
- c2c_AdminPostNavigation::register_post_page_hooks();
13
  }
14
 
15
  public function tearDown() {
@@ -20,6 +20,7 @@ class Admin_Post_Navigation_Test extends WP_UnitTestCase {
20
 
21
  remove_filter( 'c2c_admin_post_navigation_post_statuses', array( $this, 'c2c_admin_post_navigation_post_statuses' ), 10, 3 );
22
  remove_filter( 'c2c_admin_post_navigation_orderby', array( $this, 'c2c_admin_post_navigation_orderby' ), 10, 2 );
 
23
  remove_filter( 'c2c_admin_post_navigation_orderby', array( $this, 'c2c_admin_post_navigation_orderby_bad_value' ), 10, 2 );
24
  }
25
 
@@ -31,6 +32,36 @@ class Admin_Post_Navigation_Test extends WP_UnitTestCase {
31
  //
32
 
33
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
 
35
  //
36
  //
@@ -74,29 +105,35 @@ class Admin_Post_Navigation_Test extends WP_UnitTestCase {
74
  return $posts;
75
  }
76
 
77
- public function c2c_admin_post_navigation_post_statuses( $post_statuses, $post_type, $post ) {
78
  $this->assertTrue( is_array( $post_statuses ) );
79
- $this->assertEquals( 'post', $post_type );
80
- $this->assertTrue( is_a( $post, 'WP_Post' ) );
81
 
82
  // Add a post status.
83
  $post_statuses[] = 'trash';
84
 
85
  // Remove post status.
86
  $post_statuses_to_remove = array( 'draft' );
 
 
 
87
  foreach ( $post_statuses_to_remove as $remove ) {
88
  if ( false !== $index = array_search( $remove, $post_statuses ) ) {
89
  unset( $post_statuses[ $index ] );
90
  }
91
  }
92
 
93
- return $post_statuses;
94
  }
95
 
96
  public function c2c_admin_post_navigation_orderby( $orderby, $post_type ) {
97
  return 'post_date';
98
  }
99
 
 
 
 
 
100
  public function c2c_admin_post_navigation_orderby_bad_value( $orderby, $post_type ) {
101
  return 'gibberish';
102
  }
@@ -114,7 +151,7 @@ class Admin_Post_Navigation_Test extends WP_UnitTestCase {
114
  }
115
 
116
  public function test_version() {
117
- $this->assertEquals( '2.0', c2c_AdminPostNavigation::version() );
118
  }
119
 
120
  /*
@@ -207,6 +244,92 @@ class Admin_Post_Navigation_Test extends WP_UnitTestCase {
207
  $this->assertEmpty( $previous_post );
208
  }
209
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
210
 
211
  /*
212
  * Filters.
@@ -226,13 +349,13 @@ class Admin_Post_Navigation_Test extends WP_UnitTestCase {
226
  }
227
 
228
  public function test_filter_c2c_admin_post_navigation_post_statuses_when_adding_post_status() {
229
- add_filter( 'c2c_admin_post_navigation_post_statuses', array( $this, 'c2c_admin_post_navigation_post_statuses' ), 10, 3 );
230
-
231
  $posts = $this->create_posts();
232
 
 
 
233
  $post = get_post( $posts[3] );
234
- $post->post_status = 'trash';
235
- wp_update_post( $post );
236
 
237
  $next_post = c2c_AdminPostNavigation::next_post();
238
 
@@ -240,10 +363,10 @@ class Admin_Post_Navigation_Test extends WP_UnitTestCase {
240
  }
241
 
242
  public function test_filter_c2c_admin_post_navigation_post_statuses_when_removing_post_status() {
243
- add_filter( 'c2c_admin_post_navigation_post_statuses', array( $this, 'c2c_admin_post_navigation_post_statuses' ), 10, 3 );
244
-
245
  $posts = $this->create_posts();
246
 
 
 
247
  $post = get_post( $posts[3] );
248
  $post->post_status = 'draft';
249
  wp_update_post( $post );
9
  public function setUp() {
10
  parent::setUp();
11
 
12
+ do_action( 'load-post.php' );
13
  }
14
 
15
  public function tearDown() {
20
 
21
  remove_filter( 'c2c_admin_post_navigation_post_statuses', array( $this, 'c2c_admin_post_navigation_post_statuses' ), 10, 3 );
22
  remove_filter( 'c2c_admin_post_navigation_orderby', array( $this, 'c2c_admin_post_navigation_orderby' ), 10, 2 );
23
+ remove_filter( 'c2c_admin_post_navigation_orderby', array( $this, 'c2c_admin_post_navigation_orderby_title' ), 10, 2 );
24
  remove_filter( 'c2c_admin_post_navigation_orderby', array( $this, 'c2c_admin_post_navigation_orderby_bad_value' ), 10, 2 );
25
  }
26
 
32
  //
33
 
34
 
35
+ public function valid_orderbys() {
36
+ return array(
37
+ array( 'comment_count' ),
38
+ array( 'ID' ),
39
+ array( 'menu_order' ),
40
+ array( 'post_author' ),
41
+ array( 'post_content' ),
42
+ array( 'post_content_filtered' ),
43
+ array( 'post_date' ),
44
+ array( 'post_excerpt' ),
45
+ array( 'post_date_gmt' ),
46
+ array( 'post_mime_type' ),
47
+ array( 'post_modified' ),
48
+ array( 'post_modified_gmt' ),
49
+ array( 'post_name' ),
50
+ array( 'post_parent' ),
51
+ array( 'post_status' ),
52
+ array( 'post_title' ),
53
+ array( 'post_type' ),
54
+ );
55
+ }
56
+
57
+ public function invalid_orderbys() {
58
+ return array(
59
+ array( 'title' ),
60
+ array( 'id' ),
61
+ array( 'gibberish' ),
62
+ );
63
+ }
64
+
65
 
66
  //
67
  //
105
  return $posts;
106
  }
107
 
108
+ public function c2c_admin_post_navigation_post_statuses( $post_statuses, $post_type ) {
109
  $this->assertTrue( is_array( $post_statuses ) );
110
+ $this->assertTrue( is_string( $post_type ) );
 
111
 
112
  // Add a post status.
113
  $post_statuses[] = 'trash';
114
 
115
  // Remove post status.
116
  $post_statuses_to_remove = array( 'draft' );
117
+ if ( 'page' === $post_type ) {
118
+ $post_statuses_to_remove[] = 'pending';
119
+ }
120
  foreach ( $post_statuses_to_remove as $remove ) {
121
  if ( false !== $index = array_search( $remove, $post_statuses ) ) {
122
  unset( $post_statuses[ $index ] );
123
  }
124
  }
125
 
126
+ return array_values( $post_statuses );
127
  }
128
 
129
  public function c2c_admin_post_navigation_orderby( $orderby, $post_type ) {
130
  return 'post_date';
131
  }
132
 
133
+ public function c2c_admin_post_navigation_orderby_title( $orderby, $post_type ) {
134
+ return 'post_title';
135
+ }
136
+
137
  public function c2c_admin_post_navigation_orderby_bad_value( $orderby, $post_type ) {
138
  return 'gibberish';
139
  }
151
  }
152
 
153
  public function test_version() {
154
+ $this->assertEquals( '2.1', c2c_AdminPostNavigation::version() );
155
  }
156
 
157
  /*
244
  $this->assertEmpty( $previous_post );
245
  }
246
 
247
+ public function test_navigate_by_post_title_on_posts_with_quotes_in_title() {
248
+ add_filter( 'c2c_admin_post_navigation_orderby', array( $this, 'c2c_admin_post_navigation_orderby_title' ), 10, 2 );
249
+
250
+ $posts = $this->create_posts();
251
+
252
+ // Change post titles so post ordering by title is 3, 0, 2, 4, 1
253
+ $new_post_titles = array(
254
+ "Don't wake the dragon",
255
+ 'A very good post',
256
+ "Can you 'dig' it?",
257
+ 'Everything must come to an end',
258
+ 'Be a good person',
259
+ );
260
+ foreach ( $new_post_titles as $i => $title ) {
261
+ $post = get_post( $posts[ $i ] );
262
+ $post->post_title = $title;
263
+ wp_update_post( $post );
264
+ }
265
+
266
+ $next_post = c2c_AdminPostNavigation::next_post();
267
+
268
+ $this->assertEquals( get_post( $posts[0] )->post_title, get_post( $next_post->ID )->post_title );
269
+
270
+ $previous_post = c2c_AdminPostNavigation::previous_post();
271
+
272
+ $this->assertEquals( get_post( $posts[4] )->post_title, get_post( $previous_post->ID )->post_title );
273
+ }
274
+
275
+
276
+ /*
277
+ * c2c_AdminPostNavigation::is_valid_orderby()
278
+ */
279
+
280
+ /**
281
+ * @dataProvider valid_orderbys
282
+ */
283
+ public function test_is_valid_orderby_with_valid( $orderby ) {
284
+ $this->assertTrue( c2c_AdminPostNavigation::is_valid_orderby( $orderby ) );
285
+ }
286
+
287
+ /**
288
+ * @dataProvider invalid_orderbys
289
+ */
290
+ public function test_is_valid_orderby_with_invalid( $orderby ) {
291
+ $this->assertFalse( c2c_AdminPostNavigation::is_valid_orderby( $orderby ) );
292
+ }
293
+
294
+
295
+ /*
296
+ * c2c_AdminPostNavigation::get_post_type_orderby()
297
+ */
298
+
299
+
300
+ public function test_get_post_type_orderby() {
301
+ $this->assertEquals( 'post_title', c2c_AdminPostNavigation::get_post_type_orderby( 'page' ) );
302
+ $this->assertEquals( 'post_date', c2c_AdminPostNavigation::get_post_type_orderby( 'post' ) );
303
+ }
304
+
305
+ public function test_get_post_type_orderby_for_user_with_no_saved_screen_option() {
306
+ $user_id = $this->create_user( 'administrator' );
307
+
308
+ $this->assertEquals( 'post_title', c2c_AdminPostNavigation::get_post_type_orderby( 'page', $user_id ) );
309
+ $this->assertEquals( 'post_date', c2c_AdminPostNavigation::get_post_type_orderby( 'post', $user_id ) );
310
+ }
311
+
312
+ public function test_get_post_type_orderby_for_user_with_saved_screen_option() {
313
+ $user_id = $this->create_user( 'administrator' );
314
+ add_user_meta( $user_id, c2c_AdminPostNavigation::get_setting_name( 'page' ), 'ID', true );
315
+
316
+ $this->assertEquals( 'ID', c2c_AdminPostNavigation::get_post_type_orderby( 'page', $user_id ) );
317
+ // Ensure it doesn't affect value for other post types.
318
+ $this->assertEquals( 'post_date', c2c_AdminPostNavigation::get_post_type_orderby( 'post', $user_id ) );
319
+ }
320
+
321
+
322
+ /*
323
+ * c2c_AdminPostNavigation::get_setting_name()
324
+ */
325
+
326
+
327
+ public function test_get_setting_name() {
328
+ $this->assertEquals( 'c2c_apn_page_orderby', c2c_AdminPostNavigation::get_setting_name( 'page' ) );
329
+ $this->assertEquals( 'c2c_apn_post_orderby', c2c_AdminPostNavigation::get_setting_name( 'post' ) );
330
+ $this->assertEquals( 'c2c_apn_book_orderby', c2c_AdminPostNavigation::get_setting_name( 'book' ) );
331
+ }
332
+
333
 
334
  /*
335
  * Filters.
349
  }
350
 
351
  public function test_filter_c2c_admin_post_navigation_post_statuses_when_adding_post_status() {
 
 
352
  $posts = $this->create_posts();
353
 
354
+ add_filter( 'c2c_admin_post_navigation_post_statuses', array( $this, 'c2c_admin_post_navigation_post_statuses' ), 10, 2 );
355
+
356
  $post = get_post( $posts[3] );
357
+ wp_trash_post( $post->ID );
358
+ $post = get_post( $posts[2] );
359
 
360
  $next_post = c2c_AdminPostNavigation::next_post();
361
 
363
  }
364
 
365
  public function test_filter_c2c_admin_post_navigation_post_statuses_when_removing_post_status() {
 
 
366
  $posts = $this->create_posts();
367
 
368
+ add_filter( 'c2c_admin_post_navigation_post_statuses', array( $this, 'c2c_admin_post_navigation_post_statuses' ), 10, 3 );
369
+
370
  $post = get_post( $posts[3] );
371
  $post->post_status = 'draft';
372
  wp_update_post( $post );