[ Index ] |
PHP Cross Reference of WordPress |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Block navigation areas functions. 4 * 5 * @package WordPress 6 */ 7 8 /** 9 * Registers the navigation areas supported by the current theme. The expected 10 * shape of the argument is: 11 * array( 12 * 'primary' => 'Primary', 13 * 'secondary' => 'Secondary', 14 * 'tertiary' => 'Tertiary', 15 * ) 16 * 17 * @since 5.9.0 18 * 19 * @param array $new_areas Supported navigation areas. 20 */ 21 function register_navigation_areas( $new_areas ) { 22 global $navigation_areas; 23 $navigation_areas = $new_areas; 24 } 25 26 /** 27 * Register the default navigation areas. 28 * 29 * @since 5.9.0 30 * @access private 31 */ 32 function _wp_register_default_navigation_areas() { 33 register_navigation_areas( 34 array( 35 'primary' => _x( 'Primary', 'navigation area' ), 36 'secondary' => _x( 'Secondary', 'navigation area' ), 37 'tertiary' => _x( 'Tertiary', 'navigation area' ), 38 ) 39 ); 40 } 41 42 /** 43 * Returns the available navigation areas. 44 * 45 * @since 5.9.0 46 * 47 * @return array Registered navigation areas. 48 */ 49 function get_navigation_areas() { 50 global $navigation_areas; 51 return $navigation_areas; 52 } 53 54 /** 55 * Migrates classic menus to a block-based navigation post on theme switch. 56 * Assigns the created navigation post to the corresponding navigation area. 57 * 58 * @since 5.9.0 59 * @access private 60 * 61 * @param string $new_name Name of the new theme. 62 * @param WP_Theme $new_theme New theme. 63 * @param WP_Theme $old_theme Old theme. 64 */ 65 function _wp_migrate_menu_to_navigation_post( $new_name, WP_Theme $new_theme, WP_Theme $old_theme ) { 66 // Do nothing when switching to a theme that does not support site editor. 67 if ( ! wp_is_block_template_theme() ) { 68 return; 69 } 70 71 // get_nav_menu_locations() calls get_theme_mod() which depends on the stylesheet option. 72 // At the same time, switch_theme runs only after the stylesheet option was updated to $new_theme. 73 // To retrieve theme mods of the old theme, the getter is hooked to get_option( 'stylesheet' ) so that we 74 // get the old theme, which causes the get_nav_menu_locations to get the locations of the old theme. 75 $get_old_theme_stylesheet = static function() use ( $old_theme ) { 76 return $old_theme->get_stylesheet(); 77 }; 78 add_filter( 'option_stylesheet', $get_old_theme_stylesheet ); 79 80 $locations = get_nav_menu_locations(); 81 $area_mapping = get_option( 'wp_navigation_areas', array() ); 82 83 foreach ( $locations as $location_name => $menu_id ) { 84 // Get the menu from the location, skipping if there is no 85 // menu or there was an error. 86 $menu = wp_get_nav_menu_object( $menu_id ); 87 if ( ! $menu || is_wp_error( $menu ) ) { 88 continue; 89 } 90 91 $menu_items = _wp_get_menu_items_at_location( $location_name ); 92 if ( empty( $menu_items ) ) { 93 continue; 94 } 95 96 $post_name = 'classic_menu_' . $menu_id; 97 98 // Get or create to avoid creating too many wp_navigation posts. 99 $query = new WP_Query; 100 $matching_posts = $query->query( 101 array( 102 'name' => $post_name, 103 'post_status' => 'publish', 104 'post_type' => 'wp_navigation', 105 'posts_per_page' => 1, 106 'fields' => 'ids', 107 ) 108 ); 109 110 if ( ! empty( $matching_posts ) ) { 111 $navigation_post_id = $matching_posts[0]; 112 } else { 113 $menu_items_by_parent_id = _wp_sort_menu_items_by_parent_id( $menu_items ); 114 $parsed_blocks = _wp_parse_blocks_from_menu_items( $menu_items_by_parent_id[0], $menu_items_by_parent_id ); 115 $post_data = array( 116 'post_type' => 'wp_navigation', 117 'post_title' => sprintf( 118 /* translators: %s: the name of the menu, e.g. "Main Menu". */ 119 __( 'Classic menu: %s' ), 120 $menu->name 121 ), 122 'post_name' => $post_name, 123 'post_content' => serialize_blocks( $parsed_blocks ), 124 'post_status' => 'publish', 125 ); 126 $navigation_post_id = wp_insert_post( $post_data, true ); 127 // If wp_insert_post fails *at any time*, then bail out of the 128 // entire migration attempt returning the WP_Error object. 129 if ( is_wp_error( $navigation_post_id ) ) { 130 return $navigation_post_id; 131 } 132 } 133 134 $area_mapping[ $location_name ] = $navigation_post_id; 135 } 136 remove_filter( 'option_stylesheet', $get_old_theme_stylesheet ); 137 138 update_option( 'wp_navigation_areas', $area_mapping ); 139 } 140 141 /** 142 * Returns the menu items for a WordPress menu location. 143 * 144 * @since 5.9.0 145 * @access private 146 * 147 * @param string $location The menu location. 148 * @return array Menu items for the location. 149 */ 150 function _wp_get_menu_items_at_location( $location ) { 151 if ( empty( $location ) ) { 152 return; 153 } 154 155 // Build menu data. The following approximates the code in `wp_nav_menu()`. 156 157 // Find the location in the list of locations, returning early if the 158 // location can't be found. 159 $locations = get_nav_menu_locations(); 160 if ( ! isset( $locations[ $location ] ) ) { 161 return; 162 } 163 164 // Get the menu from the location, returning early if there is no 165 // menu or there was an error. 166 $menu = wp_get_nav_menu_object( $locations[ $location ] ); 167 if ( ! $menu || is_wp_error( $menu ) ) { 168 return; 169 } 170 171 $menu_items = wp_get_nav_menu_items( $menu->term_id, array( 'update_post_term_cache' => false ) ); 172 _wp_menu_item_classes_by_context( $menu_items ); 173 174 return $menu_items; 175 } 176 177 /** 178 * Sorts a standard array of menu items into a nested structure keyed by the 179 * id of the parent menu. 180 * 181 * @since 5.9.0 182 * @access private 183 * 184 * @param array $menu_items Menu items to sort. 185 * @return array An array keyed by the id of the parent menu where each element 186 * is an array of menu items that belong to that parent. 187 */ 188 function _wp_sort_menu_items_by_parent_id( $menu_items ) { 189 $sorted_menu_items = array(); 190 foreach ( $menu_items as $menu_item ) { 191 $sorted_menu_items[ $menu_item->menu_order ] = $menu_item; 192 } 193 unset( $menu_items, $menu_item ); 194 195 $menu_items_by_parent_id = array(); 196 foreach ( $sorted_menu_items as $menu_item ) { 197 $menu_items_by_parent_id[ $menu_item->menu_item_parent ][] = $menu_item; 198 } 199 200 return $menu_items_by_parent_id; 201 } 202 203 /** 204 * Turns menu item data into a nested array of parsed blocks 205 * 206 * @since 5.9.0 207 * @access private 208 * 209 * @param array $menu_items An array of menu items that represent 210 * an individual level of a menu. 211 * @param array $menu_items_by_parent_id An array keyed by the id of the 212 * parent menu where each element is an 213 * array of menu items that belong to 214 * that parent. 215 * @return array An array of parsed block data. 216 */ 217 function _wp_parse_blocks_from_menu_items( $menu_items, $menu_items_by_parent_id ) { 218 if ( empty( $menu_items ) ) { 219 return array(); 220 } 221 222 $blocks = array(); 223 224 foreach ( $menu_items as $menu_item ) { 225 $class_name = ! empty( $menu_item->classes ) ? implode( ' ', (array) $menu_item->classes ) : null; 226 $id = ( null !== $menu_item->object_id && 'custom' !== $menu_item->object ) ? $menu_item->object_id : null; 227 $opens_in_new_tab = null !== $menu_item->target && '_blank' === $menu_item->target; 228 $rel = ( null !== $menu_item->xfn && '' !== $menu_item->xfn ) ? $menu_item->xfn : null; 229 $kind = null !== $menu_item->type ? str_replace( '_', '-', $menu_item->type ) : 'custom'; 230 231 $block = array( 232 'blockName' => isset( $menu_items_by_parent_id[ $menu_item->ID ] ) ? 'core/navigation-submenu' : 'core/navigation-link', 233 'attrs' => array( 234 'className' => $class_name, 235 'description' => $menu_item->description, 236 'id' => $id, 237 'kind' => $kind, 238 'label' => $menu_item->title, 239 'opensInNewTab' => $opens_in_new_tab, 240 'rel' => $rel, 241 'title' => $menu_item->attr_title, 242 'type' => $menu_item->object, 243 'url' => $menu_item->url, 244 ), 245 ); 246 247 if ( isset( $menu_items_by_parent_id[ $menu_item->ID ] ) ) { 248 $block['innerBlocks'] = _wp_parse_blocks_from_menu_items( 249 $menu_items_by_parent_id[ $menu_item->ID ], 250 $menu_items_by_parent_id 251 ); 252 } else { 253 $block['innerBlocks'] = array(); 254 } 255 256 $block['innerContent'] = array_map( 'serialize_block', $block['innerBlocks'] ); 257 258 $blocks[] = $block; 259 } 260 261 return $blocks; 262 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Mon Nov 29 01:00:03 2021 | Cross-referenced by PHPXref 0.7.1 |