| @@ -6,8 +6,13 @@ | ||
| 6 | 6 | */ |
| 7 | 7 | |
| 8 | 8 | namespace MainWP\Dashboard; |
| 9 | 9 | |
| 10 | +// Exit if accessed directly. | |
| 11 | +if ( ! defined( 'ABSPATH' ) ) { | |
| 12 | + exit; | |
| 13 | +} | |
| 14 | + | |
| 10 | 15 | /** |
| 11 | 16 | * Class MainWP_Post_Page_Handler |
| 12 | 17 | * |
| 13 | 18 | * @uses MainWP_Bulk_Add |
| @@ -234,9 +239,9 @@ | ||
| 234 | 239 | $new_cats = json_decode( $website->categories, true ); |
| 235 | 240 | if ( is_array( $new_cats ) && ! empty( $new_cats ) ) { |
| 236 | 241 | $current = current( $new_cats ); |
| 237 | 242 | if ( is_array( $current ) && ! empty( $current ) ) { // new site's category format data. |
| 238 | - static::arrange_categories_list( $new_cats, $allCategories_new_tree ); | |
| 243 | + static::arrange_categories_list( $new_cats, $allCategories_new_tree, $website ); | |
| 239 | 244 | } elseif ( is_string( $current ) ) { // old format. |
| 240 | 245 | $allCategories = array_unique( array_merge( $allCategories, $new_cats ) ); |
| 241 | 246 | } |
| 242 | 247 | } |
| @@ -242,9 +247,9 @@ | ||
| 242 | 247 | } |
| 243 | 248 | } else { |
| 244 | 249 | $custom_categories = apply_filters( 'mainwp_edit_post_get_categories', false, $website, $_REQUEST ); |
| 245 | 250 | if ( is_array( $custom_categories ) && ! empty( $custom_categories ) ) { |
| 246 | - static::arrange_categories_list( $custom_categories, $allCategories_new_tree ); | |
| 251 | + static::arrange_categories_list( $custom_categories, $allCategories_new_tree, $website ); | |
| 247 | 252 | } |
| 248 | 253 | } |
| 249 | 254 | } |
| 250 | 255 | } |
| @@ -287,10 +292,34 @@ | ||
| 287 | 292 | * @param array $print_cats categories to print. |
| 288 | 293 | * @param array $check_printed_cats_names check printed cats slugs. |
| 289 | 294 | */ |
| 290 | 295 | public static function print_catergories_tree( $print_cats, &$check_printed_cats_names = array() ) { // phpcs:ignore Squiz.Functions.MultiLineFunctionDeclaration.ContentAfterBrace -- NOSONAR - complexity. |
| 296 | + | |
| 297 | + // Build the list of sites for each category to show in tooltip. | |
| 298 | + $cats_sites = array(); | |
| 291 | 299 | foreach ( $print_cats as $item ) { |
| 292 | 300 | |
| 301 | + $term_pt = isset( $item['term_post_type'] ) && ! empty( $item['term_post_type'] ) ? sanitize_text_field( wp_unslash( $item['term_post_type'] ) ) : ''; | |
| 302 | + | |
| 303 | + $print_slug = $item['slug']; | |
| 304 | + | |
| 305 | + if ( ! empty( $term_pt ) ) { | |
| 306 | + $print_slug .= '_' . $term_pt; | |
| 307 | + } | |
| 308 | + | |
| 309 | + if ( isset( $item['site_id'] ) && isset( $item['site_name'] ) ) { | |
| 310 | + if ( ! isset( $cats_sites[ $print_slug ] ) ) { | |
| 311 | + $cats_sites[ $print_slug ] = array(); | |
| 312 | + } | |
| 313 | + | |
| 314 | + if ( ! in_array( $item['site_name'], $cats_sites[ $print_slug ], true ) ) { | |
| 315 | + $cats_sites[ $print_slug ][] = $item['site_name']; | |
| 316 | + } | |
| 317 | + } | |
| 318 | + } | |
| 319 | + | |
| 320 | + foreach ( $print_cats as $item ) { | |
| 321 | + | |
| 293 | 322 | $level = isset( $item['level'] ) ? $item['level'] : 0; |
| 294 | 323 | $term_pt = isset( $item['term_post_type'] ) && ! empty( $item['term_post_type'] ) ? sanitize_text_field( wp_unslash( $item['term_post_type'] ) ) : ''; |
| 295 | 324 | |
| 296 | 325 | $print_slug = $item['slug']; |
| @@ -318,10 +347,14 @@ | ||
| 318 | 347 | } else { |
| 319 | 348 | $cat_val = esc_attr( $item['name'] ); |
| 320 | 349 | } |
| 321 | 350 | |
| 351 | + if ( ! empty( $cats_sites[ $print_slug ] ) ) { | |
| 352 | + $cls .= ' mainwp-html-popup '; | |
| 353 | + } | |
| 354 | + | |
| 322 | 355 | $title = ! empty( $term_pt ) ? '<strong>' . esc_html( $item['name'] ) . '</strong>' : esc_html( $item['name'] ); |
| 323 | - echo '<div class="item ' . esc_attr( $cls ) . '" data-value="' . $cat_val . '" data-slug="' . esc_attr( $item['slug'] ) . '" post-type="' . esc_attr( $term_pt ) . '"class="sitecategory-list">' . $title . '</div>'; //phpcs:ignore -- ok. | |
| 356 | + echo '<div class="item ' . esc_attr( $cls ) . '" data-value="' . $cat_val . '" data-slug="' . esc_attr( $item['slug'] ) . '" post-type="' . esc_attr( $term_pt ) . '" ' . ( ! empty( $cats_sites[ $print_slug ] ) ? ' data-position="left center" html-popup-content="' . esc_attr( implode( ', ', $cats_sites[ $print_slug ] ) ) . '" data-inverted=""' : '') . '>' . $title . '</div>'; //phpcs:ignore -- $title ok. | |
| 324 | 357 | } |
| 325 | 358 | |
| 326 | 359 | if ( ! empty( $item['children'] ) ) { |
| 327 | 360 | static::print_catergories_tree( $item['children'], $check_printed_cats_names ); |
| @@ -333,12 +366,15 @@ | ||
| 333 | 366 | * Method arrange_categories_list() |
| 334 | 367 | * |
| 335 | 368 | * Tweaked John#105641 at StackOver#4284616. |
| 336 | 369 | * |
| 337 | - * @param array $categories categories. | |
| 338 | - * @param array $save_all_cats_tree all categories tree. | |
| 370 | + * Builds a hierarchical category tree from a flat category list. | |
| 371 | + * | |
| 372 | + * @param array $categories categories. | |
| 373 | + * @param array $save_all_cats_tree all categories tree. | |
| 374 | + * @param object $website website object. | |
| 339 | 375 | */ |
| 340 | - public static function arrange_categories_list( $categories, &$save_all_cats_tree ) { //phpcs:ignore -- NOSONAR - complex. | |
| 376 | + public static function arrange_categories_list( $categories, &$save_all_cats_tree, $website = null ) { //phpcs:ignore -- NOSONAR - complex. | |
| 341 | 377 | |
| 342 | 378 | if ( ! is_array( $save_all_cats_tree ) ) { |
| 343 | 379 | $save_all_cats_tree = array(); |
| 344 | 380 | } |
| @@ -347,10 +383,10 @@ | ||
| 347 | 383 | return; |
| 348 | 384 | } |
| 349 | 385 | |
| 350 | 386 | $tree_cats = $save_all_cats_tree; |
| 351 | - $all_cats = array(); | |
| 352 | - $child_cats = array(); | |
| 387 | + $all_cats = array(); // Category lookup indexed by term_id. | |
| 388 | + $child_cats = array(); // Categories waiting for their parent to be processed. | |
| 353 | 389 | |
| 354 | 390 | foreach ( $categories as $cat ) { |
| 355 | 391 | |
| 356 | 392 | if ( ! is_array( $cat ) || empty( $cat['name'] ) ) { |
| @@ -356,27 +392,34 @@ | ||
| 356 | 392 | if ( ! is_array( $cat ) || empty( $cat['name'] ) ) { |
| 357 | 393 | continue; |
| 358 | 394 | } |
| 359 | 395 | |
| 396 | + $cat['site_id'] = $website ? $website->id : null; | |
| 397 | + $cat['site_name'] = $website ? $website->name : null; | |
| 398 | + | |
| 360 | 399 | $cat['children'] = array(); |
| 361 | 400 | $term_id = $cat['term_id']; |
| 362 | 401 | |
| 363 | - // If this is a top-level. | |
| 402 | + // Top-level category. | |
| 364 | 403 | if ( empty( $cat['parent'] ) ) { |
| 365 | 404 | $cat['level'] = 0; |
| 366 | 405 | $all_cats[ $term_id ] = $cat; |
| 367 | - $tree_cats[] =& $all_cats[ $term_id ]; | |
| 368 | - // If this isn't a top-level. | |
| 406 | + // Store by reference so child relationships added later | |
| 407 | + // are reflected in the final tree structure. | |
| 408 | + $tree_cats[] =& $all_cats[ $term_id ]; | |
| 369 | 409 | } else { |
| 410 | + // Parent may not have been processed yet, so defer linking. | |
| 370 | 411 | $cat['level'] = isset( $all_cats[ $cat['parent'] ] ) && isset( $all_cats[ $cat['parent'] ]['level'] ) ? $all_cats[ $cat['parent'] ]['level'] + 1 : 1; |
| 371 | 412 | $child_cats[ $term_id ] = $cat; |
| 372 | 413 | } |
| 373 | 414 | } |
| 374 | 415 | |
| 416 | + // Multiple passes are needed when categories are not ordered by hierarchy. | |
| 417 | + // Limit iterations to prevent infinite loops caused by invalid parent IDs. | |
| 375 | 418 | $stop = count( $categories ); |
| 376 | 419 | $limit = 0; |
| 377 | 420 | $count = count( $child_cats ); |
| 378 | - // Process child cats. | |
| 421 | + | |
| 379 | 422 | while ( $count > 0 && $limit < $stop ) { |
| 380 | 423 | foreach ( $child_cats as $cat ) { |
| 381 | 424 | $term_id = $cat['term_id']; |
| 382 | 425 | $pid = isset( $cat['parent'] ) ? $cat['parent'] : -1; |
| @@ -381,17 +424,23 @@ | ||
| 381 | 424 | $term_id = $cat['term_id']; |
| 382 | 425 | $pid = isset( $cat['parent'] ) ? $cat['parent'] : -1; |
| 383 | 426 | |
| 384 | 427 | if ( isset( $all_cats[ $pid ] ) ) { |
| 385 | - $cat['level'] = isset( $all_cats[ $pid ] ) && isset( $all_cats[ $pid ]['level'] ) ? $all_cats[ $pid ]['level'] + 1 : 1; | |
| 386 | - $all_cats[ $term_id ] = $cat; | |
| 428 | + $cat['level'] = isset( $all_cats[ $pid ]['level'] ) ? $all_cats[ $pid ]['level'] + 1 : 1; | |
| 429 | + $all_cats[ $term_id ] = $cat; | |
| 430 | + | |
| 431 | + // Link child to parent by reference so nested descendants | |
| 432 | + // automatically become part of the tree. | |
| 387 | 433 | $all_cats[ $pid ]['children'][] =& $all_cats[ $term_id ]; |
| 388 | - unset( $child_cats[ $cat['term_id'] ] ); | |
| 434 | + | |
| 435 | + unset( $child_cats[ $term_id ] ); | |
| 389 | 436 | } |
| 390 | 437 | } |
| 391 | 438 | ++$limit; |
| 392 | 439 | } |
| 393 | - $save_all_cats_tree = $tree_cats; // to prevent it deleted by reference. | |
| 440 | + | |
| 441 | + // Return the completed category tree. | |
| 442 | + $save_all_cats_tree = $tree_cats; | |
| 394 | 443 | } |
| 395 | 444 | |
| 396 | 445 | /** |
| 397 | 446 | * Method posting_bulk() |
| @@ -465,13 +514,9 @@ | ||
| 465 | 514 | if ( $p_id ) { |
| 466 | 515 | static::posting_posts( $p_id, 'posting' ); |
| 467 | 516 | } else { |
| 468 | 517 | ?> |
| 469 | - <div class="error"> | |
| 470 | - <p> | |
| 471 | - <strong><?php esc_html_e( 'ERROR', 'mainwp' ); ?></strong>: <?php esc_html_e( 'An undefined error occured!', 'mainwp' ); ?> | |
| 472 | - </p> | |
| 473 | - </div> | |
| 518 | + <div class="ui red message"><?php esc_html_e( 'Undefined error occurred!', 'mainwp' ); ?></div> | |
| 474 | 519 | <?php |
| 475 | 520 | } |
| 476 | 521 | } |
| 477 | 522 | ?> |
| @@ -480,10 +525,10 @@ | ||
| 480 | 525 | <?php do_action( 'mainwp_posts_posting_popup_actions', $post_id ); ?> |
| 481 | 526 | <a href="admin.php?page=PostBulkAdd" class="ui green button new-bulk-post"><?php esc_html_e( 'New Post', 'mainwp' ); ?></a> |
| 482 | 527 | </div> |
| 483 | 528 | </div> |
| 484 | - <div class="ui active inverted dimmer" id="mainwp-posting-running"> | |
| 485 | - <div class="ui indeterminate large text loader"><?php esc_html_e( 'Running ...', 'mainwp' ); ?></div> | |
| 529 | + <div class="ui active dimmer" id="mainwp-posting-running"> | |
| 530 | + <div class="ui double text loader"><?php esc_html_e( 'Running ...', 'mainwp' ); ?></div> | |
| 486 | 531 | </div> |
| 487 | 532 | <script type="text/javascript"> |
| 488 | 533 | jQuery( document ).ready( function () { |
| 489 | 534 | jQuery( "#mainwp-posting-running" ).hide(); |
| @@ -489,9 +534,9 @@ | ||
| 489 | 534 | jQuery( "#mainwp-posting-running" ).hide(); |
| 490 | 535 | jQuery( "#mainwp-posting-post-modal" ).modal( { |
| 491 | 536 | closable: true, |
| 492 | 537 | onHide: function() { |
| 493 | - location.href = 'admin.php?page=PostBulkManage'; | |
| 538 | + mainwp_forceReload('admin.php?page=PostBulkManage'); | |
| 494 | 539 | } |
| 495 | 540 | } ).modal( 'show' ); |
| 496 | 541 | } ); |
| 497 | 542 | </script> |
| @@ -518,9 +563,9 @@ | ||
| 518 | 563 | } else { |
| 519 | 564 | ?> |
| 520 | 565 | <div class="error"> |
| 521 | 566 | <p> |
| 522 | - <strong><?php esc_html_e( 'ERROR', 'mainwp' ); ?></strong>: <?php esc_html_e( 'An undefined error occured!', 'mainwp' ); ?> | |
| 567 | + <strong><?php esc_html_e( 'ERROR', 'mainwp' ); ?></strong>: <?php esc_html_e( 'An undefined error occurred!', 'mainwp' ); ?> | |
| 523 | 568 | </p> |
| 524 | 569 | </div> |
| 525 | 570 | <?php |
| 526 | 571 | } |
| @@ -529,10 +574,10 @@ | ||
| 529 | 574 | <div class="actions"> |
| 530 | 575 | <a href="admin.php?page=PostBulkAdd" class="ui green button"><?php esc_html_e( 'New Post', 'mainwp' ); ?></a> |
| 531 | 576 | </div> |
| 532 | 577 | </div> |
| 533 | - <div class="ui active inverted dimmer" id="mainwp-posting-running"> | |
| 534 | - <div class="ui indeterminate large text loader"><?php esc_html_e( 'Running ...', 'mainwp' ); ?></div> | |
| 578 | + <div class="ui active dimmer" id="mainwp-posting-running"> | |
| 579 | + <div class="ui double text loader"><?php esc_html_e( 'Running...', 'mainwp' ); ?></div> | |
| 535 | 580 | </div> |
| 536 | 581 | <script type="text/javascript"> |
| 537 | 582 | jQuery( document ).ready( function () { |
| 538 | 583 | jQuery( "#mainwp-posting-running" ).hide(); |
| @@ -538,9 +583,9 @@ | ||
| 538 | 583 | jQuery( "#mainwp-posting-running" ).hide(); |
| 539 | 584 | jQuery( "#mainwp-posting-post-modal" ).modal( { |
| 540 | 585 | closable: true, |
| 541 | 586 | onHide: function() { |
| 542 | - location.href = 'admin.php?page=PostBulkManage'; | |
| 587 | + mainwp_forceReload('admin.php?page=PostBulkManage'); | |
| 543 | 588 | } |
| 544 | 589 | } ).modal( 'show' ); |
| 545 | 590 | mainwp_post_posting_start_next( true ); |
| 546 | 591 | } ); |