PluginProbe
Adminify – White Label, Admin Menu Editor, Login Customizer / 4.2.13
Adminify – White Label, Admin Menu Editor, Login Customizer v4.2.13
4.3.1 4.3.0 4.2.26 4.2.25 4.2.24 4.2.23 4.2.22 4.2.21 4.2.20 4.2.19 4.2.18 4.2.17 4.2.16 4.2.15 4.2.14 4.2.13 4.2.12 4.2.11 4.2.10 4.2.9 4.2.8 4.2.7 4.2.6 4.2.5 4.1.17 All 164 releases
adminify / Inc / Modules / PostTypesOrder / PostTypesOrder.php

PostTypesOrder.php in Adminify – White Label, Admin Menu Editor, Login Customizer 4.2.13, at Inc/Modules/PostTypesOrder/PostTypesOrder.php

641 lines 21.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace PXLBSAdminify\Inc\Modules\PostTypesOrder;
4
5 use PXLBSAdminify\Inc\Admin\AdminSettings;
6 use PXLBSAdminify\Inc\Admin\AdminSettingsModel;
7 use PXLBSAdminify\Inc\Modules\PostTypesOrder\PostTypesOrderWalker;
8
9 // no direct access allowed
10 if ( ! defined( 'ABSPATH' ) ) {
11 exit;
12 }
13
14 /**
15 * WP Adminify
16 *
17 * @package WP Adminify: Post Types Order
18 *
19 * @author WP Adminify <support@wpadminify.com>
20 */
21
22 class PostTypesOrder extends AdminSettingsModel {
23 public function __construct() {
24 $this->options = (array) AdminSettings::get_instance()->get('post_types_order');
25
26 // Admin Init
27 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only check, no state change.
28 if ( empty( $_GET ) ) {
29 add_action( 'admin_init', [ $this, 'refresh' ] );
30 }
31
32 add_action( 'admin_init', [ $this, 'pto_load_scripts' ] );
33 add_action( 'admin_enqueue_scripts', [ $this, 'pto_css' ], 99 );
34
35 // sortable ajax action
36 add_action( 'wp_ajax_pxlbsadminify_update_post_types_order', [ $this, 'pto_update_order' ] );
37 add_action( 'wp_ajax_pxlbsadminify_update_post_types_taxonomy_order', [ $this, 'pto_update_taxonomy' ] );
38
39 // reorder post types
40 add_action( 'pre_get_posts', [ $this, 'pto_pre_get_posts' ] );
41
42 add_filter( 'get_previous_post_where', array( $this, 'pto_previous_post_where' ) );
43 add_filter( 'get_previous_post_sort', [ $this, 'pto_previous_post_sort' ] );
44 add_filter( 'get_next_post_where', [ $this, 'pto_next_post_where' ] );
45 add_filter( 'get_next_post_sort', [ $this, 'pto_next_post_sort' ] );
46
47 // Taxonomy ordering (pto_taxonomies) is a Pro-only feature.
48 // The get_terms_orderby / wp_get_object_terms / get_terms
49 // filters are registered by Pro/Classes/Filters.php when the
50 // Pro plugin is active.
51
52 // reorder sites
53 if ( function_exists( 'is_multisite' ) && is_multisite() ) {
54 add_action( 'wp_ajax_pxlbsadminify_update_post_types_order_sites', [ $this, 'pto_update_sites' ] );
55
56 // networkadmin
57 if (
58 empty( $_SERVER['QUERY_STRING'] ) ||
59 ( ! empty( $_SERVER['QUERY_STRING'] ) &&
60 'action=deleteblog' !== $_SERVER['QUERY_STRING'] && // delete
61 'action=allblogs' !== $_SERVER['QUERY_STRING'] // delete all
62 )
63 ) {
64
65 // call from 'get_sites'
66 add_filter( 'sites_clauses', [ $this, 'pto_sites_clauses' ], 10, 1 );
67
68 add_action( 'admin_init', [ $this, 'pto_refresh_network' ] );
69
70 // adminbar sites reorder
71 add_filter( 'get_blogs_of_user', [ $this, 'pto_get_blogs_of_user' ], 10, 3 );
72 }
73 }
74 }
75
76 public function pto_media_list( $args = '' ) {
77 $defaults = [
78 'depth' => -1,
79 'date_format' => get_option( 'date_format' ),
80 'child_of' => 0,
81 'sort_column' => 'menu_order',
82 'post_status' => 'any',
83 ];
84
85 $r = wp_parse_args( $args, $defaults );
86 extract( $r, EXTR_SKIP );
87
88 $output = '';
89
90 $r['exclude'] = implode( ',', apply_filters( 'wp_list_pages_excludes', [] ) ); // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_exclude -- small admin page-exclude list, not a VIP-scale query.
91
92 // Query pages.
93 $r['hierarchical'] = 0;
94 $args = [
95 'sort_column' => 'menu_order',
96 'post_type' => $post_type,
97 'posts_per_page' => -1,
98 'post_status' => 'any',
99 'orderby' => [
100 'menu_order' => 'ASC',
101 'post_date' => 'DESC',
102 ],
103 ];
104
105 $the_query = new \WP_Query( $args );
106 $pages = $the_query->posts;
107
108 if ( ! empty( $pages ) ) {
109 $output .= $this->walkTree( $pages, $r['depth'], $r );
110 }
111
112 echo wp_kses_post( $output );
113 }
114
115 public function walkTree( $pages, $depth, $r ) {
116 $walker = new PostTypesOrderWalker();
117
118 $args = [ $pages, $depth, $r ];
119 return call_user_func_array( [ &$walker, 'walk' ], $args );
120 }
121
122
123 public function refresh() {
124 global $wpdb;
125 $objects = $this->pto_get_options();
126
127 if ( ! empty( $objects ) ) {
128 foreach ( $objects as $object ) {
129 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- direct query required for menu_order aggregate over posts; not cached intentionally.
130 $result = $wpdb->get_results(
131 $wpdb->prepare(
132 "SELECT count(*) as cnt, max(menu_order) as max, min(menu_order) as min
133 FROM $wpdb->posts
134 WHERE post_type = %s AND post_status IN ('publish', 'pending', 'draft', 'private', 'future')",
135 $object
136 )
137 );
138 if ( $result[0]->cnt == 0 || $result[0]->cnt == $result[0]->max ) {
139 continue;
140 }
141
142 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- direct query required to fetch ordered post IDs; not cached intentionally.
143 $results = $wpdb->get_results(
144 $wpdb->prepare(
145 "SELECT ID
146 FROM $wpdb->posts
147 WHERE post_type = %s AND post_status IN ('publish', 'pending', 'draft', 'private', 'future')
148 ORDER BY menu_order ASC",
149 $object
150 )
151 );
152 foreach ( $results as $key => $result ) {
153 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- direct query required to persist menu_order; not cached intentionally.
154 $wpdb->update( $wpdb->posts, [ 'menu_order' => $key + 1 ], [ 'ID' => $result->ID ] );
155 }
156 }
157 }
158 }
159
160
161
162 function pto_pre_get_posts( $wp_query ) {
163 $objects = $this->pto_get_options();
164 if ( empty( $objects ) ) {
165 return false;
166 }
167
168 /**
169 * for Admin
170 * @default
171 * post pto: [order] => null(desc) [orderby] => null(date)
172 * page: [order] => asc [orderby] => menu_order title
173 */
174
175 if ( is_admin() ) {
176 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only check, no state change.
177 if ( isset( $wp_query->query['post_type'] ) && ! isset( $_GET['orderby'] ) ) {
178 if ( in_array( $wp_query->query['post_type'], $objects ) ) {
179 $wp_query->set( 'orderby', 'menu_order' );
180 $wp_query->set( 'order', 'ASC' );
181 }
182 }
183 } else {
184 $active = false;
185
186 // page or custom post types
187 if ( isset( $wp_query->query['post_type'] ) ) {
188 // exclude array()
189 if ( ! is_array( $wp_query->query['post_type'] ) ) {
190 if ( in_array( $wp_query->query['post_type'], $objects ) ) {
191 $active = true;
192 }
193 }
194 // post
195 } else {
196 if ( in_array( 'post', $objects ) ) {
197 $active = true;
198 }
199 }
200
201 if ( ! $active ) {
202 return false;
203 }
204
205 // get_posts()
206 if ( isset( $wp_query->query['suppress_filters'] ) ) {
207 if ( $wp_query->get( 'orderby' ) == 'date' || $wp_query->get( 'orderby' ) == 'menu_order' ) {
208 $wp_query->set( 'orderby', 'menu_order' );
209 $wp_query->set( 'order', 'ASC' );
210 } elseif ( $wp_query->get( 'orderby' ) == 'default_date' ) {
211 $wp_query->set( 'orderby', 'date' );
212 }
213 // WP_Query( contain main_query )
214 } else {
215 if (
216 ! $wp_query->get( 'orderby' )
217 ) {
218 $wp_query->set( 'orderby', 'menu_order' );
219 }
220 if (
221 ! $wp_query->get( 'order' )
222 ) {
223 $wp_query->set( 'order', 'ASC' );
224 }
225 }
226 }
227 }
228
229
230 public function pto_update_order() {
231 // Security check - verify nonce and capability
232 check_ajax_referer( 'pxlbsadminify-pto-security-nonce', 'security' );
233
234 if ( ! current_user_can( 'edit_others_posts' ) ) {
235 wp_send_json_error( array( 'message' => __( 'You do not have permission to perform this action.', 'adminify' ) ) );
236 }
237
238 global $wpdb;
239 $data = [];
240 $order = isset( $_POST['order'] ) ? sanitize_text_field( wp_unslash( $_POST['order'] ) ) : '';
241 parse_str( $order, $data );
242
243 if ( ! is_array( $data ) ) {
244 return false;
245 }
246
247 // get objects per now page
248 $id_arr = [];
249 foreach ( $data as $key => $values ) {
250 foreach ( $values as $position => $id ) {
251 $id_arr[] = $id;
252 }
253 }
254
255 // get menu_order of objects per now page
256 $menu_order_arr = [];
257 foreach ( $id_arr as $key => $id ) {
258 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- direct query required to read menu_order by ID; not cached intentionally.
259 $results = $wpdb->get_results( "SELECT menu_order FROM $wpdb->posts WHERE ID = " . intval( $id ) );
260 foreach ( $results as $result ) {
261 $menu_order_arr[] = $result->menu_order;
262 }
263 }
264
265 // maintains key association = no
266 sort( $menu_order_arr );
267
268 foreach ( $data as $key => $values ) {
269 foreach ( $values as $position => $id ) {
270 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- direct query required to persist menu_order; not cached intentionally.
271 $wpdb->update( $wpdb->posts, [ 'menu_order' => $menu_order_arr[ $position ] ], [ 'ID' => intval( $id ) ] );
272 }
273 }
274
275 // same number check
276 $post_type = get_post_type( $id );
277 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- direct query required for menu_order duplicate detection; not cached intentionally.
278 $results = $wpdb->get_results(
279 $wpdb->prepare(
280 "SELECT COUNT(menu_order) AS mo_count, post_type, menu_order FROM $wpdb->posts
281 WHERE post_type = %s AND post_status IN ('publish', 'pending', 'draft', 'private', 'future')
282 AND menu_order > 0 GROUP BY post_type, menu_order HAVING (mo_count) > 1",
283 $post_type
284 )
285 );
286 if ( count( $results ) > 0 ) {
287
288 // menu_order refresh
289 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- direct query required to fetch ordered post IDs; not cached intentionally.
290 $results = $wpdb->get_results(
291 $wpdb->prepare(
292 "SELECT ID, menu_order FROM $wpdb->posts
293 WHERE post_type = %s AND post_status IN ('publish', 'pending', 'draft', 'private', 'future')
294 AND menu_order > 0 ORDER BY menu_order",
295 $post_type
296 )
297 );
298 foreach ( $results as $key => $result ) {
299 $view_posi = array_search( $result->ID, $id_arr, true );
300 if ( $view_posi === false ) {
301 $view_posi = 999;
302 }
303 $sort_key = ( $result->menu_order * 1000 ) + $view_posi;
304 $sort_ids[ $sort_key ] = $result->ID;
305 }
306 ksort( $sort_ids );
307 $oreder_no = 0;
308 foreach ( $sort_ids as $key => $id ) {
309 $oreder_no = $oreder_no + 1;
310 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- direct query required to persist menu_order; not cached intentionally.
311 $wpdb->update( $wpdb->posts, [ 'menu_order' => $oreder_no ], [ 'ID' => intval( $id ) ] );
312 }
313 }
314 }
315
316 public function pto_update_taxonomy() {
317 // Security check - verify nonce and capability
318 check_ajax_referer( 'pxlbsadminify-pto-security-nonce', 'security' );
319
320 if ( ! current_user_can( 'manage_categories' ) ) {
321 wp_send_json_error( array( 'message' => __( 'You do not have permission to perform this action.', 'adminify' ) ) );
322 }
323
324 global $wpdb;
325
326 $order = isset( $_POST['order'] ) ? sanitize_text_field( wp_unslash( $_POST['order'] ) ) : '';
327 parse_str( $order, $data );
328
329 if ( ! is_array( $data ) ) {
330 return false;
331 }
332
333 $id_arr = [];
334 foreach ( $data as $key => $values ) {
335 foreach ( $values as $position => $id ) {
336 $id_arr[] = $id;
337 }
338 }
339
340 $menu_order_arr = [];
341 foreach ( $id_arr as $key => $id ) {
342 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- direct query required to read term_order by ID; not cached intentionally.
343 $results = $wpdb->get_results( "SELECT term_order FROM $wpdb->terms WHERE term_id = " . intval( $id ) );
344 foreach ( $results as $result ) {
345 $menu_order_arr[] = $result->term_order;
346 }
347 }
348 sort( $menu_order_arr );
349
350 foreach ( $data as $key => $values ) {
351 foreach ( $values as $position => $id ) {
352 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- direct query required to persist term_order; not cached intentionally.
353 $wpdb->update( $wpdb->terms, [ 'term_order' => $menu_order_arr[ $position ] ], [ 'term_id' => intval( $id ) ] );
354 }
355 }
356
357 // same number check
358 $term = get_term( $id );
359 $taxonomy = $term->taxonomy;
360 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- direct query required for term_order duplicate detection; not cached intentionally.
361 $results = $wpdb->get_results(
362 $wpdb->prepare(
363 "SELECT COUNT(term_order) AS to_count, term_order
364 FROM $wpdb->terms AS terms
365 INNER JOIN $wpdb->term_taxonomy AS term_taxonomy ON ( terms.term_id = term_taxonomy.term_id )
366 WHERE term_taxonomy.taxonomy = %s GROUP BY taxonomy, term_order HAVING (to_count) > 1",
367 $taxonomy
368 )
369 );
370 if ( count( $results ) > 0 ) {
371 // term_order refresh
372 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- direct query required to fetch ordered term IDs; not cached intentionally.
373 $results = $wpdb->get_results(
374 $wpdb->prepare(
375 "SELECT terms.term_id, term_order
376 FROM $wpdb->terms AS terms
377 INNER JOIN $wpdb->term_taxonomy AS term_taxonomy ON ( terms.term_id = term_taxonomy.term_id )
378 WHERE term_taxonomy.taxonomy = %s
379 ORDER BY term_order ASC",
380 $taxonomy
381 )
382 );
383 foreach ( $results as $key => $result ) {
384 $view_posi = array_search( $result->term_id, $id_arr, true );
385 if ( $view_posi === false ) {
386 $view_posi = 999;
387 }
388 $sort_key = ( $result->term_order * 1000 ) + $view_posi;
389 $sort_ids[ $sort_key ] = $result->term_id;
390 }
391 ksort( $sort_ids );
392 $oreder_no = 0;
393 foreach ( $sort_ids as $key => $id ) {
394 $oreder_no = $oreder_no + 1;
395 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- direct query required to persist term_order; not cached intentionally.
396 $wpdb->update( $wpdb->terms, [ 'term_order' => $oreder_no ], [ 'term_id' => $id ] );
397 }
398 }
399
400 do_action( 'pxlbsadminify_update_post_types_order_taxonomy' );
401 }
402
403 public function pto_load_scripts() {
404 global $pagenow;
405
406 if ( $this->conditional_script_load() || ( $pagenow === 'upload.php' && ( isset( $this->options['pto_media'] ) && $this->options['pto_media'] ) ) ) {
407 wp_enqueue_script( 'jquery' );
408 wp_enqueue_script( 'jquery-ui-sortable' );
409 wp_enqueue_script( 'adminify-post-type-order', PXLBSADMINIFY_URL . 'Inc/Modules/PostTypesOrder/js/post-type-order.js', [ 'jquery' ], PXLBSADMINIFY_VER, true );
410 wp_localize_script( 'adminify-post-type-order', 'PXLBSADMINIFY_PTO', array(
411 'nonce' => wp_create_nonce( 'pxlbsadminify-pto-security-nonce' ),
412 ) );
413 }
414 }
415
416 public function pto_css() {
417 global $pagenow;
418 if ( $this->conditional_script_load() || ( $pagenow === 'upload.php' && ( ! empty( $this->options['pto_media'] ) ) ) ) {
419 echo '<!-- Start of Post Type and Taxonomy Order --->';
420 echo '<style type="text/css">';
421 echo '.adminify-table-responsive-wrapper .ui-sortable tr:hover{cursor:move}.adminify-table-responsive-wrapper .ui-sortable tr.alternate{background-color:#f9f9f9 !important}.adminify-table-responsive-wrapper .ui-sortable tr.ui-sortable-helper{background-color:#f9f9f9 !important;border-top:1px solid #dfdfdf;border-bottom:1px solid #dfdfdf;box-shadow:0 -5px 5px -4px rgba(0,0,0,.1),0 5px 5px -3px rgba(0,0,0,.1)}.adminify-table-responsive-wrapper .ui-sortable-placeholder{height:50px;background-color:#e9e9e9;border:2px dashed #dfdfdf;visibility:visible!important}.adminify-table-responsive-wrapper .wp-list-table{table-layout:fixed;width:100%;border-collapse:collapse}.adminify-table-responsive-wrapper.wp-list-table td,.adminify-table-responsive-wrapper .wp-list-table th{padding:8px 16px;text-align:left;white-space:nowrap;word-wrap:break-word;overflow:hidden}.adminify-table-responsive-wrapper.wp-list-table .column-title,.wp-list-table td.column-title,.adminify-table-responsive-wrapper{overflow-x:auto;-webkit-overflow-scrolling:touch}@media screen and (max-width:768px){.adminify-table-responsive-wrapper .wp-list-table td,.adminify-table-responsive-wrapper.wp-list-table th{padding:8px}}';
422 echo '</style>';
423 echo '<!-- End of Post Type and Taxonomy Order --->';
424 }
425 }
426
427 public function conditional_script_load() {
428 global $pagenow;
429
430 $active = false;
431
432 // Multisite > Sites
433 if (
434 function_exists( 'is_multisite' )
435 && is_multisite()
436 && $pagenow == 'sites.php'
437 ) {
438 return true;
439 }
440
441 $objects = $this->pto_get_options();
442
443 if ( empty( $objects ) ) {
444 return false;
445 }
446
447 // exclude (sorting, addnew page, edit page)
448 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only check, no state change.
449 if ( isset( $_GET['orderby'] ) || ( ! empty( $_SERVER['REQUEST_URI'] ) && strstr( sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ), 'action=edit' ) || strstr( sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ), 'wp-admin/post-new.php' ) ) ) {
450 return false;
451 }
452
453 if ( ! empty( $objects ) ) {
454 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only check, no state change.
455 if ( isset( $_GET['post_type'] ) && ! isset( $_GET['taxonomy'] ) && in_array( sanitize_text_field( wp_unslash( $_GET['post_type'] ) ), $objects ) ) { // if page or custom post types
456 $active = true;
457 }
458 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only check, no state change.
459 if ( ! isset( $_GET['post_type'] ) && ( ! empty( $_SERVER['REQUEST_URI'] && strstr( sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ), 'wp-admin/edit.php' ) ) && in_array( 'post', $objects ) ) ) {
460 // if post
461 $active = true;
462 }
463 }
464
465 return $active;
466 }
467
468 function pto_get_options() {
469 $objects = isset( $this->options['pto_posts'] ) && is_array( $this->options['pto_posts'] ) ? $this->options['pto_posts'] : [];
470 return $objects;
471 }
472
473 function pto_previous_post_where( $where ) {
474 global $post;
475
476 $objects = $this->pto_get_options();
477 if ( empty( $objects ) ) {
478 return $where;
479 }
480
481 if ( isset( $post->post_type ) && in_array( $post->post_type, $objects ) ) {
482 $current_menu_order = $post->menu_order;
483 $where = str_replace( "p.post_date < '" . $post->post_date . "'", "p.menu_order > '" . $current_menu_order . "'", $where );
484 }
485 return $where;
486 }
487
488 function pto_previous_post_sort( $orderby ) {
489 global $post;
490
491 $objects = $this->pto_get_options();
492 if ( empty( $objects ) ) {
493 return $orderby;
494 }
495
496 if ( isset( $post->post_type ) && in_array( $post->post_type, $objects ) ) {
497 $orderby = 'ORDER BY p.menu_order ASC LIMIT 1';
498 }
499 return $orderby;
500 }
501
502
503 function pto_next_post_where( $where ) {
504 global $post;
505
506 $objects = $this->pto_get_options();
507 if ( empty( $objects ) ) {
508 return $where;
509 }
510
511 if ( isset( $post->post_type ) && in_array( $post->post_type, $objects ) ) {
512 $current_menu_order = $post->menu_order;
513 $where = str_replace( "p.post_date > '" . $post->post_date . "'", "p.menu_order < '" . $current_menu_order . "'", $where );
514 }
515 return $where;
516 }
517
518 function pto_next_post_sort( $orderby ) {
519 global $post;
520
521 $objects = $this->pto_get_options();
522 if ( empty( $objects ) ) {
523 return $orderby;
524 }
525
526 if ( isset( $post->post_type ) && in_array( $post->post_type, $objects ) ) {
527 $orderby = 'ORDER BY p.menu_order DESC LIMIT 1';
528 }
529 return $orderby;
530 }
531
532
533 public function pto_sites_clauses( $pieces = [] ) {
534 if ( is_admin() ) {
535 return $pieces;
536 }
537
538 global $wp_version;
539 if ( version_compare( $wp_version, '4.6.0' ) >= 0 ) {
540 if ( 'blog_id ASC' === $pieces['orderby'] ) {
541 $pieces['orderby'] = 'menu_order ASC';
542 }
543 }
544 return $pieces;
545 }
546
547 public function pto_update_sites() {
548 // Security check - verify nonce and capability
549 check_ajax_referer( 'pxlbsadminify-pto-security-nonce', 'security' );
550
551 if ( ! current_user_can( 'manage_sites' ) ) {
552 wp_send_json_error( array( 'message' => __( 'You do not have permission to perform this action.', 'adminify' ) ) );
553 }
554
555 global $wpdb;
556
557 $order = isset( $_POST['order'] ) ? sanitize_text_field( wp_unslash( $_POST['order'] ) ) : '';
558 parse_str( $order, $data );
559
560 if ( ! is_array( $data ) ) {
561 return false;
562 }
563
564 $id_arr = [];
565 foreach ( $data as $key => $values ) {
566 foreach ( $values as $position => $id ) {
567 $id_arr[] = $id;
568 }
569 }
570
571 foreach ( $data as $key => $values ) {
572 foreach ( $values as $position => $id ) {
573 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- direct query required to persist blog menu_order; not cached intentionally.
574 $wpdb->update( $wpdb->prefix . 'blogs', [ 'menu_order' => $position + 1 ], [ 'blog_id' => intval( $id ) ] );
575 }
576 }
577
578 die();
579 }
580
581 public function pto_refresh_network() {
582 global $pagenow;
583 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only check, no state change.
584 if ( 'sites.php' === $pagenow && ! isset( $_GET['orderby'] ) ) {
585 add_filter( 'query', [ $this, 'pto_refresh_network_second' ] );
586 }
587 }
588
589
590 public function pto_refresh_network_second( $query ) {
591 global $wpdb, $wp_version, $blog_id;
592
593 // $wpdb->get_varやswitch_to_blog(1)
594 if ( version_compare( $wp_version, '4.7.0' ) >= 0 ) {
595 if ( 1 !== $blog_id ) {
596 return $query;
597 }
598 }
599
600 if (
601 false !== strpos( $query, "SELECT * FROM $wpdb->blogs WHERE site_id = '1'" ) ||
602 false !== strpos( $query, "SQL_CALC_FOUND_ROWS blog_id FROM $wpdb->blogs WHERE site_id = 1" )
603 ) {
604 if ( false !== strpos( $query, ' LIMIT ' ) ) {
605 $query = preg_replace( '/^(.*) LIMIT(.*)$/', '$1 ORDER BY menu_order ASC LIMIT $2', $query );
606 } else {
607 $query .= ' ORDER BY menu_order ASC';
608 }
609 }
610 return $query;
611 }
612
613
614 public function pto_get_blogs_of_user( $blogs ) {
615 $sites = get_sites( [] );
616 $sort_keys = [];
617 foreach ( $sites as $k => $v ) {
618 $sort_keys[] = $v->menu_order;
619 }
620 array_multisort( $sort_keys, SORT_ASC, $sites );
621
622 $blog_list = [];
623 foreach ( $blogs as $k => $v ) {
624 $blog_list[ $v->userblog_id ] = $v;
625 }
626
627 $new = [];
628 foreach ( $sites as $k => $v ) {
629 if (
630 isset( $v->blog_id ) &&
631 isset( $blog_list[ $v->blog_id ] ) &&
632 is_object( $blog_list[ $v->blog_id ] )
633 ) {
634 $new[] = $blog_list[ $v->blog_id ];
635 }
636 }
637
638 return $new;
639 }
640 }
641