PluginProbe ʕ •ᴥ•ʔ
Simple Page Ordering / 2.1.2
Simple Page Ordering v2.1.2
2.3.1 2.3.2 2.3.3 2.3.4 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.5.0 2.5.1 2.6.0 2.6.1 2.6.2 2.6.3 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.8.0 trunk 0.8.4 0.9 0.9.1 0.9.5 0.9.6 1.0 2.0 2.1 2.1.1 2.1.2 2.2 2.2.1 2.2.2 2.2.3 2.2.4 2.3
simple-page-ordering / simple-page-ordering.php
simple-page-ordering Last commit date
localization 13 years ago readme.txt 13 years ago screenshot-1.png 13 years ago screenshot-2.png 13 years ago simple-page-ordering.css 13 years ago simple-page-ordering.dev.js 13 years ago simple-page-ordering.js 13 years ago simple-page-ordering.php 13 years ago
simple-page-ordering.php
234 lines
1 <?php
2 /**
3 Plugin Name: Simple Page Ordering
4 Plugin URI: http://10up.com/plugins/simple-page-ordering-wordpress/
5 Description: Order your pages and hierarchical post types using drag and drop on the built in page list. For further instructions, open the "Help" tab on the Pages screen.
6 Version: 2.1.2
7 Author: Jake Goldman, 10up
8 Author URI: http://10up.com
9 License: GPLv2 or later
10 */
11
12 class Simple_Page_Ordering {
13
14 public function __construct() {
15 add_action( 'load-edit.php', array( $this, 'load_edit_screen' ) );
16 add_action( 'wp_ajax_simple_page_ordering', array( $this, 'ajax_simple_page_ordering' ) );
17 }
18
19 public function load_edit_screen() {
20 $screen = get_current_screen();
21 $post_type = $screen->post_type;
22
23 // is post type sortable?
24 $sortable = ( post_type_supports( $post_type, 'page-attributes' ) || is_post_type_hierarchical( $post_type ) ); // check permission
25 if ( ! $sortable = apply_filters( 'simple_page_ordering_is_sortable', $sortable, $post_type ) )
26 return;
27
28 // does user have the right to manage these post objects?
29 if ( ! $this->check_edit_others_caps( $post_type ) )
30 return;
31
32 add_filter( 'views_' . $screen->id, array( $this, 'sort_by_order_link' ) ); // add view by menu order to views
33 add_action( 'wp', array( $this, 'wp' ) );
34 add_action( 'admin_head', array( $this, 'admin_head' ) );
35 }
36
37 public function wp() {
38 if ( 0 === strpos( get_query_var('orderby'), 'menu_order' ) ) { // we can only sort if we're organized by menu order
39 $script_name = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? 'simple-page-ordering.dev.js' : 'simple-page-ordering.js';
40 wp_enqueue_script( 'simple-page-ordering', plugins_url( $script_name, __FILE__ ), array('jquery-ui-sortable'), '2.1', true );
41 wp_enqueue_style( 'simple-page-ordering', plugins_url( 'simple-page-ordering.css', __FILE__ ) );
42 }
43 }
44
45 public function admin_head() {
46 $screen = get_current_screen();
47 $screen->add_help_tab(array(
48 'id' => 'simple_page_ordering_help_tab',
49 'title' => 'Simple Page Ordering',
50 'content' => '<p>' . __( 'To reposition an item, simply drag and drop the row by "clicking and holding" it anywhere (outside of the links and form controls) and moving it to its new position.', 'simple-page-ordering' ) . '</p>',
51 ));
52 }
53
54 public function ajax_simple_page_ordering() {
55 // check and make sure we have what we need
56 if ( empty( $_POST['id'] ) || ( !isset( $_POST['previd'] ) && !isset( $_POST['nextid'] ) ) )
57 die(-1);
58
59 // real post?
60 if ( ! $post = get_post( $_POST['id'] ) )
61 die(-1);
62
63 // does user have the right to manage these post objects?
64 if ( ! $this->check_edit_others_caps( $post->post_type ) )
65 die(-1);
66
67 // badly written plug-in hooks for save post can break things
68 if ( !defined( 'WP_DEBUG' ) || !WP_DEBUG )
69 error_reporting( 0 );
70
71 $previd = empty( $_POST['previd'] ) ? false : (int) $_POST['previd'];
72 $nextid = empty( $_POST['nextid'] ) ? false : (int) $_POST['nextid'];
73 $start = empty( $_POST['start'] ) ? 1 : (int) $_POST['start'];
74 $excluded = empty( $_POST['excluded'] ) ? array( $post->ID ) : array_filter( (array) $_POST['excluded'], 'intval' );
75
76 $new_pos = array(); // store new positions for ajax
77 $return_data = new stdClass;
78
79 do_action( 'simple_page_ordering_pre_order_posts', $post, $start );
80
81 // attempt to get the intended parent... if either sibling has a matching parent ID, use that
82 $parent_id = $post->post_parent;
83 $next_post_parent = $nextid ? wp_get_post_parent_id( $nextid ) : false;
84 if ( $previd == $next_post_parent ) { // if the preceding post is the parent of the next post, move it inside
85 $parent_id = $next_post_parent;
86 } elseif ( $next_post_parent !== $parent_id ) { // otherwise, if the next post's parent isn't the same as our parent, we need to study
87 $prev_post_parent = $previd ? wp_get_post_parent_id( $previd ) : false;
88 if ( $prev_post_parent !== $parent_id ) { // if the previous post is not our parent now, make it so!
89 $parent_id = ( $prev_post_parent !== false ) ? $prev_post_parent : $next_post_parent;
90 }
91 }
92 // if the next post's parent isn't our parent, it might as well be false (irrelevant to our query)
93 if ( $next_post_parent !== $parent_id )
94 $nextid = false;
95
96 $max_sortable_posts = (int) apply_filters( 'simple_page_ordering_limit', 50 ); // should reliably be able to do about 50 at a time
97 if ( $max_sortable_posts < 5 ) // don't be ridiculous!
98 $max_sortable_posts = 50;
99
100 // we need to handle all post stati, except trash (in case of custom stati)
101 $post_stati = get_post_stati(array(
102 'show_in_admin_all_list' => true,
103 ));
104
105 $siblings = new WP_Query(array(
106 'depth' => 1,
107 'posts_per_page' => $max_sortable_posts,
108 'post_type' => $post->post_type,
109 'post_status' => $post_stati,
110 'post_parent' => $parent_id,
111 'orderby' => 'menu_order title',
112 'order' => 'ASC',
113 'post__not_in' => $excluded,
114 'update_post_term_cache' => false,
115 'update_post_meta_cache' => false,
116 'suppress_filters' => true,
117 'ignore_sticky_posts' => true,
118 )); // fetch all the siblings (relative ordering)
119
120 // don't waste overhead of revisions on a menu order change (especially since they can't *all* be rolled back at once)
121 remove_action( 'pre_post_update', 'wp_save_post_revision' );
122
123 foreach( $siblings->posts as $sibling ) :
124
125 // don't handle the actual post
126 if ( $sibling->ID === $post->ID )
127 continue;
128
129 // if this is the post that comes after our repositioned post, set our repositioned post position and increment menu order
130 if ( $nextid === $sibling->ID ) {
131 wp_update_post(array(
132 'ID' => $post->ID,
133 'menu_order' => $start,
134 'post_parent' => $parent_id,
135 ));
136 $ancestors = get_post_ancestors( $post->ID );
137 $new_pos[$post->ID] = array(
138 'menu_order' => $start,
139 'post_parent' => $parent_id,
140 'depth' => count( $ancestors ),
141 );
142 $start++;
143 }
144
145 // if repositioned post has been set, and new items are already in the right order, we can stop
146 if ( isset( $new_pos[$post->ID] ) && $sibling->menu_order >= $start ) {
147 $return_data->next = false;
148 break;
149 }
150
151 // set the menu order of the current sibling and increment the menu order
152 if ( $sibling->menu_order != $start ) {
153 wp_update_post(array(
154 'ID' => $sibling->ID,
155 'menu_order' => $start,
156 ));
157 }
158 $new_pos[$sibling->ID] = $start;
159 $start++;
160
161 if ( !$nextid && $previd == $sibling->ID ) {
162 wp_update_post(array(
163 'ID' => $post->ID,
164 'menu_order' => $start,
165 'post_parent' => $parent_id
166 ));
167 $ancestors = get_post_ancestors( $post->ID );
168 $new_pos[$post->ID] = array(
169 'menu_order' => $start,
170 'post_parent' => $parent_id,
171 'depth' => count($ancestors) );
172 $start++;
173 }
174
175 endforeach;
176
177 // max per request
178 if ( !isset( $return_data->next ) && $siblings->max_num_pages > 1 ) {
179 $return_data->next = array(
180 'id' => $post->ID,
181 'previd' => $previd,
182 'nextid' => $nextid,
183 'start' => $start,
184 'excluded' => array_merge( array_keys( $new_pos ), $excluded ),
185 );
186 } else {
187 $return_data->next = false;
188 }
189
190 do_action( 'simple_page_ordering_ordered_posts', $post, $new_pos );
191
192 if ( ! $return_data->next ) {
193 // if the moved post has children, we need to refresh the page (unless we're continuing)
194 $children = get_posts(array(
195 'numberposts' => 1,
196 'post_type' => $post->post_type,
197 'post_status' => $post_stati,
198 'post_parent' => $post->ID,
199 'fields' => 'ids',
200 'update_post_term_cache' => false,
201 'update_post_meta_cache' => false,
202 ));
203
204 if ( ! empty( $children ) )
205 die( 'children' );
206 }
207
208 $return_data->new_pos = $new_pos;
209
210 die( json_encode( $return_data ) );
211 }
212
213 public function sort_by_order_link( $views ) {
214 $class = ( get_query_var('orderby') == 'menu_order title' ) ? 'current' : '';
215 $query_string = remove_query_arg(array( 'orderby', 'order' ));
216 $query_string = add_query_arg( 'orderby', urlencode('menu_order title'), $query_string );
217 $views['byorder'] = '<a href="'. $query_string . '" class="' . $class . '">Sort by Order</a>';
218 return $views;
219 }
220
221 /**
222 * Checks to see if the current user has the capability to "edit others" for a post type
223 *
224 * @param (string) $post_type Post type name
225 * @return (bool) True or false
226 */
227 public function check_edit_others_caps( $post_type ) {
228 $post_type_object = get_post_type_object( $post_type );
229 $edit_others_cap = empty( $post_type_object ) ? 'edit_others_' . $post_type . 's' : $post_type_object->cap->edit_others_posts;
230 return apply_filters( 'simple_page_ordering_edit_rights', current_user_can( $edit_others_cap ), $post_type );
231 }
232 }
233
234 $simple_page_ordering = new Simple_Page_Ordering;