PluginProbe ʕ •ᴥ•ʔ
Admin and Site Enhancements (ASE) / 8.6.2
Admin and Site Enhancements (ASE) v8.6.2
9.1.0 9.0.2 9.0.1 9.0.0 8.9.2 8.9.1 8.9.0 8.8.8 8.8.7 8.8.6 8.8.5 8.8.4 8.8.3 8.8.2 8.8.1 8.8.0 8.7.3 8.7.2 8.7.1 8.2.1 8.2.2 8.2.3 8.3.0 8.3.1 8.3.2 8.4.0 8.4.1 8.4.2 8.5.0 8.5.1 8.5.2 8.6.0 8.6.1 8.6.2 8.7.0 5.0.1 5.0.2 5.0.2.1 5.0.2.2 5.0.2.3 5.0.2.4 5.1.0 5.2.0 5.2.1 5.2.10 5.2.11 5.2.2 5.2.3 5.2.4 5.2.5 5.2.6 5.2.7 5.2.8 5.2.9 5.3.0 5.3.1 5.3.2 5.4.0 5.4.1 5.5.0 5.5.1 5.5.2 5.6.0 5.6.1 5.6.2 5.7.0 5.7.1 5.8.0 5.8.1 6.0.0 6.0.3 6.0.4 6.0.5 6.0.5.1 6.0.6 6.0.7 6.0.8.1 6.1.0 6.1.3 6.2.0 6.2.1 6.2.2 6.2.3 6.2.4 6.2.5 6.2.6 6.2.7 6.3.0 6.3.1 6.3.2 6.4.0 6.5.0 6.5.1 6.6.0 6.7.0 6.8.0 6.8.2 6.8.3 6.9.0 6.9.1 6.9.10 6.9.11 6.9.12 6.9.13.1 6.9.13.2 6.9.2 6.9.3 6.9.4 6.9.5 6.9.6 6.9.7 6.9.8 6.9.9 7.0.0 7.0.2 7.0.2.1 7.0.2.2 7.0.2.3 7.0.3 7.1.0 7.1.1 7.1.2 7.1.3 7.1.4 7.1.5 7.2.0 7.2.1 7.3.0 7.3.1 7.3.2 7.3.3 7.4.0 7.4.2 7.4.4 7.4.5 7.4.6 7.4.7 7.4.8 7.5.0 7.5.1 7.5.2 7.5.3 7.5.4 7.6.0 7.6.1 7.6.1.1 7.6.10 7.6.11 7.6.2 7.6.3 7.6.4 7.6.5 7.6.6 7.6.7 7.6.7.1 7.6.8 7.6.9 7.7.0 7.8.0 7.8.1 7.8.10 7.8.11 7.8.12 7.8.13 7.8.14 7.8.15 7.8.16 7.8.17 7.8.18 7.8.2 7.8.3 7.8.4 7.8.5 7.8.5.1 7.8.6 7.8.7 7.8.8 7.8.9 7.9.0 7.9.1 7.9.10 7.9.11 7.9.2 7.9.3 7.9.4 7.9.5 7.9.6 7.9.7 7.9.8 7.9.9 8.0.0 8.0.1 8.0.2 8.0.3 8.0.4 8.0.5 8.0.6 8.0.7 8.0.8 8.1.0 8.1.1 8.1.2 8.1.3 8.1.4 8.2.0 trunk 1.0.0 1.1.0 1.2.0 1.3.0 1.4.0 1.5.0 1.6.0 1.7.0 1.8.0 1.9.0 2.0.0 2.1.0 2.2.0 2.3.0 2.4.0 2.5.0 2.6.0 2.7.0 2.8.0 2.8.1 2.8.2 2.8.3 2.9.0 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.1.0 3.2.0 3.3.0 3.4.0 3.5.0 3.6.1 3.7.0 3.8.0 3.9.0 3.9.1 3.9.2 4.0.0 4.0.1 4.1.0 4.2.0 4.2.1 4.2.2 4.3.0 4.3.1 4.4.0 4.5.0 4.6.0 4.7.0 4.7.1 4.7.2 4.7.3 4.7.4 4.8.0 4.8.1 4.8.2 4.8.3 4.9.0 4.9.1 4.9.2 4.9.3 5.0.0
admin-site-enhancements / classes / class-content-order.php
admin-site-enhancements / classes Last commit date
class-activation.php 4 months ago class-admin-menu-organizer.php 4 months ago class-admin-menu-svg-icon-mask.php 4 months ago class-auto-publish-posts-with-missed-schedule.php 4 months ago class-avif-upload.php 4 months ago class-captcha-protection.php 4 months ago class-change-login-url.php 4 months ago class-cleanup-admin-bar.php 4 months ago class-common-methods.php 4 months ago class-content-duplication.php 4 months ago class-content-order.php 4 months ago class-custom-admin-footer-text.php 4 months ago class-custom-body-class.php 4 months ago class-custom-css.php 4 months ago class-custom-nav-menu-items-in-new-tab.php 4 months ago class-deactivation.php 4 months ago class-disable-author-archives.php 4 months ago class-disable-comments.php 4 months ago class-disable-dashboard-widgets.php 4 months ago class-disable-embeds.php 4 months ago class-disable-feeds.php 4 months ago class-disable-gutenberg.php 4 months ago class-disable-rest-api.php 4 months ago class-disable-smaller-components.php 4 months ago class-disable-updates.php 4 months ago class-disable-xml-rpc.php 4 months ago class-display-system-summary.php 4 months ago class-email-address-obfuscator.php 4 months ago class-email-delivery.php 4 months ago class-enhance-list-tables.php 4 months ago class-external-permalinks.php 4 months ago class-heartbeat-control.php 4 months ago class-hide-admin-bar.php 4 months ago class-hide-admin-notices.php 4 months ago class-image-sizes-panel.php 4 months ago class-image-upload-control.php 4 months ago class-insert-head-body-footer-code.php 4 months ago class-last-login-column.php 4 months ago class-limit-login-attempts.php 4 months ago class-login-id-type.php 4 months ago class-login-logout-menu.php 4 months ago class-maintenance-mode.php 4 months ago class-manage-ads-appads-txt.php 4 months ago class-manage-robots-txt.php 4 months ago class-media-files-visibility-control.php 4 months ago class-media-replacement.php 4 months ago class-multiple-user-roles.php 4 months ago class-obfuscate-author-slugs.php 4 months ago class-open-external-links-in-new-tab.php 4 months ago class-password-protection.php 4 months ago class-redirect-after-login.php 4 months ago class-redirect-after-logout.php 4 months ago class-redirect-fourofour.php 4 months ago class-registration-date-column.php 4 months ago class-revisions-control.php 4 months ago class-search-engines-visibility.php 4 months ago class-settings-fields-render.php 4 months ago class-settings-sanitization.php 4 months ago class-settings-sections-fields.php 4 months ago class-show-custom-taxonomy-filters.php 4 months ago class-site-identity-on-login-page.php 4 months ago class-svg-upload.php 4 months ago class-various-admin-ui-enhancements.php 4 months ago class-view-admin-as-role.php 4 months ago class-wider-admin-menu.php 4 months ago class-wp-config-transformer.php 4 months ago
class-content-order.php
593 lines
1 <?php
2
3 namespace ASENHA\Classes;
4
5 use WP_Query;
6 /**
7 * Class for Content Order module
8 *
9 * @since 6.9.5
10 */
11 class Content_Order {
12 /**
13 * Whether to render featured image thumbnails on the "Order" admin page.
14 *
15 * Pro-only feature. Default is false to avoid rendering thumbnails for large lists.
16 *
17 * @var bool
18 */
19 private $show_featured_thumbnails = false;
20
21 /**
22 * Add "Custom Order" sub-menu for post types
23 *
24 * @since 5.0.0
25 */
26 public function add_content_order_submenu( $context ) {
27 $options = get_option( ASENHA_SLUG_U, array() );
28 $content_order_for = ( isset( $options['content_order_for'] ) ? $options['content_order_for'] : array() );
29 $content_order_enabled_post_types = array();
30 if ( is_array( $content_order_for ) && count( $content_order_for ) > 0 ) {
31 foreach ( $content_order_for as $post_type_slug => $is_custom_order_enabled ) {
32 if ( $is_custom_order_enabled ) {
33 $post_type_object = get_post_type_object( $post_type_slug );
34 if ( is_object( $post_type_object ) && property_exists( $post_type_object, 'labels' ) ) {
35 $post_type_name_plural = $post_type_object->labels->name;
36 if ( 'post' == $post_type_slug ) {
37 $hook_suffix = add_posts_page(
38 $post_type_name_plural . ' Order',
39 // Page title
40 __( 'Order', 'admin-site-enhancements' ),
41 // Menu title
42 'edit_others_posts',
43 // Capability required
44 'custom-order-posts',
45 // Menu and page slug
46 [$this, 'custom_order_page_output']
47 );
48 } else {
49 if ( 'sfwd-courses' == $post_type_slug ) {
50 // LearnDash LMS Courses
51 // Add 'Order' submenu item under LearnDash menu
52 // Linked URL will be /wp-admin/admin.php?page=custom-order-sfwd-courses
53 // We will add a redirect to the correct URL via $this->maybe_perform_menu_link_redirects() hooked in admin_init
54 $hook_suffix = add_submenu_page(
55 'learndash-lms',
56 // Parent (menu) slug. Ref: https://developer.wordpress.org/reference/functions/add_submenu_page/#comment-1404
57 $post_type_name_plural . ' ' . __( 'Order', 'admin-site-enhancements' ),
58 // Page title
59 $post_type_name_plural . ' ' . __( 'Order', 'admin-site-enhancements' ),
60 // Menu title
61 'edit_others_posts',
62 // Capability required
63 'custom-order-' . $post_type_slug,
64 // Menu and page slug
65 [$this, 'custom_order_page_output'],
66 // Callback function that outputs page content
67 9999
68 );
69 // Add the actual, functional 'Order' submenu page at /edit.php?post_type=sfwd-courses&page=custom-order-sfwd-courses
70 // We will redirect to this URL from /wp-admin/admin.php?page=custom-order-sfwd-courses created above using $this->maybe_perform_menu_link_redirects() hooked in admin_init
71 $hook_suffix = add_submenu_page(
72 'edit.php?post_type=' . $post_type_slug,
73 // Parent (menu) slug. Ref: https://developer.wordpress.org/reference/functions/add_submenu_page/#comment-1404
74 // 'learndash-lms', // Parent (menu) slug. Ref: https://developer.wordpress.org/reference/functions/add_submenu_page/#comment-1404
75 $post_type_name_plural . ' ' . __( 'Order', 'admin-site-enhancements' ),
76 // Page title
77 $post_type_name_plural . ' ' . __( 'Order', 'admin-site-enhancements' ),
78 // Menu title
79 'edit_others_posts',
80 // Capability required
81 'custom-order-' . $post_type_slug,
82 // Menu and page slug
83 [$this, 'custom_order_page_output'],
84 // Callback function that outputs page content
85 9999
86 );
87 } else {
88 $hook_suffix = add_submenu_page(
89 'edit.php?post_type=' . $post_type_slug,
90 // Parent (menu) slug. Ref: https://developer.wordpress.org/reference/functions/add_submenu_page/#comment-1404
91 $post_type_name_plural . ' Order',
92 // Page title
93 __( 'Order', 'admin-site-enhancements' ),
94 // Menu title
95 'edit_others_posts',
96 // Capability required
97 'custom-order-' . $post_type_slug,
98 // Menu and page slug
99 [$this, 'custom_order_page_output'],
100 // Callback function that outputs page content
101 9999
102 );
103 }
104 }
105 add_action( 'admin_print_styles-' . $hook_suffix, [$this, 'enqueue_content_order_styles'] );
106 add_action( 'admin_print_scripts-' . $hook_suffix, [$this, 'enqueue_content_order_scripts'] );
107 }
108 }
109 }
110 }
111 }
112
113 /**
114 * Add additinal HTML elements on list tables
115 *
116 * @since 7.6.10
117 */
118 public function add_additional_elements() {
119 global $pagenow, $typenow;
120 $common_methods = new Common_Methods();
121 $options = get_option( ASENHA_SLUG_U, array() );
122 $content_order_for = ( isset( $options['content_order_for'] ) ? $options['content_order_for'] : array() );
123 $content_order_enabled_post_types = $common_methods->get_array_of_keys_with_true_value( $content_order_for );
124 $content_order_other_enabled_post_types = array();
125 // List tables of pages, posts and CPTs. Administrators and Editors only.
126 if ( 'edit.php' == $pagenow && current_user_can( 'edit_others_posts' ) && (in_array( $typenow, $content_order_enabled_post_types ) || in_array( $typenow, $content_order_other_enabled_post_types )) ) {
127 // Add "Order" button
128 if ( 'post' == $typenow ) {
129 $typenow = 'posts';
130 }
131 ?>
132 <div id="content-order-button">
133 <a class="button" href="<?php
134 echo esc_url( get_admin_url() );
135 ?>edit.php?post_type=<?php
136 echo esc_attr( $typenow );
137 ?>&page=custom-order-<?php
138 echo esc_attr( $typenow );
139 ?>"><?php
140 _e( 'Order', 'admin-site-enhancements' );
141 ?></a>
142 </div>
143 <?php
144 }
145 }
146
147 /**
148 * Add scripts for content list tables
149 *
150 * @since 7.6.10
151 */
152 public function add_list_tables_scripts( $hook_suffix ) {
153 global $pagenow, $typenow;
154 $common_methods = new Common_Methods();
155 $options = get_option( ASENHA_SLUG_U, array() );
156 $content_order_for = ( isset( $options['content_order_for'] ) ? $options['content_order_for'] : array() );
157 $content_order_enabled_post_types = $common_methods->get_array_of_keys_with_true_value( $content_order_for );
158 $content_order_other_enabled_post_types = array();
159 // List tables of pages, posts and CPTs
160 if ( 'edit.php' == $hook_suffix && current_user_can( 'edit_others_posts' ) && (in_array( $typenow, $content_order_enabled_post_types ) || in_array( $typenow, $content_order_other_enabled_post_types )) ) {
161 wp_enqueue_style(
162 'asenha-list-tables-content-order',
163 ASENHA_URL . 'assets/css/list-tables-content-order.css',
164 array(),
165 ASENHA_VERSION
166 );
167 wp_enqueue_script(
168 'asenha-list-tables-content-order',
169 ASENHA_URL . 'assets/js/list-tables-content-order.js',
170 array('jquery'),
171 ASENHA_VERSION,
172 false
173 );
174 }
175 }
176
177 /**
178 * Maybe perform redirects from the 'Order' submenu link
179 *
180 * @since 7.6.9
181 */
182 public function maybe_perform_menu_link_redirects() {
183 $request_uri = sanitize_text_field( $_SERVER['REQUEST_URI'] );
184 // e.g. /wp-admin/index.php?page=page-slug
185 // Redirect for LearnDash LMS Courses post type ('sfwd-courses')
186 if ( in_array( 'sfwd-lms/sfwd_lms.php', get_option( 'active_plugins', array() ) ) ) {
187 if ( false !== strpos( $request_uri, 'admin.php?page=custom-order-sfwd-courses' ) ) {
188 wp_safe_redirect( get_admin_url() . 'edit.php?post_type=sfwd-courses&page=custom-order-sfwd-courses' );
189 exit;
190 }
191 }
192 }
193
194 /**
195 * Output content for the custom order page for each enabled post types
196 * Not using settings API because all done via AJAX
197 *
198 * @since 5.0.0
199 */
200 public function custom_order_page_output() {
201 $post_status = array(
202 'publish',
203 'future',
204 'draft',
205 'pending',
206 'private'
207 );
208 $parent_slug = get_admin_page_parent();
209 if ( 'edit.php' == $parent_slug ) {
210 $post_type_slug = 'post';
211 } elseif ( 'upload.php' == $parent_slug ) {
212 $post_type_slug = 'attachment';
213 $post_status = array('inherit', 'private');
214 } else {
215 $post_type_slug = str_replace( 'edit.php?post_type=', '', $parent_slug );
216 }
217 // Pro-only: featured image thumbnails are rendered only when explicitly enabled via query arg.
218 $this->show_featured_thumbnails = false;
219 // Object with properties for each post status and the count of posts for each status
220 // $post_count_object = wp_count_posts( $post_type_slug );
221 // Number of items with the status 'publish(ed)', 'future' (scheduled), 'draft', 'pending' and 'private'
222 // $post_count = absint( $post_count_object->publish )
223 // + absint( $post_count_object->future )
224 // + absint( $post_count_object->draft )
225 // + absint( $post_count_object->pending )
226 // + absint( $post_count_object->private );
227 ?>
228 <div class="wrap">
229 <div class="page-header">
230 <h2>
231 <?php
232 echo esc_html( get_admin_page_title() );
233 ?>
234 </h2>
235 <?php
236 ?>
237 </div>
238 <?php
239 // Get posts
240 $args = array(
241 'post_type' => $post_type_slug,
242 'numberposts' => -1,
243 'orderby' => 'menu_order title',
244 'order' => 'ASC',
245 'post_status' => $post_status,
246 );
247 // Add the following to non-attachment post types
248 if ( 'attachment' != $post_type_slug && is_post_type_hierarchical( $post_type_slug ) ) {
249 // In hierarchical post types, only return non-child posts as we currently only sort parent posts
250 $args['post_parent'] = 0;
251 }
252 $posts = get_posts( $args );
253 if ( !empty( $posts ) ) {
254 ?>
255 <ul id="item-list" class="asenha-content-order">
256 <?php
257 foreach ( $posts as $post ) {
258 $this->custom_order_single_item_output( $post );
259 }
260 ?>
261 </ul>
262 <div id="updating-order-notice" class="updating-order-notice" style="display: none;"><img src="<?php
263 echo esc_attr( ASENHA_URL ) . 'assets/img/oval.svg';
264 ?>" id="spinner-img" class="spinner-img" /><span class="dashicons dashicons-saved" style="display:none;"></span>Updating order...</div>
265 <?php
266 } else {
267 ?>
268 <h3>There is nothing to sort for this post type.</h3>
269 <?php
270 }
271 ?>
272 </div> <!-- End of div.wrap -->
273 <?php
274 }
275
276 /**
277 * Output single item sortable for custom content order
278 *
279 * @since 5.0.0
280 */
281 private function custom_order_single_item_output( $post ) {
282 if ( is_post_type_hierarchical( $post->post_type ) ) {
283 $post_type_object = get_post_type_object( $post->post_type );
284 $children = get_pages( array(
285 'child_of' => $post->ID,
286 'post_type' => $post->post_type,
287 ) );
288 if ( count( $children ) > 0 ) {
289 $has_child_label = '<span class="has-child-label"> <span class="dashicons dashicons-arrow-right"></span> Has child ' . strtolower( $post_type_object->label ) . '</span>';
290 $has_child = 'true';
291 } else {
292 $has_child_label = '';
293 $has_child = 'false';
294 }
295 } else {
296 $has_child_label = '';
297 $has_child = 'false';
298 }
299 $post_status_label_class = ( $post->post_status == 'publish' ? ' item-status-hidden' : '' );
300 $post_status_object = get_post_status_object( $post->post_status );
301 if ( 'attachment' == $post->post_type ) {
302 $post_status_label_separator = '';
303 $post_status_label = '';
304 // Attachments / media only has the post status 'inherit'. Let's not show it.
305 } else {
306 $post_status_label_separator = '';
307 $post_status_label = $post_status_object->label;
308 }
309 $short_excerpt = '';
310 $taxonomies_and_terms = '';
311 // If WPML plugin is active, let's get the current language
312 if ( in_array( 'sitepress-multilingual-cms/sitepress.php', get_option( 'active_plugins', array() ) ) ) {
313 $current_language = apply_filters( 'wpml_current_language', null );
314 $current_post_language_info = apply_filters( 'wpml_post_language_details', null, $post->ID );
315 if ( !is_wp_error( $current_post_language_info ) ) {
316 $current_post_language = $current_post_language_info['language_code'];
317 } else {
318 // wpml has not set language information for the post
319 // e.g. post is not translated yet, so, let's use the current site/admin language
320 $current_post_language = $current_language;
321 }
322 $same_language = $current_language === $current_post_language;
323 // true if language is the same, false otherwise
324 } else {
325 // WPML is not active, $same_language is always true, e.g. all posts are in English
326 $same_language = true;
327 }
328 // Only render sortable for posts that have the same language as the current chosen language
329 if ( $same_language ) {
330 ?>
331 <li id="list_<?php
332 echo esc_attr( $post->ID );
333 ?>" class="list-item" data-id="<?php
334 echo esc_attr( $post->ID );
335 ?>" data-menu-order="<?php
336 echo esc_attr( $post->menu_order );
337 ?>" data-parent="<?php
338 echo esc_attr( $post->post_parent );
339 ?>" data-has-child="<?php
340 echo esc_attr( $has_child );
341 ?>" data-post-type="<?php
342 echo esc_attr( $post->post_type );
343 ?>">
344 <div class="row">
345 <div class="row-content">
346 <?php
347 echo '<div class="content-main">
348 <span class="dashicons dashicons-menu"></span><a href="' . esc_attr( get_edit_post_link( $post->ID ) ) . '" class="item-title">' . esc_html( $post->post_title ) . '</a><span class="item-status' . esc_attr( $post_status_label_class ) . '">' . esc_html( $post_status_label_separator ) . esc_html( $post_status_label ) . '</span>' . wp_kses_post( $has_child_label ) . '<div class="fader"></div>
349 </div>';
350 if ( !in_array( $post->post_type, array('asenha_code_snippet') ) ) {
351 echo '<div class="content-additional">
352 <a href="' . esc_attr( get_the_permalink( $post->ID ) ) . '" target="_blank" class="button item-view-link">View</a>
353 </div>';
354 }
355 ?>
356 </div>
357 </div>
358 <?php
359 }
360 // if ( $same_language )
361 ?>
362 </li>
363 <?php
364 }
365
366 /**
367 * Enqueue styles for content order pages
368 *
369 * @since 5.0.0
370 */
371 public function enqueue_content_order_styles() {
372 wp_enqueue_style(
373 'content-order-style',
374 ASENHA_URL . 'assets/css/content-order.css',
375 array(),
376 ASENHA_VERSION
377 );
378 }
379
380 /**
381 * Enqueue scripts for content order pages
382 *
383 * @since 5.0.0
384 */
385 public function enqueue_content_order_scripts() {
386 global $typenow;
387 wp_enqueue_script(
388 'content-order-jquery-ui-touch-punch',
389 ASENHA_URL . 'assets/js/jquery.ui.touch-punch.min.js',
390 array('jquery-ui-sortable'),
391 '0.2.3',
392 true
393 );
394 wp_register_script(
395 'content-order-nested-sortable',
396 ASENHA_URL . 'assets/js/jquery.mjs.nestedSortable.js',
397 array('content-order-jquery-ui-touch-punch'),
398 '2.0.0',
399 true
400 );
401 wp_enqueue_script(
402 'content-order-sort',
403 ASENHA_URL . 'assets/js/content-order-sort.js',
404 array('content-order-nested-sortable'),
405 ASENHA_VERSION,
406 true
407 );
408 wp_localize_script( 'content-order-sort', 'contentOrderSort', array(
409 'action' => 'save_custom_order',
410 'nonce' => wp_create_nonce( 'order_sorting_nonce' ),
411 'hierarchical' => ( is_post_type_hierarchical( $typenow ) ? 'true' : 'false' ),
412 'hirarchical' => ( is_post_type_hierarchical( $typenow ) ? 'true' : 'false' ),
413 ) );
414 }
415
416 /**
417 * Save custom content order coming from ajax call
418 *
419 * @since 5.0.0
420 */
421 public function save_custom_content_order() {
422 global $wpdb;
423 // Check user capabilities
424 if ( !current_user_can( 'edit_others_posts' ) ) {
425 wp_send_json( 'Something went wrong.' );
426 }
427 // Verify nonce
428 if ( !wp_verify_nonce( $_POST['nonce'], 'order_sorting_nonce' ) ) {
429 wp_send_json( 'Something went wrong.' );
430 }
431 // Get ajax variables
432 $action = ( isset( $_POST['action'] ) ? $_POST['action'] : '' );
433 // Item parent is currently 0, as we only handle sorting of non-child posts
434 $item_parent = ( isset( $_POST['item_parent'] ) ? absint( $_POST['item_parent'] ) : 0 );
435 $menu_order_start = ( isset( $_POST['start'] ) ? absint( $_POST['start'] ) : 0 );
436 $post_id = ( isset( $_POST['post_id'] ) ? absint( $_POST['post_id'] ) : 0 );
437 $item_menu_order = ( isset( $_POST['menu_order'] ) ? absint( $_POST['menu_order'] ) : 0 );
438 $items_to_exclude = ( isset( $_POST['excluded_items'] ) && is_array( $_POST['excluded_items'] ) ? array_map( 'absint', $_POST['excluded_items'] ) : array() );
439 $post_type = ( isset( $_POST['post_type'] ) ? sanitize_key( wp_unslash( $_POST['post_type'] ) ) : false );
440 $is_hierarchical_post_type = ( $post_type ? is_post_type_hierarchical( $post_type ) : false );
441 $allow_parent_updates = 'attachment' === $post_type || $is_hierarchical_post_type;
442 if ( !$allow_parent_updates ) {
443 $item_parent = 0;
444 }
445 // Make processing faster by removing certain actions
446 remove_action( 'pre_post_update', 'wp_save_post_revision' );
447 // $response array for ajax response
448 $response = array();
449 // Update the item whose order/position was moved
450 if ( $post_id > 0 && !isset( $_POST['more_posts'] ) ) {
451 $wpdb->update(
452 $wpdb->posts,
453 // The table
454 array(
455 'menu_order' => $item_menu_order,
456 ),
457 array(
458 'ID' => $post_id,
459 )
460 );
461 clean_post_cache( $post_id );
462 $items_to_exclude[] = $post_id;
463 }
464 if ( 'attachment' == $post_type ) {
465 $post_status = array('inherit', 'private');
466 } else {
467 $post_status = array(
468 'publish',
469 'future',
470 'draft',
471 'pending',
472 'private'
473 );
474 }
475 // Get all posts from the post type related to ajax request
476 $query_args = array(
477 'post_type' => $post_type,
478 'orderby' => 'menu_order title',
479 'order' => 'ASC',
480 'posts_per_page' => -1,
481 'suppress_filters' => true,
482 'ignore_sticky_posts' => true,
483 'post_status' => $post_status,
484 'post__not_in' => $items_to_exclude,
485 'update_post_term_cache' => false,
486 'update_post_meta_cache' => false,
487 );
488 if ( 'attachment' === $post_type ) {
489 // do nothing, we do not add post_parent parameter as media items can be attached to other posts, making them the parent.
490 } else {
491 // For hierarchical post types only, update one branch at a time.
492 // Non-hierarchical post types are reindexed as a full set to avoid duplicate menu_order values.
493 if ( $is_hierarchical_post_type ) {
494 $query_args['post_parent'] = $item_parent;
495 }
496 }
497 $posts = new WP_Query($query_args);
498 if ( $posts->have_posts() ) {
499 // Iterate through posts and update menu order and post parent
500 foreach ( $posts->posts as $post ) {
501 // If the $post is the one being displaced (shited downward) by the moved item, increment it's menu_order by one
502 if ( $menu_order_start == $item_menu_order && $post_id > 0 ) {
503 $menu_order_start++;
504 }
505 // Only process posts other than the moved item, which has been processed earlier outside this loop
506 if ( $post_id != $post->ID ) {
507 // Update menu_order
508 $wpdb->update( $wpdb->posts, array(
509 'menu_order' => $menu_order_start,
510 ), array(
511 'ID' => $post->ID,
512 ) );
513 clean_post_cache( $post->ID );
514 }
515 $items_to_exclude[] = $post->ID;
516 $menu_order_start++;
517 }
518 die( json_encode( $response ) );
519 } else {
520 die( json_encode( $response ) );
521 }
522 }
523
524 /**
525 * Set default ordering of list tables of sortable post types by 'menu_order'
526 *
527 * @link https://developer.wordpress.org/reference/classes/wp_query/#methods
528 * @since 5.0.0
529 */
530 public function orderby_menu_order( $query ) {
531 global $pagenow, $typenow;
532 $query_post_type = $query->get( 'post_type' );
533 $options = get_option( ASENHA_SLUG_U, array() );
534 // Hierarchical post types that should be custom ordered
535 $content_order_for = ( isset( $options['content_order_for'] ) ? $options['content_order_for'] : array() );
536 $content_order_enabled_post_types = array();
537 if ( is_array( $content_order_for ) && count( $content_order_for ) > 0 ) {
538 foreach ( $content_order_for as $post_type_slug => $is_custom_order_enabled ) {
539 if ( $is_custom_order_enabled ) {
540 $content_order_enabled_post_types[] = $post_type_slug;
541 }
542 }
543 }
544 $should_be_custom_sorted = false;
545 // All post types that should be custom ordered
546 $content_order_post_types = $content_order_enabled_post_types;
547 // Use custom order in wp-admin listing pages/tables for enabled post types
548 if ( is_admin() && ('edit.php' == $pagenow || 'upload.php' == $pagenow) && !isset( $_GET['orderby'] ) ) {
549 if ( in_array( $typenow, $content_order_post_types ) ) {
550 $query->set( 'orderby', 'menu_order title' );
551 $query->set( 'order', 'ASC' );
552 }
553 }
554 }
555
556 /**
557 * Make sure newly created posts are assigned the highest menu_order so it's added at the bottom of the existing order
558 *
559 * @since 6.2.1
560 */
561 public function set_menu_order_for_new_posts( $post_id, $post, $update ) {
562 $options = get_option( ASENHA_SLUG_U, array() );
563 $content_order_for = ( isset( $options['content_order_for'] ) ? $options['content_order_for'] : array() );
564 $content_order_enabled_post_types = array();
565 if ( is_array( $content_order_for ) && count( $content_order_for ) > 0 ) {
566 foreach ( $content_order_for as $post_type_slug => $is_custom_order_enabled ) {
567 if ( $is_custom_order_enabled ) {
568 $content_order_enabled_post_types[] = $post_type_slug;
569 }
570 }
571 }
572 // Only assign menu_order if there are none assigned when creating the post, i.e. menu_order is 0
573 if ( in_array( $post->post_type, $content_order_enabled_post_types ) && ('auto-draft' == $post->post_status || 'publish' == $post->post_status) && $post->menu_order == '0' && false === $update ) {
574 $post_with_highest_menu_order = get_posts( array(
575 'post_type' => $post->post_type,
576 'posts_per_page' => 1,
577 'orderby' => 'menu_order',
578 'order' => 'DESC',
579 ) );
580 if ( $post_with_highest_menu_order ) {
581 $new_menu_order = (int) $post_with_highest_menu_order[0]->menu_order + 1;
582 // Assign the one higher menu_order to the new post
583 $args = array(
584 'ID' => $post_id,
585 'menu_order' => $new_menu_order,
586 );
587 wp_update_post( $args );
588 }
589 }
590 }
591
592 }
593