Reorder Posts - Version 2.1.0

Version Description

  • Released 2015-01-19
  • Added add-on support
  • Make sure reordering can only be done by those with edit_pages privileges
  • Added pagination for performance reasons
  • Optimized queries for performance reasons
  • Added warning message for those with a lot of posts
Download this release

Release Info

Developer ronalfy
Plugin Icon 128x128 Reorder Posts
Version 2.1.0
Comparing to
See all releases

Code changes from version 2.0.2 to 2.1.0

Files changed (5) hide show
  1. class-reorder.php +332 -181
  2. index.php +21 -12
  3. languages/metronet-reorder-posts.pot +21 -6
  4. readme.txt +29 -8
  5. scripts/sort.js +97 -5
class-reorder.php CHANGED
@@ -21,7 +21,7 @@
21
  * @author Ryan Hellyer <ryan@metronet.no>
22
  * @since 1.0
23
  */
24
- class MN_Reorder {
25
 
26
  /**
27
  * @var $post_type
@@ -29,13 +29,20 @@ class MN_Reorder {
29
  * @access private
30
  */
31
  private $post_type;
32
-
33
  /**
34
- * @var $direction
35
- * @desc ASC or DESC
 
 
 
 
 
 
 
36
  * @access private
37
  */
38
- private $direction;
39
 
40
  /**
41
  * @var $heading
@@ -71,7 +78,69 @@ class MN_Reorder {
71
  * @access private
72
  */
73
  private $menu_label;
74
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  /**
76
  * Class constructor
77
  *
@@ -94,6 +163,8 @@ class MN_Reorder {
94
  'final' => '', // Initial text displayed before sorting code
95
  'post_status' => 'publish', // Post status of posts to be reordered
96
  'menu_label' => __( 'Reorder', 'metronet-reorder-posts' ), //Menu label for the post type
 
 
97
  );
98
  $args = wp_parse_args( $args, $defaults );
99
 
@@ -106,63 +177,119 @@ class MN_Reorder {
106
  $this->menu_label = $args[ 'menu_label' ];
107
  $this->post_status = $args[ 'post_status' ];
108
 
 
 
 
 
 
 
 
109
  // Add actions
110
  add_action( 'wp_ajax_post_sort', array( $this, 'ajax_save_post_order' ) );
111
  add_action( 'admin_menu', array( $this, 'enable_post_sort' ), 10, 'page' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
  }
113
-
114
 
115
  /**
116
  * Saving the post oder for later use
117
  *
118
- * @author Ryan Hellyer <ryan@metronet.no> and Ronald Huereca <ronald@metronet.no>
119
  * @since Reorder 1.0
120
  * @access public
121
  * @global object $wpdb The primary global database object used internally by WordPress
122
  */
123
  public function ajax_save_post_order() {
124
  global $wpdb;
125
-
 
126
  // Verify nonce value, for security purposes
127
  if ( !wp_verify_nonce( $_POST['nonce'], 'sortnonce' ) ) die( '' );
128
 
129
- //Get JSON data
130
- $post_data = json_decode( str_replace( "\\", '', $_POST[ 'data' ] ) );
 
 
 
 
 
131
 
132
- //Iterate through post data
133
- $this->update_posts( $post_data, 0 );
134
 
135
- die( json_encode( array( 'success' => 'true' ) ) );
136
- } //end ajax_save_post_order
137
-
138
- /**
139
- * Saving the post order recursively
140
- *
141
- * @author Ronald Huereca <ronald@metronet.no>
142
- * @since Reorder 1.0
143
- * @access public
144
- * @global object $wpdb The primary global database object used internally by WordPress
145
- */
146
- private function update_posts( $post_data, $parent_id ) {
147
- global $wpdb;
148
- $count = 0;
 
 
 
 
149
 
150
- foreach( $post_data as $post_obj ) {
151
- $post_id = absint( $post_obj->id );
152
- $children = isset( $post_obj->children ) ? $post_obj->children : false;
153
- if ( $children )
154
- $this->update_posts( $children, $post_id );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
155
 
156
- //Update the posts
157
- $wpdb->update(
158
- $wpdb->posts,
159
- array( 'menu_order' => $count, 'post_parent' => $parent_id ),
160
- array( 'ID' => $post_id )
161
- );
162
- $count += 1;
163
-
164
- } //end foreach $post_data
165
- } //end update_posts
 
 
 
 
 
 
 
 
 
166
 
167
  /**
168
  * Print styles to admin page
@@ -173,13 +300,7 @@ class MN_Reorder {
173
  * @global string $pagenow Used internally by WordPress to designate what the current page is in the admin panel
174
  */
175
  public function print_styles() {
176
- global $pagenow;
177
-
178
- $pages = array( 'edit.php' );
179
-
180
- if ( in_array( $pagenow, $pages ) )
181
- wp_enqueue_style( 'reorderpages_style', REORDER_URL . '/css/admin.css' );
182
-
183
  }
184
 
185
  /**
@@ -191,19 +312,15 @@ class MN_Reorder {
191
  * @global string $pagenow Used internally by WordPress to designate what the current page is in the admin panel
192
  */
193
  public function print_scripts() {
194
- global $pagenow, $hook_suffix;
195
- $pages = array( 'edit.php' );
196
-
197
- if ( in_array( $pagenow, $pages ) ) {
198
- wp_register_script( 'reorder_nested', REORDER_URL . '/scripts/jquery.mjs.nestedSortable.js', array( 'jquery-ui-sortable' ), '1.3.5', true );
199
- wp_enqueue_script( 'reorder_posts', REORDER_URL . '/scripts/sort.js', array( 'reorder_nested' ) );
200
- wp_localize_script( 'reorder_posts', 'reorder_posts', array(
201
- 'expand' => esc_js( __( 'Expand', 'reorder' ) ),
202
- 'collapse' => esc_js( __( 'Collapse', 'reorder' ) ),
203
- 'sortnonce' => wp_create_nonce( 'sortnonce' ),
204
- 'hierarchical' => is_post_type_hierarchical( $this->post_type ) ? 'true' : 'false',
205
- ) );
206
- }
207
  }
208
 
209
  /**
@@ -221,171 +338,205 @@ class MN_Reorder {
221
  $menu_location, // Parent slug
222
  $this->heading, // Page title (unneeded since specified directly)
223
  apply_filters( 'metronet_reorder_menu_label_' . $post_type, $this->menu_label , $post_type ), // Menu title
224
- 'edit_posts', // Capability
225
  'reorder-' . $post_type, // Menu slug
226
  array( $this, 'sort_posts' ) // Callback function
227
  );
 
228
  }
229
  else {
230
  $hook = add_posts_page(
231
  $this->heading, // Page title (unneeded since specified directly)
232
  apply_filters( 'metronet_reorder_menu_label_' . $post_type, $this->menu_label ), // Menu title
233
- 'edit_posts', // Capability
234
  'reorder-posts', // Menu slug
235
  array( $this, 'sort_posts' ) // Callback function
236
  );
 
237
  }
 
 
238
  add_action( 'admin_print_styles-' . $hook, array( $this, 'print_styles' ) );
239
  add_action( 'admin_print_scripts-' . $hook, array( $this, 'print_scripts' ) );
240
  }
241
 
242
  /**
243
- * Post Row Output
244
- *
245
- * @author Ronald Huereca <ronald@metronet.no>
246
- * @since Reorder 1.0.1
247
- * @access private
248
- * @param stdclass $post object to post
249
- */
250
- private function output_row( $the_post ) {
251
- global $post;
252
- $post = $the_post;
253
- setup_postdata( $post );
 
 
 
254
  ?>
255
- <li id="list_<?php the_id(); ?>"><div><?php the_title(); ?></div></li>
 
 
 
 
 
 
 
256
  <?php
257
- } //end output_row
258
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
259
  /**
260
- * Post Row Output for Hierarchical posts
261
  *
262
- * @author Ronald Huereca <ronald@metronet.no>
263
- * @since Reorder 1.0.1
264
  * @access private
265
  * @param stdclass $post object to post
266
- * @param array $all_children - array of children
267
  */
268
- private function output_row_hierarchical( $the_post, $post_children, $all_children ) {
269
  global $post;
270
- $post = $the_post;
271
- $post_id = $the_post->ID;
272
-
273
  setup_postdata( $post );
274
  ?>
275
- <li id="list_<?php the_id(); ?>">
276
- <div><?php the_title(); ?> <a href='#' style="float: right"><?php esc_html_e( 'Expand', 'metronet-reorder-posts' ); ?></a></div>
277
- <ul class='children'>
278
- <?php $this->output_row_children( $post_children, $all_children ); ?>
279
- </ul>
280
- </li>
281
- <?php
282
-
283
- ?>
284
- <?php
285
- } //end output_row_hierarchical
286
-
287
- /**
288
- * Output children posts
289
- *
290
- * @author Ronald Huereca <ronald@metronet.no>
291
- * @since Reorder 1.0.1
292
- * @access private
293
- * @param stdclass $post object to post
294
- * @param array $children_pages - array of children
295
- */
296
- private function output_row_children( $children_pages, $all_children ) {
297
- foreach( $children_pages as $child ) {
298
- $post_id = $child->ID;
299
- if ( isset( $all_children[ $post_id ] ) && !empty( $all_children[ $post_id ] ) ) {
300
- $this->output_row_hierarchical( $child, $all_children[ $post_id ], $all_children );
301
  } else {
302
- $this->output_row( $child );
 
 
303
  }
304
 
305
- } //end foreach $child
306
- } //end output_row_children
307
-
 
 
 
 
 
 
 
 
 
 
308
 
309
-
310
  /**
311
- * HTML output
312
  *
313
- * @author Ryan Hellyer <ryan@metronet.no>
314
- * @since Reorder 1.0
315
  * @access public
316
  * @global string $post_type
317
  */
318
  public function sort_posts() {
319
- $has_posts = false;
320
  ?>
321
- </style>
322
  <div class="wrap">
323
  <h2>
324
  <?php echo esc_html( $this->heading ); ?>
325
- <img src="<?php echo esc_url( admin_url( 'images/loading.gif' ) ); ?>" id="loading-animation" />
326
  </h2>
327
- <div id="reorder-error"></div>
328
- <?php echo esc_html( $this->initial ); ?>
329
- <?php
330
- if ( is_post_type_hierarchical( $this->post_type ) ) {
331
- $pages = get_pages( array(
332
- 'sort_column' => 'menu_order',
333
- 'post_type' => $this->post_type,
334
- ) );
335
- if( $pages ) {
336
- $has_posts = true;
337
- echo '<ul id="post-list">';
338
- //Get hiearchy of children/parents
339
- $top_level_pages = array();
340
- $children_pages = array();
341
- foreach( $pages as $page ) {
342
- if ( $page->post_parent == 0 ) {
343
- //Parent page
344
- $top_level_pages[] = $page;
345
- } else {
346
- $children_pages[ $page->post_parent ][] = $page;
347
- }
348
- } //end foreach
349
-
350
- foreach( $top_level_pages as $page ) {
351
- $page_id = $page->ID;
352
- if ( isset( $children_pages[ $page_id ] ) && !empty( $children_pages[ $page_id ] ) ) {
353
- //If page has children, output page and its children
354
- $this->output_row_hierarchical( $page, $children_pages[ $page_id ], $children_pages );
355
- } else {
356
- $this->output_row( $page );
357
- }
358
- }
359
- echo '</ul>';
360
- }
361
- } else {
362
- //Output non hierarchical posts
363
- $post_query = new WP_Query(
364
  array(
365
- 'post_type' => $this->post_type,
366
- 'posts_per_page' => -1,
367
- 'orderby' => 'menu_order',
368
- 'order' => $this->order,
369
- 'post_status' => $this->post_status,
370
  )
371
  );
372
- $posts = $post_query->get_posts();
373
- if( $posts && !empty( $posts ) ) {
374
- $has_posts = true;
375
- echo '<ul id="post-list">';
376
- foreach( $posts as $post ) {
377
- $this->output_row( $post );
378
- } //end foreach
379
- echo '</ul>';
380
- }
381
- }
382
- if ( false === $has_posts ) {
383
- echo sprintf( '<h3>%s</h3> ', esc_html__( 'There is nothing to sort at this time', 'metronet-reorder-posts' ) );
384
- }
385
- echo esc_html( $this->final );
386
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
387
  </div><!-- .wrap -->
388
  <?php
389
  } //end sort_posts
390
 
391
- }
21
  * @author Ryan Hellyer <ryan@metronet.no>
22
  * @since 1.0
23
  */
24
+ final class MN_Reorder {
25
 
26
  /**
27
  * @var $post_type
29
  * @access private
30
  */
31
  private $post_type;
32
+
33
  /**
34
+ * @var $posts_per_page
35
+ * @desc How many posts to show
36
+ * @access private
37
+ */
38
+ private $posts_per_page;
39
+
40
+ /**
41
+ * @var $offset
42
+ * @desc How many posts to offset by
43
  * @access private
44
  */
45
+ private $offset;
46
 
47
  /**
48
  * @var $heading
78
  * @access private
79
  */
80
  private $menu_label;
81
+
82
+ /**
83
+ * @var $order
84
+ * @desc ASC or DESC
85
+ * @access private
86
+ */
87
+ private $order;
88
+
89
+ /**
90
+ * @var $reorder_page
91
+ * @desc Where the reorder interface is being added
92
+ * @access private
93
+ */
94
+ private $reorder_page = '';
95
+
96
+ /**
97
+ * Get method for post status
98
+ *
99
+ * @author Ronald Huereca <ronald@gmail.com>
100
+ * @since Reorder 2.1.0
101
+ * @access public
102
+ * @returns string $post_status Post Status of Posts
103
+ */
104
+ public function get_post_status() {
105
+ return $this->post_status;
106
+ }
107
+
108
+ /**
109
+ * Get method for post order
110
+ *
111
+ * @author Ronald Huereca <ronald@gmail.com>
112
+ * @since Reorder 2.1.0
113
+ * @access public
114
+ * @returns string $order Order of posts (ASC or DESC)
115
+ */
116
+ public function get_post_order() {
117
+ return $this->order;
118
+ }
119
+
120
+ /**
121
+ * Get method for posts per page
122
+ *
123
+ * @author Ronald Huereca <ronald@gmail.com>
124
+ * @since Reorder 2.1.0
125
+ * @access public
126
+ * @returns int $posts_per_page How many posts to display
127
+ */
128
+ public function get_posts_per_page() {
129
+ return $this->posts_per_page;
130
+ }
131
+
132
+ /**
133
+ * Get method for post offset used in pagination
134
+ *
135
+ * @author Ronald Huereca <ronald@gmail.com>
136
+ * @since Reorder 2.1.0
137
+ * @access public
138
+ * @returns int $offset Offset of posts
139
+ */
140
+ public function get_offset() {
141
+ return $this->offset;
142
+ }
143
+
144
  /**
145
  * Class constructor
146
  *
163
  'final' => '', // Initial text displayed before sorting code
164
  'post_status' => 'publish', // Post status of posts to be reordered
165
  'menu_label' => __( 'Reorder', 'metronet-reorder-posts' ), //Menu label for the post type
166
+ 'offset' => 48,
167
+ 'posts_per_page' => 50
168
  );
169
  $args = wp_parse_args( $args, $defaults );
170
 
177
  $this->menu_label = $args[ 'menu_label' ];
178
  $this->post_status = $args[ 'post_status' ];
179
 
180
+ //Get offset and posts_per_page
181
+ $this->posts_per_page = absint( $args[ 'posts_per_page' ] ); //todo - filterable?
182
+ $this->offset = absint( $args[ 'offset' ] ); //todo - filterable?
183
+ if ( $this->offset > $this->posts_per_page ) {
184
+ $this->offset = $this->posts_per_page;
185
+ }
186
+
187
  // Add actions
188
  add_action( 'wp_ajax_post_sort', array( $this, 'ajax_save_post_order' ) );
189
  add_action( 'admin_menu', array( $this, 'enable_post_sort' ), 10, 'page' );
190
+ add_action( 'metronet_reorder_posts_interface_' . $this->post_type, array( $this, 'output_interface' ) );
191
+ }
192
+ /**
193
+ * Adjust the found posts for the offset
194
+ *
195
+ * @author Ronald Huereca <ronald@gmail.com>
196
+ * @since Reorder 2.1.0
197
+ * @access public
198
+ * @returns int $found_posts Number of posts
199
+ */
200
+ public function adjust_offset_pagination( $found_posts, $query ) {
201
+ //This sometimes will have a bug of showing an extra page, but it doesn't break anything, so leaving it for now.
202
+ if( $found_posts > $this->posts_per_page ) {
203
+ $num_pages = round($found_posts / $this->offset);
204
+ $found_posts = (string)round( $num_pages * $this->posts_per_page );
205
+ }
206
+ return $found_posts;
207
  }
 
208
 
209
  /**
210
  * Saving the post oder for later use
211
  *
212
+ * @author Ronald Huereca <ronalfy@gmail.com>
213
  * @since Reorder 1.0
214
  * @access public
215
  * @global object $wpdb The primary global database object used internally by WordPress
216
  */
217
  public function ajax_save_post_order() {
218
  global $wpdb;
219
+
220
+ if ( !current_user_can( 'edit_pages' ) ) die( '' );
221
  // Verify nonce value, for security purposes
222
  if ( !wp_verify_nonce( $_POST['nonce'], 'sortnonce' ) ) die( '' );
223
 
224
+ //Get Ajax Vars
225
+ $post_parent = isset( $_POST[ 'post_parent' ] ) ? absint( $_POST[ 'post_parent' ] ) : 0;
226
+ $menu_order_start = isset( $_POST[ 'start' ] ) ? absint( $_POST[ 'start' ] ) : 0;
227
+ $post_id = isset( $_POST[ 'post_id' ] ) ? absint( $_POST[ 'post_id' ] ) : 0;
228
+ $post_menu_order = isset( $_POST[ 'menu_order' ] ) ? absint( $_POST[ 'menu_order' ] ) : 0;
229
+ $posts_to_exclude = isset( $_POST[ 'excluded' ] ) ? array_filter( $_POST[ 'excluded' ], 'absint' ) : array();
230
+ $post_type = isset( $_POST[ 'post_type' ] ) ? sanitize_text_field( $_POST[ 'post_type' ] ) : false;
231
 
232
+ if ( !$post_type ) die( '' );
 
233
 
234
+ //Performance
235
+ remove_action( 'pre_post_update', 'wp_save_post_revision' );
236
+
237
+ //Build Initial Return
238
+ $return = array();
239
+ $return[ 'more_posts' ] = false;
240
+ $return[ 'action' ] = 'post_sort';
241
+ $return[ 'post_parent' ] = $post_parent;
242
+ $return[ 'nonce' ] = sanitize_text_field( $_POST[ 'nonce' ] );
243
+ $return[ 'post_id'] = $post_id;
244
+ $return[ 'menu_order' ] = $post_menu_order;
245
+ $return[ 'post_type' ] = $post_type;
246
+
247
+ //Update post if passed - Should run only on beginning of first iteration
248
+ if( $post_id > 0 && !isset( $_POST[ 'more_posts' ] ) ) {
249
+ wp_update_post( array( 'ID' => $post_id, 'post_parent' => $post_parent, 'menu_order' => $post_menu_order ) );
250
+ $posts_to_exclude[] = $post_id;
251
+ }
252
 
253
+ //Build Query
254
+ $query_args = array(
255
+ 'post_type' => $post_type,
256
+ 'orderby' => 'menu_order title',
257
+ 'order' => $this->order,
258
+ 'posts_per_page' => 50,
259
+ 'suppress_filters' => true,
260
+ 'ignore_sticky_posts' => true,
261
+ 'post_status' => $this->post_status,
262
+ 'post_parent' => $post_parent,
263
+ 'post__not_in' => $posts_to_exclude
264
+ );
265
+ $posts = new WP_Query( $query_args );
266
+ $start = $menu_order_start;
267
+ if ( $posts->have_posts() ) {
268
+ foreach( $posts->posts as $post ) {
269
+ //Increment start if matches menu_order and there is a post to change
270
+ if ( $start == $post_menu_order && $post_id > 0 ) {
271
+ $start++;
272
+ }
273
 
274
+ if ( $post_id != $post->ID ) {
275
+ //Update post and counts
276
+ wp_update_post( array( 'ID' => $post->ID, 'menu_order' => $start, 'post_parent' => $post_parent ) );
277
+ }
278
+ $posts_to_exclude[] = $post->ID;
279
+ $start++;
280
+ }
281
+ $return[ 'excluded' ] = $posts_to_exclude;
282
+ $return[ 'start' ] = $start;
283
+ if ( $posts->max_num_pages > 1 ) {
284
+ $return[ 'more_posts' ] = true;
285
+ } else {
286
+ $return[ 'more_posts' ] = false;
287
+ }
288
+ die( json_encode( $return ) );
289
+ } else {
290
+ die( json_encode( $return ) );
291
+ }
292
+ } //end ajax_save_post_order
293
 
294
  /**
295
  * Print styles to admin page
300
  * @global string $pagenow Used internally by WordPress to designate what the current page is in the admin panel
301
  */
302
  public function print_styles() {
303
+ wp_enqueue_style( 'reorderpages_style', REORDER_URL . '/css/admin.css' );
 
 
 
 
 
 
304
  }
305
 
306
  /**
312
  * @global string $pagenow Used internally by WordPress to designate what the current page is in the admin panel
313
  */
314
  public function print_scripts() {
315
+ wp_register_script( 'reorder_nested', REORDER_URL . '/scripts/jquery.mjs.nestedSortable.js', array( 'jquery-ui-sortable' ), '1.3.5', true );
316
+ wp_enqueue_script( 'reorder_posts', REORDER_URL . '/scripts/sort.js', array( 'reorder_nested' ) );
317
+ wp_localize_script( 'reorder_posts', 'reorder_posts', array(
318
+ 'action' => 'post_sort',
319
+ 'expand' => esc_js( __( 'Expand', 'metronet-reorder-posts' ) ),
320
+ 'collapse' => esc_js( __( 'Collapse', 'metronet-reorder-posts' ) ),
321
+ 'sortnonce' => wp_create_nonce( 'sortnonce' ),
322
+ 'hierarchical' => is_post_type_hierarchical( $this->post_type ) ? 'true' : 'false',
323
+ ) );
 
 
 
 
324
  }
325
 
326
  /**
338
  $menu_location, // Parent slug
339
  $this->heading, // Page title (unneeded since specified directly)
340
  apply_filters( 'metronet_reorder_menu_label_' . $post_type, $this->menu_label , $post_type ), // Menu title
341
+ 'edit_pages', // Capability
342
  'reorder-' . $post_type, // Menu slug
343
  array( $this, 'sort_posts' ) // Callback function
344
  );
345
+ $this->reorder_page = add_query_arg( array( 'page' => 'reorder-' . $post_type ), admin_url( $menu_location ) );
346
  }
347
  else {
348
  $hook = add_posts_page(
349
  $this->heading, // Page title (unneeded since specified directly)
350
  apply_filters( 'metronet_reorder_menu_label_' . $post_type, $this->menu_label ), // Menu title
351
+ 'edit_pages', // Capability
352
  'reorder-posts', // Menu slug
353
  array( $this, 'sort_posts' ) // Callback function
354
  );
355
+ $this->reorder_page = add_query_arg( array( 'page' => 'reorder-posts' ), admin_url( 'edit.php' ) );
356
  }
357
+ do_action( 'metronet_reorder_posts_add_menu_' . $post_type, $hook ); //Allow other plugin authors to add scripts/styles to our menu items
358
+ do_action( 'metronet_reorder_menu_url_' . $post_type, $this->reorder_page );
359
  add_action( 'admin_print_styles-' . $hook, array( $this, 'print_styles' ) );
360
  add_action( 'admin_print_scripts-' . $hook, array( $this, 'print_scripts' ) );
361
  }
362
 
363
  /**
364
+ * Output the main Reorder Interface
365
+ *
366
+ * @author Ryan Hellyer <ryan@metronet.no> and Ronald Huereca <ronalfy@gmail.com>
367
+ * @since Reorder 2.1.0
368
+ * @access public
369
+ * @global string $post_type
370
+ */
371
+ public function output_interface() {
372
+ echo '<br />';
373
+ $post_count_obj = wp_count_posts( $this->post_type );
374
+ $post_count = isset( $post_count_obj->{$this->post_status} ) ?absint( $post_count_obj->{$this->post_status} ) : absint( $post_count_obj[ 'publish' ] );
375
+ if ( $post_count >= 1000 ) {
376
+ printf( '<div class="error"><p>%s</p></div>', sprintf( __( 'There are over %s posts found. We do not recommend you sort these posts for performance reasons.', 'metronet_reorder_posts' ), number_format( $post_count ) ) );
377
+ }
378
  ?>
379
+ <div id="reorder-error"></div>
380
+ <div><img src="<?php echo esc_url( admin_url( 'images/loading.gif' ) ); ?>" id="loading-animation" /></div>
381
+ <div class="updated">
382
+ <p><strong>
383
+ <?php echo sprintf( __( 'Note: reordering here does not change the order on your website without some code modifications. Please see our <a target="_blank" href="%s">Wiki</a>.', 'metronet-reorder-posts' ), 'https://github.com/ronalfy/reorder-posts/wiki' ); ?>
384
+ </strong></p>
385
+ </div>
386
+ <?php echo esc_html( $this->initial ); ?>
387
  <?php
388
+ //Output non hierarchical posts
389
+ $page = isset( $_GET[ 'paged' ] ) ? absint( $_GET[ 'paged' ] ) : 0;
390
+ if ( $page == 0 ) {
391
+ $offset = 0;
392
+ } elseif ( $page > 1 ) {
393
+ $offset = $this->offset * ( $page - 1 );
394
+ }
395
+ printf( '<input type="hidden" id="reorder-offset" value="%s" />', absint( $offset ) );
396
+ add_filter( 'found_posts', array( $this, 'adjust_offset_pagination' ), 10, 2 );
397
+ $post_query = new WP_Query(
398
+ array(
399
+ 'post_type' => $this->post_type,
400
+ 'posts_per_page' => $this->posts_per_page,
401
+ 'orderby' => 'menu_order title',
402
+ 'order' => $this->order,
403
+ 'post_status' => $this->post_status,
404
+ 'post_parent' => 0,
405
+ 'offset' => $offset
406
+ )
407
+ );
408
+ remove_filter( 'found_posts', array( $this, 'adjust_offset_pagination' ), 10, 2 );
409
+ if( $post_query->have_posts() ) {
410
+ echo '<ul id="post-list">';
411
+ while( $post_query->have_posts() ) {
412
+ global $post;
413
+ $post_query->the_post();
414
+ $this->output_row( $post );
415
+ }
416
+ echo '</ul><!-- #post-list -->';
417
+
418
+ //Show pagination links
419
+ if( $post_query->max_num_pages > 1 ) {
420
+ echo '<div id="reorder-pagination">';
421
+ $current_url = add_query_arg( array( 'paged' => '%#%' ) );
422
+ $pagination_args = array(
423
+ 'base' => $current_url,
424
+ 'total' => $post_query->max_num_pages,
425
+ 'current' => ( $page == 0 ) ? 1 : $page
426
+ );
427
+ echo paginate_links( $pagination_args );
428
+ echo '</div>';
429
+ }
430
+ } else {
431
+ echo sprintf( '<h3>%s</h3> ', esc_html__( 'There is nothing to sort at this time', 'metronet-reorder-posts' ) );
432
+ }
433
+ echo esc_html( $this->final );
434
+ }
435
  /**
436
+ * Post Row Output
437
  *
438
+ * @author Ronald Huereca <ronalfy@gmail.com>
439
+ * @since Reorder 2.1.0
440
  * @access private
441
  * @param stdclass $post object to post
 
442
  */
443
+ private function output_row( $post ) {
444
  global $post;
 
 
 
445
  setup_postdata( $post );
446
  ?>
447
+ <li id="list_<?php the_id(); ?>" data-id="<?php the_id(); ?>" data-menu-order="<?php echo absint( $post->menu_order ); ?>" data-parent="<?php echo absint( $post->post_parent ); ?>" data-post-type="<?php echo esc_attr( $post->post_type ); ?>">
448
+ <?php
449
+ //Get the children
450
+ $args = array(
451
+ 'post_type' => $this->post_type,
452
+ 'post_status' => $this->post_status,
453
+ 'posts_per_page' => 100, /*hope there's never more than 100 children*/
454
+ 'post_parent' => get_the_ID(),
455
+ 'orderby' => 'menu_order',
456
+ 'order' => $this->order,
457
+ );
458
+ $children = new WP_Query( $args );
459
+ //Output parent title
460
+ if( $children->have_posts() ) {
461
+ ?>
462
+ <div><?php the_title(); ?><?php echo ( defined( 'REORDER_DEBUG' ) && REORDER_DEBUG == true ) ? ' - Menu Order:' . absint( $post->menu_order ) : ''; ?><a href='#' style="float: right"><?php esc_html_e( 'Expand', 'metronet-reorder-posts' ); ?></a></div>
463
+ <?php
 
 
 
 
 
 
 
 
 
464
  } else {
465
+ ?>
466
+ <div><?php the_title(); ?><?php echo ( defined( 'REORDER_DEBUG' ) && REORDER_DEBUG == true ) ? ' - Menu Order:' . absint( $post->menu_order ) : ''; ?></div>
467
+ <?php
468
  }
469
 
470
+ if( $children->have_posts() ) {
471
+ echo '<ul class="children">';
472
+ while( $children->have_posts() ) {
473
+ global $post;
474
+ $children->the_post();
475
+ $this->output_row( $post );
476
+ }
477
+ echo '</ul>';
478
+ }
479
+ ?>
480
+ </li>
481
+ <?php
482
+ } //end output_row
483
 
 
484
  /**
485
+ * Initial HTML output
486
  *
487
+ * @author Ryan Hellyer <ryan@metronet.no> and Ronald Huereca <ronalfy@gmail.com>
488
+ * @since Reorder 2.1.0
489
  * @access public
490
  * @global string $post_type
491
  */
492
  public function sort_posts() {
493
+ //Dev note - Settings API not used here because there are no options to save.
494
  ?>
 
495
  <div class="wrap">
496
  <h2>
497
  <?php echo esc_html( $this->heading ); ?>
 
498
  </h2>
499
+ <?php
500
+ $tabs =
501
+ array(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
502
  array(
503
+ 'url' => $this->reorder_page /* URL to the tab */,
504
+ 'label' => $this->heading,
505
+ 'get' => 'main' /*$_GET variable*/,
506
+ 'action' => 'metronet_reorder_posts_interface_' . $this->post_type /* action variable in do_action */
 
507
  )
508
  );
509
+ $tabs = apply_filters( 'metronet_reorder_posts_tabs_' . $this->post_type, (array)$tabs );
510
+ $tabs_count = count( $tabs );
511
+
512
+ //Output tabs
513
+ $tab_html = '';
514
+ if ( $tabs && !empty( $tabs ) ) {
515
+ $tab_html .= '<h2 class="nav-tab-wrapper">';
516
+ $active_tab = isset( $_GET[ 'tab' ] ) ? sanitize_text_field( $_GET[ 'tab' ] ) : 'main';
517
+ $do_action = false;
518
+ foreach( $tabs as $tab ) {
519
+ $classes = array( 'nav-tab' );
520
+ $tab_get = isset( $tab[ 'get' ] ) ? $tab[ 'get' ] : '';
521
+ if ( $active_tab == $tab_get ) {
522
+ $classes[] = 'nav-tab-active';
523
+ $do_action = isset( $tab[ 'action' ] ) ? $tab[ 'action' ] : false;
524
+ }
525
+ $tab_url = isset( $tab[ 'url' ] ) ? $tab[ 'url' ] : '';
526
+ $tab_label = isset( $tab[ 'label' ] ) ? $tab[ 'label' ] : '';
527
+ $tab_html .= sprintf( '<a href="%s" class="%s">%s</a>', esc_url( $tab_url ), esc_attr( implode( ' ', $classes ) ), esc_html( $tab[ 'label' ] ) );
528
+ }
529
+ $tab_html .= '</h2>';
530
+ if ( $tabs_count > 1 ) {
531
+ echo $tab_html;
532
+ }
533
+ if ( $do_action ) {
534
+ do_action( $do_action );
535
+ }
536
+ }
537
+ ?>
538
  </div><!-- .wrap -->
539
  <?php
540
  } //end sort_posts
541
 
542
+ }
index.php CHANGED
@@ -2,8 +2,8 @@
2
  /*
3
  Plugin Name: Metronet Reorder Posts
4
  Plugin URI: https://wordpress.org/plugins/metronet-reorder-posts/
5
- Description: Reorder posts
6
- Version: 2.0.2
7
  Author: Ryan Hellyer, Ronald Huereca, Scott Basgaard
8
  Author URI: https://github.com/ronalfy/reorder-posts
9
  Text Domain: metronet-reorder-posts
@@ -50,6 +50,7 @@ require( 'class-reorder-admin.php' );
50
  * @since 1.0
51
  * @author Ryan Hellyer <ryan@metronet.no>
52
  */
 
53
  define( 'REORDER_DIR', rtrim( plugin_dir_path(__FILE__), '/' ) ); // Plugin folder DIR
54
  define( 'REORDER_URL', rtrim( plugin_dir_url(__FILE__), '/' ) ); // Plugin folder URL
55
  define( 'REORDER_BASENAME', plugin_basename(__FILE__) ); //Plugin basename
@@ -63,6 +64,7 @@ define( 'REORDER_BASENAME', plugin_basename(__FILE__) ); //Plugin basename
63
  */
64
  add_action( 'wp_loaded', 'mn_reorder_posts_init', 100 ); //Load low priority in init for other plugins to generate their post types
65
  function mn_reorder_posts_init() {
 
66
  $post_types = get_post_types( array(), 'names' );
67
 
68
  //Get plugin options for post types and exclude as necessary
@@ -77,6 +79,7 @@ function mn_reorder_posts_init() {
77
 
78
  // Add filter to allow users to control which post-types the plugin is used with via their theme
79
  $post_types = array_unique( apply_filters( 'metronet_reorder_post_types', $post_types ) );
 
80
 
81
  foreach ( $post_types as $post_type ) {
82
  //Generate heading
@@ -85,16 +88,18 @@ function mn_reorder_posts_init() {
85
  $heading = sprintf( __( 'Reorder %s', 'metronet-reorder-posts' ), $post_type_label );
86
 
87
  // Instantiate new reordering
88
- new MN_Reorder(
89
- array(
90
- 'post_type' => $post_type,
91
- 'order' => 'ASC',
92
- 'heading' => $heading,
93
- 'final' => '',
94
- 'initial' => '',
95
- 'menu_label' => __( 'Reorder', 'metronet-reorder-posts' ),
96
- 'post_status' => 'publish',
97
- )
 
 
98
  );
99
  }
100
  } //end mt_reorder_posts_init
@@ -105,3 +110,7 @@ function mn_reorder_init_language() {
105
  load_plugin_textdomain( 'metronet-reorder-posts', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
106
  }
107
 
 
 
 
 
2
  /*
3
  Plugin Name: Metronet Reorder Posts
4
  Plugin URI: https://wordpress.org/plugins/metronet-reorder-posts/
5
+ Description: Easily reorder posts and pages in WordPress
6
+ Version: 2.1.0
7
  Author: Ryan Hellyer, Ronald Huereca, Scott Basgaard
8
  Author URI: https://github.com/ronalfy/reorder-posts
9
  Text Domain: metronet-reorder-posts
50
  * @since 1.0
51
  * @author Ryan Hellyer <ryan@metronet.no>
52
  */
53
+ define( 'REORDER_ALLOW_ADDONS', true ); // Plugin folder DIR
54
  define( 'REORDER_DIR', rtrim( plugin_dir_path(__FILE__), '/' ) ); // Plugin folder DIR
55
  define( 'REORDER_URL', rtrim( plugin_dir_url(__FILE__), '/' ) ); // Plugin folder URL
56
  define( 'REORDER_BASENAME', plugin_basename(__FILE__) ); //Plugin basename
64
  */
65
  add_action( 'wp_loaded', 'mn_reorder_posts_init', 100 ); //Load low priority in init for other plugins to generate their post types
66
  function mn_reorder_posts_init() {
67
+ global $mn_reorder_instances;
68
  $post_types = get_post_types( array(), 'names' );
69
 
70
  //Get plugin options for post types and exclude as necessary
79
 
80
  // Add filter to allow users to control which post-types the plugin is used with via their theme
81
  $post_types = array_unique( apply_filters( 'metronet_reorder_post_types', $post_types ) );
82
+ do_action( 'metronet_reorder_post_types_loaded', $post_types );
83
 
84
  foreach ( $post_types as $post_type ) {
85
  //Generate heading
88
  $heading = sprintf( __( 'Reorder %s', 'metronet-reorder-posts' ), $post_type_label );
89
 
90
  // Instantiate new reordering
91
+ $mn_reorder_args = array(
92
+ 'post_type' => $post_type,
93
+ 'order' => 'ASC',
94
+ 'heading' => $heading,
95
+ 'final' => '',
96
+ 'initial' => '',
97
+ 'menu_label' => __( 'Reorder', 'metronet-reorder-posts' ),
98
+ 'post_status' => 'publish',
99
+ );
100
+
101
+ $mn_reorder_instances[ $post_type ] = new MN_Reorder(
102
+ $mn_reorder_args
103
  );
104
  }
105
  } //end mt_reorder_posts_init
110
  load_plugin_textdomain( 'metronet-reorder-posts', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
111
  }
112
 
113
+ /* Global variable for storing class instances */
114
+ global $mn_reorder_instances;
115
+ $mn_reorder_instances = array();
116
+
languages/metronet-reorder-posts.pot CHANGED
@@ -5,7 +5,7 @@ msgid ""
5
  msgstr ""
6
  "Project-Id-Version: Metronet Reorder Posts v1.0.0\n"
7
  "Report-Msgid-Bugs-To: Ronald Huereca <ronalfy@gmail.com>\n"
8
- "POT-Creation-Date: 2014-12-23 17:00-0600\n"
9
  "PO-Revision-Date: \n"
10
  "Last-Translator: Ronald Huereca <ron@ronalfy.com>\n"
11
  "Language-Team: Ronald Huereca <ronalfy@gmail.com>\n"
@@ -96,27 +96,42 @@ msgstr ""
96
  msgid "Select the menu order for the post types."
97
  msgstr ""
98
 
99
- #: class-reorder.php:92 class-reorder.php:96 index.php:95
100
  msgid "Reorder"
101
  msgstr ""
102
 
103
- #: class-reorder.php:201 class-reorder.php:276
104
  msgid "Expand"
105
  msgstr ""
106
 
107
- #: class-reorder.php:202
108
  msgid "Collapse"
109
  msgstr ""
110
 
 
 
 
 
 
 
 
111
  #: class-reorder.php:383
 
 
 
 
 
 
 
 
112
  msgid "There is nothing to sort at this time"
113
  msgstr ""
114
 
115
- #: index.php:84
116
  msgid "Posts"
117
  msgstr ""
118
 
119
- #: index.php:85
120
  #, php-format
121
  msgid "Reorder %s"
122
  msgstr ""
5
  msgstr ""
6
  "Project-Id-Version: Metronet Reorder Posts v1.0.0\n"
7
  "Report-Msgid-Bugs-To: Ronald Huereca <ronalfy@gmail.com>\n"
8
+ "POT-Creation-Date: 2015-01-19 19:30-0600\n"
9
  "PO-Revision-Date: \n"
10
  "Last-Translator: Ronald Huereca <ron@ronalfy.com>\n"
11
  "Language-Team: Ronald Huereca <ronalfy@gmail.com>\n"
96
  msgid "Select the menu order for the post types."
97
  msgstr ""
98
 
99
+ #: class-reorder.php:161 class-reorder.php:165 index.php:97
100
  msgid "Reorder"
101
  msgstr ""
102
 
103
+ #: class-reorder.php:319 class-reorder.php:462
104
  msgid "Expand"
105
  msgstr ""
106
 
107
+ #: class-reorder.php:320
108
  msgid "Collapse"
109
  msgstr ""
110
 
111
+ #: class-reorder.php:376
112
+ #, php-format
113
+ msgid ""
114
+ "There are over %s posts found. We do not recommend you sort these posts for "
115
+ "performance reasons."
116
+ msgstr ""
117
+
118
  #: class-reorder.php:383
119
+ #, php-format
120
+ msgid ""
121
+ "Note: reordering here does not change the order on your website without "
122
+ "some code modifications. Please see our <a target=\"_blank\" href=\"%s"
123
+ "\">Wiki</a>."
124
+ msgstr ""
125
+
126
+ #: class-reorder.php:431
127
  msgid "There is nothing to sort at this time"
128
  msgstr ""
129
 
130
+ #: index.php:87
131
  msgid "Posts"
132
  msgstr ""
133
 
134
+ #: index.php:88
135
  #, php-format
136
  msgid "Reorder %s"
137
  msgstr ""
readme.txt CHANGED
@@ -5,17 +5,17 @@ Plugin URL: https://wordpress.org/plugins/metronet-reorder-posts/
5
  Requires at Least: 3.7
6
  Tested up to: 4.1
7
  Tags: reorder, re-order, posts, wordpress, post-type, ajax, admin, hierarchical, menu_order, ordering
8
- Stable tag: 2.0.2
9
- License: GPLv2 or later
10
- License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
12
- A simple and easy way to reorder your custom post-type posts in WordPress.
13
 
14
  == Description ==
15
 
16
- A simple and easy way to reorder your custom post-type posts in WordPress. Adds drag and drop functionality for post ordering in the WordPress admin panel. Works with custom post-types and regular posts.
17
 
18
- A settings panel is available for determining which post types to enable ordering for. Advanced options allow you to change the menu order for post types.
19
 
20
  <h3>Features</h3>
21
  <ul>
@@ -27,7 +27,7 @@ A settings panel is available for determining which post types to enable orderin
27
  <li>Advanced settings panel for overriding the menu order of custom post type queries</li>
28
  </ul>
29
 
30
- Advanced customization is allowed via hooks. See the <a href="https://github.com/ronalfy/reorder-posts#plugin-filters">Plugin Filters on GitHub</a>.
31
 
32
  <h3>Spread the Word</h3>
33
  If you like this plugin, please help spread the word. Rate the plugin. Write about the plugin. Something :)
@@ -59,7 +59,17 @@ Either install the plugin via the WordPress admin panel, or ...
59
 
60
  For each post type, you will see a new "Reorder" submenu. Simply navigate to "Reorder" to change the order of your post types. Changes are saved immediately, there is no need to click a save or update button.
61
 
62
- By default, ordering is enabled for all post types. A settings panel is available for determining which post types to enable ordering for. Advanced options allow you to change the menu order for post types.
 
 
 
 
 
 
 
 
 
 
63
 
64
  == Frequently Asked Questions ==
65
 
@@ -106,6 +116,14 @@ This plugin requires WordPress 3.7 or above. We urge you, however, to always us
106
 
107
  == Changelog ==
108
 
 
 
 
 
 
 
 
 
109
  = 2.0.2 =
110
  * Released 2014-12-26
111
  * Bug fix: Saving admin panel settings resulted in a variety of PHP offset error messages.
@@ -161,6 +179,9 @@ This plugin requires WordPress 3.7 or above. We urge you, however, to always us
161
 
162
  == Upgrade Notice ==
163
 
 
 
 
164
  = 2.0.2 =
165
  Bug fixes with PHP error notices. Highly recommend you upgrade.
166
 
5
  Requires at Least: 3.7
6
  Tested up to: 4.1
7
  Tags: reorder, re-order, posts, wordpress, post-type, ajax, admin, hierarchical, menu_order, ordering
8
+ Stable tag: 2.1.0
9
+ License: GPLv3 or later
10
+ License URI: http://www.gnu.org/licenses/gpl-3.0.html
11
 
12
+ A simple and easy way to reorder your custom post types in WordPress.
13
 
14
  == Description ==
15
 
16
+ A simple and easy way to reorder your custom post-type posts in WordPress. Adds drag and drop functionality for post ordering in the WordPress admin panel. Works with custom post-types and regular posts.
17
 
18
+ We consider Reorder Posts a <strong>developer tool</strong>. If you do not know what `menu_order` or custom queries are, then this plugin is likely not for you.
19
 
20
  <h3>Features</h3>
21
  <ul>
27
  <li>Advanced settings panel for overriding the menu order of custom post type queries</li>
28
  </ul>
29
 
30
+
31
 
32
  <h3>Spread the Word</h3>
33
  If you like this plugin, please help spread the word. Rate the plugin. Write about the plugin. Something :)
59
 
60
  For each post type, you will see a new "Reorder" submenu. Simply navigate to "Reorder" to change the order of your post types. Changes are saved immediately, there is no need to click a save or update button.
61
 
62
+ By default, ordering is enabled for all post types. A settings panel is available for determining which post types to enable ordering for.
63
+
64
+ Advanced customization is allowed via hooks. See the <a href="https://github.com/ronalfy/reorder-posts#plugin-filters">Plugin Filters on GitHub</a>.
65
+
66
+ This tool allows you to easily reorder post types in the back-end of WordPress. How the posts are sorted in the front-end is entirely up to you, as it should be.
67
+
68
+ We do have advanced settings under `Settings->Reorder Posts`, but these should only be used for testing purposes.
69
+
70
+ You'll want to make use of <a href="http://codex.wordpress.org/Class_Reference/WP_Query">WP_Query</a>, <a href="http://codex.wordpress.org/Template_Tags/get_posts">get_posts</a>, or <a href="http://codex.wordpress.org/Plugin_API/Action_Reference/pre_get_posts">pre_get_posts</a> to modify query behavior on the front-end of your site.
71
+
72
+ Examples of each are on the respective pages above. You are welcome to leave a support request if you need help with a query and we'll do our best to get back with you.
73
 
74
  == Frequently Asked Questions ==
75
 
116
 
117
  == Changelog ==
118
 
119
+ = 2.1.0 =
120
+ * Released 2015-01-19
121
+ * Added add-on support
122
+ * Make sure reordering can only be done by those with edit_pages privileges
123
+ * Added pagination for performance reasons
124
+ * Optimized queries for performance reasons
125
+ * Added warning message for those with a lot of posts
126
+
127
  = 2.0.2 =
128
  * Released 2014-12-26
129
  * Bug fix: Saving admin panel settings resulted in a variety of PHP offset error messages.
179
 
180
  == Upgrade Notice ==
181
 
182
+ = 2.1.0 =
183
+ Some capability fixes, pagination for post types with a lot of posts, improved query performance, and add-on capability.
184
+
185
  = 2.0.2 =
186
  Bug fixes with PHP error notices. Highly recommend you upgrade.
187
 
scripts/sort.js CHANGED
@@ -5,6 +5,9 @@ jQuery(document).ready(function($) {
5
  if ( reorder_posts.hierarchical == 'false' ) {
6
  max_levels = 1;
7
  }
 
 
 
8
  postList.nestedSortable( {
9
  forcePlaceholderSize: true,
10
  handle: 'div',
@@ -19,13 +22,102 @@ jQuery(document).ready(function($) {
19
  toleranceElement: '> div',
20
  listType: 'ul',
21
  update: function( event, ui ) {
22
- var order = $('ul#post-list').nestedSortable( 'toHierarchy',{ listType: 'ul'});
23
- order = JSON.stringify( order , null, 2);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  $('#loading-animation').show();
25
- $.post( ajaxurl, { action: 'post_sort', nonce: reorder_posts.sortnonce, data: order }, function( response ) {
26
- $('#loading-animation').hide()
27
- }, 'json' );
28
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  }
30
  });
31
  $( "#post-list a" ).toggle( function() {
5
  if ( reorder_posts.hierarchical == 'false' ) {
6
  max_levels = 1;
7
  }
8
+ var callback = false;
9
+ var sort_start = {};
10
+ var sort_end = {};
11
  postList.nestedSortable( {
12
  forcePlaceholderSize: true,
13
  handle: 'div',
22
  toleranceElement: '> div',
23
  listType: 'ul',
24
  update: function( event, ui ) {
25
+
26
+ var reorder_ajax_callback = function( response ) {
27
+ response = jQuery.parseJSON( response );
28
+ if ( true == response.more_posts ) {
29
+ $.post( ajaxurl, response, reorder_ajax_callback );
30
+ } else {
31
+ if ( false != callback ) {
32
+ var callback_ajax_args = callback;
33
+ callback = false;
34
+ $.post( ajaxurl, callback_ajax_args, reorder_ajax_callback );
35
+ } else {
36
+ $('#loading-animation').hide();
37
+ }
38
+ }
39
+ };
40
+
41
  $('#loading-animation').show();
 
 
 
42
 
43
+ //Get the end items where the post was placed
44
+ sort_end.item = ui.item;
45
+ sort_end.prev = ui.item.prev( ':not(".placeholder")' );
46
+ sort_end.next = ui.item.next( ':not(".placeholder")' );
47
+
48
+ //Get starting post parent
49
+ var start_post_parent = parseInt( sort_start.item.attr( 'data-parent' ) );
50
+
51
+ //Get ending post parent
52
+ var end_post_parent = 0;
53
+ if( sort_end.prev.length > 0 || sort_end.next.length > 0 ) {
54
+ if ( sort_end.prev.length > 0 ) {
55
+ end_post_parent = parseInt( sort_end.prev.attr( 'data-parent' ) );
56
+ } else if ( sort_end.next.length > 0 ) {
57
+ end_post_parent = parseInt( sort_end.next.attr( 'data-parent' ) );
58
+ }
59
+ } else if ( sort_end.prev.length == 0 && sort_end.next.length == 0 ) {
60
+ //We're the only child :(
61
+ end_post_parent = ui.item.parents( 'li:first' ).attr( 'data-id' );
62
+ }
63
+
64
+ //Update post parent in DOM
65
+ sort_end.item.attr( 'data-parent', end_post_parent );
66
+
67
+
68
+
69
+ //Find the menu order and update dom accordingly
70
+ var list_offset = 0;
71
+ if( end_post_parent == 0 ) {
72
+ var offset = $( '#reorder-offset' ).val();
73
+
74
+ //Get index in list order and update dom
75
+ list_offset = parseInt(offset) + parseInt(sort_end.item.index());
76
+ } else {
77
+ list_offset = parseInt(sort_end.item.index());
78
+ }
79
+ sort_end.item.attr( 'data-menu-order', list_offset );
80
+
81
+ //Get attributes
82
+ var attributes = {};
83
+ $.each( sort_end.item[0].attributes, function() {
84
+ attributes [ this.name ] = this.value;
85
+ } );
86
+
87
+ //Perform Ajax Call
88
+ var parent_ajax_args = {
89
+ action: reorder_posts.action,
90
+ post_parent: end_post_parent,
91
+ start: 0,
92
+ nonce: reorder_posts.sortnonce,
93
+ post_id: sort_end.item.attr( 'data-id' ),
94
+ menu_order: sort_end.item.attr( 'data-menu-order' ),
95
+ excluded: {},
96
+ post_type: sort_start.item.attr( 'data-post-type' ),
97
+ attributes: attributes
98
+ };
99
+ //Determine if we need to sort child nodes - if post_parent ids don't match and there are any remaining child nodes, we need to reorder those
100
+ if ( start_post_parent != end_post_parent ) {
101
+ //Determine if there are any remaining child nodes
102
+ callback = {
103
+ action: reorder_posts.action,
104
+ post_parent: start_post_parent,
105
+ start: 0,
106
+ nonce: reorder_posts.sortnonce,
107
+ post_id: 0,
108
+ menu_order: 0,
109
+ excluded: {},
110
+ post_type: sort_start.item.attr( 'data-post-type' ),
111
+ attributes: attributes
112
+ };
113
+ }
114
+
115
+ $.post( ajaxurl, parent_ajax_args, reorder_ajax_callback );
116
+ },
117
+ start: function( event, ui ) {
118
+ sort_start.item = ui.item;
119
+ sort_start.prev = ui.item.prev( ':not(".placeholder")' );
120
+ sort_start.next = ui.item.next( ':not(".placeholder")' );
121
  }
122
  });
123
  $( "#post-list a" ).toggle( function() {