PluginProbe ʕ •ᴥ•ʔ
Admin and Site Enhancements (ASE) / 8.2.3
Admin and Site Enhancements (ASE) v8.2.3
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 7 months ago class-admin-menu-organizer.php 7 months ago class-admin-menu-svg-icon-mask.php 7 months ago class-auto-publish-posts-with-missed-schedule.php 7 months ago class-avif-upload.php 7 months ago class-captcha-protection.php 7 months ago class-change-login-url.php 7 months ago class-cleanup-admin-bar.php 7 months ago class-common-methods.php 7 months ago class-content-duplication.php 7 months ago class-content-order.php 7 months ago class-custom-admin-footer-text.php 7 months ago class-custom-body-class.php 7 months ago class-custom-css.php 7 months ago class-custom-nav-menu-items-in-new-tab.php 7 months ago class-deactivation.php 7 months ago class-disable-author-archives.php 7 months ago class-disable-comments.php 7 months ago class-disable-dashboard-widgets.php 7 months ago class-disable-embeds.php 7 months ago class-disable-feeds.php 7 months ago class-disable-gutenberg.php 7 months ago class-disable-rest-api.php 7 months ago class-disable-smaller-components.php 7 months ago class-disable-updates.php 7 months ago class-disable-xml-rpc.php 7 months ago class-display-system-summary.php 7 months ago class-email-address-obfuscator.php 7 months ago class-email-delivery.php 7 months ago class-enhance-list-tables.php 7 months ago class-external-permalinks.php 7 months ago class-heartbeat-control.php 7 months ago class-hide-admin-bar.php 7 months ago class-hide-admin-notices.php 7 months ago class-image-sizes-panel.php 7 months ago class-image-upload-control.php 7 months ago class-insert-head-body-footer-code.php 7 months ago class-last-login-column.php 7 months ago class-limit-login-attempts.php 7 months ago class-login-id-type.php 7 months ago class-login-logout-menu.php 7 months ago class-maintenance-mode.php 7 months ago class-manage-ads-appads-txt.php 7 months ago class-manage-robots-txt.php 7 months ago class-media-replacement.php 7 months ago class-multiple-user-roles.php 7 months ago class-obfuscate-author-slugs.php 7 months ago class-open-external-links-in-new-tab.php 7 months ago class-password-protection.php 7 months ago class-redirect-after-login.php 7 months ago class-redirect-after-logout.php 7 months ago class-redirect-fourofour.php 7 months ago class-registration-date-column.php 7 months ago class-revisions-control.php 7 months ago class-search-engines-visibility.php 7 months ago class-settings-fields-render.php 7 months ago class-settings-sanitization.php 7 months ago class-settings-sections-fields.php 7 months ago class-show-custom-taxonomy-filters.php 7 months ago class-site-identity-on-login-page.php 7 months ago class-svg-upload.php 7 months ago class-various-admin-ui-enhancements.php 7 months ago class-view-admin-as-role.php 7 months ago class-wider-admin-menu.php 7 months ago class-wp-config-transformer.php 7 months ago
class-content-order.php
607 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">
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 if ( empty( wp_trim_excerpt( $post->post_excerpt, $post ) ) ) {
310 $short_excerpt = '';
311 } else {
312 $excerpt_trimmed = implode( " ", array_slice( explode( " ", wp_trim_excerpt( $post->post_excerpt, $post ) ), 0, 30 ) );
313 $short_excerpt = '<span class="item-excerpt"> | ' . $excerpt_trimmed . '</span>';
314 }
315 $taxonomies = get_object_taxonomies( $post->post_type, 'objects' );
316 // vi( $taxonomies );
317 $taxonomies_and_terms = '';
318 foreach ( $taxonomies as $taxonomy ) {
319 $terms = array();
320 if ( $taxonomy->hierarchical ) {
321 $taxonomy_terms = get_the_terms( $post->ID, $taxonomy->name );
322 if ( is_array( $taxonomy_terms ) && !empty( $taxonomy_terms ) ) {
323 foreach ( $taxonomy_terms as $term ) {
324 $terms[] = $term->name;
325 }
326 }
327 }
328 $terms = implode( ', ', $terms );
329 $taxonomies_and_terms .= ' | ' . $taxonomy->label . ': ' . $terms;
330 }
331 if ( !empty( $taxonomies_and_terms ) ) {
332 $taxonomies_and_terms = '<span class="item-taxonomy-terms">' . $taxonomies_and_terms . '</span>';
333 }
334 // If WPML plugin is active, let's get the current language
335 if ( in_array( 'sitepress-multilingual-cms/sitepress.php', get_option( 'active_plugins', array() ) ) ) {
336 $current_language = apply_filters( 'wpml_current_language', null );
337 $current_post_language_info = apply_filters( 'wpml_post_language_details', null, $post->ID );
338 if ( !is_wp_error( $current_post_language_info ) ) {
339 $current_post_language = $current_post_language_info['language_code'];
340 } else {
341 // wpml has not set language information for the post
342 // e.g. post is not translated yet, so, let's use the current site/admin language
343 $current_post_language = $current_language;
344 }
345 $same_language = $current_language === $current_post_language;
346 // true if language is the same, false otherwise
347 } else {
348 // WPML is not active, $same_language is always true, e.g. all posts are in English
349 $same_language = true;
350 }
351 // Only render sortable for posts that have the same language as the current chosen language
352 if ( $same_language ) {
353 ?>
354 <li id="list_<?php
355 echo esc_attr( $post->ID );
356 ?>" class="list-item" data-id="<?php
357 echo esc_attr( $post->ID );
358 ?>" data-menu-order="<?php
359 echo esc_attr( $post->menu_order );
360 ?>" data-parent="<?php
361 echo esc_attr( $post->post_parent );
362 ?>" data-has-child="<?php
363 echo esc_attr( $has_child );
364 ?>" data-post-type="<?php
365 echo esc_attr( $post->post_type );
366 ?>">
367 <div class="row">
368 <div class="row-content">
369 <?php
370 echo '<div class="content-main">
371 <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 ) . wp_kses_post( $taxonomies_and_terms ) . wp_kses_post( $short_excerpt ) . '<div class="fader"></div>
372 </div>';
373 if ( !in_array( $post->post_type, array('asenha_code_snippet') ) ) {
374 echo '<div class="content-additional">
375 <a href="' . esc_attr( get_the_permalink( $post->ID ) ) . '" target="_blank" class="button item-view-link">View</a>
376 </div>';
377 }
378 ?>
379 </div>
380 </div>
381 <?php
382 }
383 // if ( $same_language )
384 ?>
385 </li>
386 <?php
387 }
388
389 /**
390 * Enqueue styles for content order pages
391 *
392 * @since 5.0.0
393 */
394 public function enqueue_content_order_styles() {
395 wp_enqueue_style(
396 'content-order-style',
397 ASENHA_URL . 'assets/css/content-order.css',
398 array(),
399 ASENHA_VERSION
400 );
401 }
402
403 /**
404 * Enqueue scripts for content order pages
405 *
406 * @since 5.0.0
407 */
408 public function enqueue_content_order_scripts() {
409 global $typenow;
410 wp_enqueue_script(
411 'content-order-jquery-ui-touch-punch',
412 ASENHA_URL . 'assets/js/jquery.ui.touch-punch.min.js',
413 array('jquery-ui-sortable'),
414 '0.2.3',
415 true
416 );
417 wp_register_script(
418 'content-order-nested-sortable',
419 ASENHA_URL . 'assets/js/jquery.mjs.nestedSortable.js',
420 array('content-order-jquery-ui-touch-punch'),
421 '2.0.0',
422 true
423 );
424 wp_enqueue_script(
425 'content-order-sort',
426 ASENHA_URL . 'assets/js/content-order-sort.js',
427 array('content-order-nested-sortable'),
428 ASENHA_VERSION,
429 true
430 );
431 wp_localize_script( 'content-order-sort', 'contentOrderSort', array(
432 'action' => 'save_custom_order',
433 'nonce' => wp_create_nonce( 'order_sorting_nonce' ),
434 'hirarchical' => ( is_post_type_hierarchical( $typenow ) ? 'true' : 'false' ),
435 ) );
436 }
437
438 /**
439 * Save custom content order coming from ajax call
440 *
441 * @since 5.0.0
442 */
443 public function save_custom_content_order() {
444 global $wpdb;
445 // Check user capabilities
446 if ( !current_user_can( 'edit_others_posts' ) ) {
447 wp_send_json( 'Something went wrong.' );
448 }
449 // Verify nonce
450 if ( !wp_verify_nonce( $_POST['nonce'], 'order_sorting_nonce' ) ) {
451 wp_send_json( 'Something went wrong.' );
452 }
453 // Get ajax variables
454 $action = ( isset( $_POST['action'] ) ? $_POST['action'] : '' );
455 // Item parent is currently 0, as we only handle sorting of non-child posts
456 $item_parent = ( isset( $_POST['item_parent'] ) ? absint( $_POST['item_parent'] ) : 0 );
457 $menu_order_start = ( isset( $_POST['start'] ) ? absint( $_POST['start'] ) : 0 );
458 $post_id = ( isset( $_POST['post_id'] ) ? absint( $_POST['post_id'] ) : 0 );
459 $item_menu_order = ( isset( $_POST['menu_order'] ) ? absint( $_POST['menu_order'] ) : 0 );
460 $items_to_exclude = ( isset( $_POST['excluded_items'] ) ? absint( $_POST['excluded_items'] ) : array() );
461 $post_type = ( isset( $_POST['post_type'] ) ? $_POST['post_type'] : false );
462 // Make processing faster by removing certain actions
463 remove_action( 'pre_post_update', 'wp_save_post_revision' );
464 // $response array for ajax response
465 $response = array();
466 // Update the item whose order/position was moved
467 if ( $post_id > 0 && !isset( $_POST['more_posts'] ) ) {
468 $wpdb->update(
469 $wpdb->posts,
470 // The table
471 array(
472 'menu_order' => $item_menu_order,
473 ),
474 array(
475 'ID' => $post_id,
476 )
477 );
478 clean_post_cache( $post_id );
479 $items_to_exclude[] = $post_id;
480 }
481 if ( 'attachment' == $post_type ) {
482 $post_status = array('inherit', 'private');
483 } else {
484 $post_status = array(
485 'publish',
486 'future',
487 'draft',
488 'pending',
489 'private'
490 );
491 }
492 // Get all posts from the post type related to ajax request
493 $query_args = array(
494 'post_type' => $post_type,
495 'orderby' => 'menu_order title',
496 'order' => 'ASC',
497 'posts_per_page' => -1,
498 'suppress_filters' => true,
499 'ignore_sticky_posts' => true,
500 'post_status' => $post_status,
501 'post__not_in' => $items_to_exclude,
502 'update_post_term_cache' => false,
503 'update_post_meta_cache' => false,
504 );
505 if ( 'attachment' == $post_type ) {
506 // do nothing, we do not add post_parent parameter as media items can be attached to other posts, making them the parent.
507 } else {
508 // Item parent is currently 0, as we only handle sorting of non-child posts
509 $query_args['post_parent'] = $item_parent;
510 }
511 $posts = new WP_Query($query_args);
512 if ( $posts->have_posts() ) {
513 // Iterate through posts and update menu order and post parent
514 foreach ( $posts->posts as $post ) {
515 // If the $post is the one being displaced (shited downward) by the moved item, increment it's menu_order by one
516 if ( $menu_order_start == $item_menu_order && $post_id > 0 ) {
517 $menu_order_start++;
518 }
519 // Only process posts other than the moved item, which has been processed earlier outside this loop
520 if ( $post_id != $post->ID ) {
521 // Update menu_order
522 $wpdb->update( $wpdb->posts, array(
523 'menu_order' => $menu_order_start,
524 ), array(
525 'ID' => $post->ID,
526 ) );
527 clean_post_cache( $post->ID );
528 }
529 $items_to_exclude[] = $post->ID;
530 $menu_order_start++;
531 }
532 die( json_encode( $response ) );
533 } else {
534 die( json_encode( $response ) );
535 }
536 }
537
538 /**
539 * Set default ordering of list tables of sortable post types by 'menu_order'
540 *
541 * @link https://developer.wordpress.org/reference/classes/wp_query/#methods
542 * @since 5.0.0
543 */
544 public function orderby_menu_order( $query ) {
545 global $pagenow, $typenow;
546 $query_post_type = $query->get( 'post_type' );
547 $options = get_option( ASENHA_SLUG_U, array() );
548 // Hierarchical post types that should be custom ordered
549 $content_order_for = ( isset( $options['content_order_for'] ) ? $options['content_order_for'] : array() );
550 $content_order_enabled_post_types = array();
551 if ( is_array( $content_order_for ) && count( $content_order_for ) > 0 ) {
552 foreach ( $content_order_for as $post_type_slug => $is_custom_order_enabled ) {
553 if ( $is_custom_order_enabled ) {
554 $content_order_enabled_post_types[] = $post_type_slug;
555 }
556 }
557 }
558 $should_be_custom_sorted = false;
559 // All post types that should be custom ordered
560 $content_order_post_types = $content_order_enabled_post_types;
561 // Use custom order in wp-admin listing pages/tables for enabled post types
562 if ( is_admin() && ('edit.php' == $pagenow || 'upload.php' == $pagenow) && !isset( $_GET['orderby'] ) ) {
563 if ( in_array( $typenow, $content_order_post_types ) ) {
564 $query->set( 'orderby', 'menu_order title' );
565 $query->set( 'order', 'ASC' );
566 }
567 }
568 }
569
570 /**
571 * Make sure newly created posts are assigned the highest menu_order so it's added at the bottom of the existing order
572 *
573 * @since 6.2.1
574 */
575 public function set_menu_order_for_new_posts( $post_id, $post, $update ) {
576 $options = get_option( ASENHA_SLUG_U, array() );
577 $content_order_for = ( isset( $options['content_order_for'] ) ? $options['content_order_for'] : array() );
578 $content_order_enabled_post_types = array();
579 if ( is_array( $content_order_for ) && count( $content_order_for ) > 0 ) {
580 foreach ( $content_order_for as $post_type_slug => $is_custom_order_enabled ) {
581 if ( $is_custom_order_enabled ) {
582 $content_order_enabled_post_types[] = $post_type_slug;
583 }
584 }
585 }
586 // Only assign menu_order if there are none assigned when creating the post, i.e. menu_order is 0
587 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 ) {
588 $post_with_highest_menu_order = get_posts( array(
589 'post_type' => $post->post_type,
590 'posts_per_page' => 1,
591 'orderby' => 'menu_order',
592 'order' => 'DESC',
593 ) );
594 if ( $post_with_highest_menu_order ) {
595 $new_menu_order = (int) $post_with_highest_menu_order[0]->menu_order + 1;
596 // Assign the one higher menu_order to the new post
597 $args = array(
598 'ID' => $post_id,
599 'menu_order' => $new_menu_order,
600 );
601 wp_update_post( $args );
602 }
603 }
604 }
605
606 }
607