[ Index ]

PHP Cross Reference of WordPress

title

Body

[close]

/wp-includes/ -> navigation-areas.php (source)

   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  }


Generated: Mon Nov 29 01:00:03 2021 Cross-referenced by PHPXref 0.7.1