278 $result = wp_delete_term( $menu->term_id, 'nav_menu' ); |
278 $result = wp_delete_term( $menu->term_id, 'nav_menu' ); |
279 |
279 |
280 // Remove this menu from any locations. |
280 // Remove this menu from any locations. |
281 $locations = get_nav_menu_locations(); |
281 $locations = get_nav_menu_locations(); |
282 foreach ( $locations as $location => $menu_id ) { |
282 foreach ( $locations as $location => $menu_id ) { |
283 if ( $menu_id == $menu->term_id ) { |
283 if ( $menu_id === $menu->term_id ) { |
284 $locations[ $location ] = 0; |
284 $locations[ $location ] = 0; |
285 } |
285 } |
286 } |
286 } |
287 set_theme_mod( 'nav_menu_locations', $locations ); |
287 set_theme_mod( 'nav_menu_locations', $locations ); |
288 |
288 |
456 'menu-item-post-date-gmt' => '', |
456 'menu-item-post-date-gmt' => '', |
457 ); |
457 ); |
458 |
458 |
459 $args = wp_parse_args( $menu_item_data, $defaults ); |
459 $args = wp_parse_args( $menu_item_data, $defaults ); |
460 |
460 |
461 if ( 0 == $menu_id ) { |
461 if ( 0 === $menu_id ) { |
462 $args['menu-item-position'] = 1; |
462 $args['menu-item-position'] = 1; |
463 } elseif ( 0 == (int) $args['menu-item-position'] ) { |
463 } elseif ( 0 === (int) $args['menu-item-position'] ) { |
464 $menu_items = 0 == $menu_id ? array() : (array) wp_get_nav_menu_items( $menu_id, array( 'post_status' => 'publish,draft' ) ); |
464 $menu_items = array(); |
465 $last_item = array_pop( $menu_items ); |
465 |
466 $args['menu-item-position'] = ( $last_item && isset( $last_item->menu_order ) ) ? 1 + $last_item->menu_order : count( $menu_items ); |
466 if ( 0 !== $menu_id ) { |
|
467 $menu_items = (array) wp_get_nav_menu_items( $menu_id, array( 'post_status' => 'publish,draft' ) ); |
|
468 } |
|
469 |
|
470 $last_item = array_pop( $menu_items ); |
|
471 |
|
472 if ( $last_item && isset( $last_item->menu_order ) ) { |
|
473 $args['menu-item-position'] = 1 + $last_item->menu_order; |
|
474 } else { |
|
475 $args['menu-item-position'] = count( $menu_items ); |
|
476 } |
467 } |
477 } |
468 |
478 |
469 $original_parent = 0 < $menu_item_db_id ? get_post_field( 'post_parent', $menu_item_db_id ) : 0; |
479 $original_parent = 0 < $menu_item_db_id ? get_post_field( 'post_parent', $menu_item_db_id ) : 0; |
470 |
480 |
471 if ( 'custom' === $args['menu-item-type'] ) { |
481 if ( 'custom' === $args['menu-item-type'] ) { |
545 * @param array $args An array of arguments used to update/add the menu item. |
555 * @param array $args An array of arguments used to update/add the menu item. |
546 */ |
556 */ |
547 do_action( 'wp_add_nav_menu_item', $menu_id, $menu_item_db_id, $args ); |
557 do_action( 'wp_add_nav_menu_item', $menu_id, $menu_item_db_id, $args ); |
548 } |
558 } |
549 |
559 |
550 // Associate the menu item with the menu term. |
560 /* |
551 // Only set the menu term if it isn't set to avoid unnecessary wp_get_object_terms(). |
561 * Associate the menu item with the menu term. |
|
562 * Only set the menu term if it isn't set to avoid unnecessary wp_get_object_terms(). |
|
563 */ |
552 if ( $menu_id && ( ! $update || ! is_object_in_term( $menu_item_db_id, 'nav_menu', (int) $menu->term_id ) ) ) { |
564 if ( $menu_id && ( ! $update || ! is_object_in_term( $menu_item_db_id, 'nav_menu', (int) $menu->term_id ) ) ) { |
553 $update_terms = wp_set_object_terms( $menu_item_db_id, array( $menu->term_id ), 'nav_menu' ); |
565 $update_terms = wp_set_object_terms( $menu_item_db_id, array( $menu->term_id ), 'nav_menu' ); |
554 if ( is_wp_error( $update_terms ) ) { |
566 if ( is_wp_error( $update_terms ) ) { |
555 return $update_terms; |
567 return $update_terms; |
556 } |
568 } |
560 $args['menu-item-object-id'] = $menu_item_db_id; |
572 $args['menu-item-object-id'] = $menu_item_db_id; |
561 $args['menu-item-object'] = 'custom'; |
573 $args['menu-item-object'] = 'custom'; |
562 } |
574 } |
563 |
575 |
564 $menu_item_db_id = (int) $menu_item_db_id; |
576 $menu_item_db_id = (int) $menu_item_db_id; |
|
577 |
|
578 // Reset invalid `menu_item_parent`. |
|
579 if ( (int) $args['menu-item-parent-id'] === $menu_item_db_id ) { |
|
580 $args['menu-item-parent-id'] = 0; |
|
581 } |
565 |
582 |
566 update_post_meta( $menu_item_db_id, '_menu_item_type', sanitize_key( $args['menu-item-type'] ) ); |
583 update_post_meta( $menu_item_db_id, '_menu_item_type', sanitize_key( $args['menu-item-type'] ) ); |
567 update_post_meta( $menu_item_db_id, '_menu_item_menu_item_parent', (string) ( (int) $args['menu-item-parent-id'] ) ); |
584 update_post_meta( $menu_item_db_id, '_menu_item_menu_item_parent', (string) ( (int) $args['menu-item-parent-id'] ) ); |
568 update_post_meta( $menu_item_db_id, '_menu_item_object_id', (string) ( (int) $args['menu-item-object-id'] ) ); |
585 update_post_meta( $menu_item_db_id, '_menu_item_object_id', (string) ( (int) $args['menu-item-object-id'] ) ); |
569 update_post_meta( $menu_item_db_id, '_menu_item_object', sanitize_key( $args['menu-item-object'] ) ); |
586 update_post_meta( $menu_item_db_id, '_menu_item_object', sanitize_key( $args['menu-item-object'] ) ); |
571 |
588 |
572 $args['menu-item-classes'] = array_map( 'sanitize_html_class', explode( ' ', $args['menu-item-classes'] ) ); |
589 $args['menu-item-classes'] = array_map( 'sanitize_html_class', explode( ' ', $args['menu-item-classes'] ) ); |
573 $args['menu-item-xfn'] = implode( ' ', array_map( 'sanitize_html_class', explode( ' ', $args['menu-item-xfn'] ) ) ); |
590 $args['menu-item-xfn'] = implode( ' ', array_map( 'sanitize_html_class', explode( ' ', $args['menu-item-xfn'] ) ) ); |
574 update_post_meta( $menu_item_db_id, '_menu_item_classes', $args['menu-item-classes'] ); |
591 update_post_meta( $menu_item_db_id, '_menu_item_classes', $args['menu-item-classes'] ); |
575 update_post_meta( $menu_item_db_id, '_menu_item_xfn', $args['menu-item-xfn'] ); |
592 update_post_meta( $menu_item_db_id, '_menu_item_xfn', $args['menu-item-xfn'] ); |
576 update_post_meta( $menu_item_db_id, '_menu_item_url', esc_url_raw( $args['menu-item-url'] ) ); |
593 update_post_meta( $menu_item_db_id, '_menu_item_url', sanitize_url( $args['menu-item-url'] ) ); |
577 |
594 |
578 if ( 0 == $menu_id ) { |
595 if ( 0 === $menu_id ) { |
579 update_post_meta( $menu_item_db_id, '_menu_item_orphaned', (string) time() ); |
596 update_post_meta( $menu_item_db_id, '_menu_item_orphaned', (string) time() ); |
580 } elseif ( get_post_meta( $menu_item_db_id, '_menu_item_orphaned' ) ) { |
597 } elseif ( get_post_meta( $menu_item_db_id, '_menu_item_orphaned' ) ) { |
581 delete_post_meta( $menu_item_db_id, '_menu_item_orphaned' ); |
598 delete_post_meta( $menu_item_db_id, '_menu_item_orphaned' ); |
582 } |
599 } |
583 |
600 |
667 * |
684 * |
668 * @param int|string|WP_Term $menu Menu ID, slug, name, or object. |
685 * @param int|string|WP_Term $menu Menu ID, slug, name, or object. |
669 * @param array $args { |
686 * @param array $args { |
670 * Optional. Arguments to pass to get_posts(). |
687 * Optional. Arguments to pass to get_posts(). |
671 * |
688 * |
672 * @type string $order How to order nav menu items as queried with get_posts(). Will be ignored |
689 * @type string $order How to order nav menu items as queried with get_posts(). |
673 * if 'output' is ARRAY_A. Default 'ASC'. |
690 * Will be ignored if 'output' is ARRAY_A. Default 'ASC'. |
674 * @type string $orderby Field to order menu items by as retrieved from get_posts(). Supply an orderby |
691 * @type string $orderby Field to order menu items by as retrieved from get_posts(). |
675 * field via 'output_key' to affect the output order of nav menu items. |
692 * Supply an orderby field via 'output_key' to affect the |
676 * Default 'menu_order'. |
693 * output order of nav menu items. Default 'menu_order'. |
677 * @type string $post_type Menu items post type. Default 'nav_menu_item'. |
694 * @type string $post_type Menu items post type. Default 'nav_menu_item'. |
678 * @type string $post_status Menu items post status. Default 'publish'. |
695 * @type string $post_status Menu items post status. Default 'publish'. |
679 * @type string $output How to order outputted menu items. Default ARRAY_A. |
696 * @type string $output How to order outputted menu items. Default ARRAY_A. |
680 * @type string $output_key Key to use for ordering the actual menu items that get returned. Note that |
697 * @type string $output_key Key to use for ordering the actual menu items that get |
681 * that is not a get_posts() argument and will only affect output of menu items |
698 * returned. Note that that is not a get_posts() argument |
682 * processed in this function. Default 'menu_order'. |
699 * and will only affect output of menu items processed in |
683 * @type bool $nopaging Whether to retrieve all menu items (true) or paginate (false). Default true. |
700 * this function. Default 'menu_order'. |
|
701 * @type bool $nopaging Whether to retrieve all menu items (true) or paginate |
|
702 * (false). Default true. |
|
703 * @type bool $update_menu_item_cache Whether to update the menu item cache. Default true. |
684 * } |
704 * } |
685 * @return array|false Array of menu items, otherwise false. |
705 * @return array|false Array of menu items, otherwise false. |
686 */ |
706 */ |
687 function wp_get_nav_menu_items( $menu, $args = array() ) { |
707 function wp_get_nav_menu_items( $menu, $args = array() ) { |
688 $menu = wp_get_nav_menu_object( $menu ); |
708 $menu = wp_get_nav_menu_object( $menu ); |
689 |
709 |
690 if ( ! $menu ) { |
710 if ( ! $menu ) { |
691 return false; |
711 return false; |
692 } |
712 } |
693 |
713 |
694 static $fetched = array(); |
|
695 |
|
696 if ( ! taxonomy_exists( 'nav_menu' ) ) { |
714 if ( ! taxonomy_exists( 'nav_menu' ) ) { |
697 return false; |
715 return false; |
698 } |
716 } |
699 |
717 |
700 $defaults = array( |
718 $defaults = array( |
701 'order' => 'ASC', |
719 'order' => 'ASC', |
702 'orderby' => 'menu_order', |
720 'orderby' => 'menu_order', |
703 'post_type' => 'nav_menu_item', |
721 'post_type' => 'nav_menu_item', |
704 'post_status' => 'publish', |
722 'post_status' => 'publish', |
705 'output' => ARRAY_A, |
723 'output' => ARRAY_A, |
706 'output_key' => 'menu_order', |
724 'output_key' => 'menu_order', |
707 'nopaging' => true, |
725 'nopaging' => true, |
708 'tax_query' => array( |
726 'update_menu_item_cache' => true, |
|
727 'tax_query' => array( |
709 array( |
728 array( |
710 'taxonomy' => 'nav_menu', |
729 'taxonomy' => 'nav_menu', |
711 'field' => 'term_taxonomy_id', |
730 'field' => 'term_taxonomy_id', |
712 'terms' => $menu->term_taxonomy_id, |
731 'terms' => $menu->term_taxonomy_id, |
713 ), |
732 ), |
718 $items = get_posts( $args ); |
737 $items = get_posts( $args ); |
719 } else { |
738 } else { |
720 $items = array(); |
739 $items = array(); |
721 } |
740 } |
722 |
741 |
723 // Prime posts and terms caches. |
|
724 if ( empty( $fetched[ $menu->term_id ] ) ) { |
|
725 $fetched[ $menu->term_id ] = true; |
|
726 $post_ids = array(); |
|
727 $term_ids = array(); |
|
728 foreach ( $items as $item ) { |
|
729 $object_id = get_post_meta( $item->ID, '_menu_item_object_id', true ); |
|
730 $type = get_post_meta( $item->ID, '_menu_item_type', true ); |
|
731 |
|
732 if ( 'post_type' === $type ) { |
|
733 $post_ids[] = (int) $object_id; |
|
734 } elseif ( 'taxonomy' === $type ) { |
|
735 $term_ids[] = (int) $object_id; |
|
736 } |
|
737 } |
|
738 |
|
739 if ( ! empty( $post_ids ) ) { |
|
740 _prime_post_caches( $post_ids, false ); |
|
741 } |
|
742 unset( $post_ids ); |
|
743 |
|
744 if ( ! empty( $term_ids ) ) { |
|
745 _prime_term_caches( $term_ids ); |
|
746 } |
|
747 unset( $term_ids ); |
|
748 } |
|
749 |
|
750 $items = array_map( 'wp_setup_nav_menu_item', $items ); |
742 $items = array_map( 'wp_setup_nav_menu_item', $items ); |
751 |
743 |
752 if ( ! is_admin() ) { // Remove invalid items only on front end. |
744 if ( ! is_admin() ) { // Remove invalid items only on front end. |
753 $items = array_filter( $items, '_is_valid_nav_menu_item' ); |
745 $items = array_filter( $items, '_is_valid_nav_menu_item' ); |
754 } |
746 } |
776 * @param array $items An array of menu item post objects. |
768 * @param array $items An array of menu item post objects. |
777 * @param object $menu The menu object. |
769 * @param object $menu The menu object. |
778 * @param array $args An array of arguments used to retrieve menu item objects. |
770 * @param array $args An array of arguments used to retrieve menu item objects. |
779 */ |
771 */ |
780 return apply_filters( 'wp_get_nav_menu_items', $items, $menu, $args ); |
772 return apply_filters( 'wp_get_nav_menu_items', $items, $menu, $args ); |
|
773 } |
|
774 |
|
775 /** |
|
776 * Updates post and term caches for all linked objects for a list of menu items. |
|
777 * |
|
778 * @since 6.1.0 |
|
779 * |
|
780 * @param WP_Post[] $menu_items Array of menu item post objects. |
|
781 */ |
|
782 function update_menu_item_cache( $menu_items ) { |
|
783 $post_ids = array(); |
|
784 $term_ids = array(); |
|
785 |
|
786 foreach ( $menu_items as $menu_item ) { |
|
787 if ( 'nav_menu_item' !== $menu_item->post_type ) { |
|
788 continue; |
|
789 } |
|
790 |
|
791 $object_id = get_post_meta( $menu_item->ID, '_menu_item_object_id', true ); |
|
792 $type = get_post_meta( $menu_item->ID, '_menu_item_type', true ); |
|
793 |
|
794 if ( 'post_type' === $type ) { |
|
795 $post_ids[] = (int) $object_id; |
|
796 } elseif ( 'taxonomy' === $type ) { |
|
797 $term_ids[] = (int) $object_id; |
|
798 } |
|
799 } |
|
800 |
|
801 if ( ! empty( $post_ids ) ) { |
|
802 _prime_post_caches( $post_ids, false ); |
|
803 } |
|
804 |
|
805 if ( ! empty( $term_ids ) ) { |
|
806 _prime_term_caches( $term_ids ); |
|
807 } |
781 } |
808 } |
782 |
809 |
783 /** |
810 /** |
784 * Decorates a menu item object with the shared navigation menu item properties. |
811 * Decorates a menu item object with the shared navigation menu item properties. |
785 * |
812 * |
806 * |
833 * |
807 * @param object $menu_item The menu item to modify. |
834 * @param object $menu_item The menu item to modify. |
808 * @return object The menu item with standard menu item properties. |
835 * @return object The menu item with standard menu item properties. |
809 */ |
836 */ |
810 function wp_setup_nav_menu_item( $menu_item ) { |
837 function wp_setup_nav_menu_item( $menu_item ) { |
|
838 |
|
839 /** |
|
840 * Filters whether to short-circuit the wp_setup_nav_menu_item() output. |
|
841 * |
|
842 * Returning a non-null value from the filter will short-circuit wp_setup_nav_menu_item(), |
|
843 * returning that value instead. |
|
844 * |
|
845 * @since 6.3.0 |
|
846 * |
|
847 * @param object|null $modified_menu_item Modified menu item. Default null. |
|
848 * @param object $menu_item The menu item to modify. |
|
849 */ |
|
850 $pre_menu_item = apply_filters( 'pre_wp_setup_nav_menu_item', null, $menu_item ); |
|
851 |
|
852 if ( null !== $pre_menu_item ) { |
|
853 return $pre_menu_item; |
|
854 } |
|
855 |
811 if ( isset( $menu_item->post_type ) ) { |
856 if ( isset( $menu_item->post_type ) ) { |
812 if ( 'nav_menu_item' === $menu_item->post_type ) { |
857 if ( 'nav_menu_item' === $menu_item->post_type ) { |
813 $menu_item->db_id = (int) $menu_item->ID; |
858 $menu_item->db_id = (int) $menu_item->ID; |
814 $menu_item->menu_item_parent = ! isset( $menu_item->menu_item_parent ) ? get_post_meta( $menu_item->ID, '_menu_item_menu_item_parent', true ) : $menu_item->menu_item_parent; |
859 $menu_item->menu_item_parent = ! isset( $menu_item->menu_item_parent ) ? get_post_meta( $menu_item->ID, '_menu_item_menu_item_parent', true ) : $menu_item->menu_item_parent; |
815 $menu_item->object_id = ! isset( $menu_item->object_id ) ? get_post_meta( $menu_item->ID, '_menu_item_object_id', true ) : $menu_item->object_id; |
860 $menu_item->object_id = ! isset( $menu_item->object_id ) ? get_post_meta( $menu_item->ID, '_menu_item_object_id', true ) : $menu_item->object_id; |
1001 */ |
1046 */ |
1002 function wp_get_associated_nav_menu_items( $object_id = 0, $object_type = 'post_type', $taxonomy = '' ) { |
1047 function wp_get_associated_nav_menu_items( $object_id = 0, $object_type = 'post_type', $taxonomy = '' ) { |
1003 $object_id = (int) $object_id; |
1048 $object_id = (int) $object_id; |
1004 $menu_item_ids = array(); |
1049 $menu_item_ids = array(); |
1005 |
1050 |
1006 $query = new WP_Query; |
1051 $query = new WP_Query(); |
1007 $menu_items = $query->query( |
1052 $menu_items = $query->query( |
1008 array( |
1053 array( |
1009 'meta_key' => '_menu_item_object_id', |
1054 'meta_key' => '_menu_item_object_id', |
1010 'meta_value' => $object_id, |
1055 'meta_value' => $object_id, |
1011 'post_status' => 'any', |
1056 'post_status' => 'any', |
1264 } // End foreach ( $slug_group as $slug ). |
1309 } // End foreach ( $slug_group as $slug ). |
1265 } // End foreach ( $common_slug_groups as $slug_group ). |
1310 } // End foreach ( $common_slug_groups as $slug_group ). |
1266 |
1311 |
1267 return $new_nav_menu_locations; |
1312 return $new_nav_menu_locations; |
1268 } |
1313 } |
|
1314 |
|
1315 /** |
|
1316 * Prevents menu items from being their own parent. |
|
1317 * |
|
1318 * Resets menu_item_parent to 0 when the parent is set to the item itself. |
|
1319 * For use before saving `_menu_item_menu_item_parent` in nav-menus.php. |
|
1320 * |
|
1321 * @since 6.2.0 |
|
1322 * @access private |
|
1323 * |
|
1324 * @param array $menu_item_data The menu item data array. |
|
1325 * @return array The menu item data with reset menu_item_parent. |
|
1326 */ |
|
1327 function _wp_reset_invalid_menu_item_parent( $menu_item_data ) { |
|
1328 if ( ! is_array( $menu_item_data ) ) { |
|
1329 return $menu_item_data; |
|
1330 } |
|
1331 |
|
1332 if ( |
|
1333 ! empty( $menu_item_data['ID'] ) && |
|
1334 ! empty( $menu_item_data['menu_item_parent'] ) && |
|
1335 (int) $menu_item_data['ID'] === (int) $menu_item_data['menu_item_parent'] |
|
1336 ) { |
|
1337 $menu_item_data['menu_item_parent'] = 0; |
|
1338 } |
|
1339 |
|
1340 return $menu_item_data; |
|
1341 } |