Skip to content

Commit

Permalink
Navigation: Allow Search block to be added alongside links
Browse files Browse the repository at this point in the history
  • Loading branch information
noisysocks committed Jun 19, 2020
1 parent cbef072 commit 3d04332
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 17 deletions.
55 changes: 54 additions & 1 deletion lib/class-wp-rest-menu-items-controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@ protected function prepare_item_for_database( $request ) {
'menu-item-db-id' => $menu_item_db_id,
'menu-item-object-id' => $menu_item_obj->object_id,
'menu-item-object' => $menu_item_obj->object,
'menu-item-content' => $menu_item_obj->menu_item_content,
'menu-item-parent-id' => $menu_item_obj->menu_item_parent,
'menu-item-position' => $position,
'menu-item-title' => $menu_item_obj->title,
Expand All @@ -331,6 +332,7 @@ protected function prepare_item_for_database( $request ) {
'menu-item-db-id' => 0,
'menu-item-object-id' => 0,
'menu-item-object' => '',
'menu-item-content' => '',
'menu-item-parent-id' => 0,
'menu-item-position' => 0,
'menu-item-type' => 'custom',
Expand Down Expand Up @@ -374,6 +376,14 @@ protected function prepare_item_for_database( $request ) {
}
}

if ( ! empty( $schema['properties']['content'] ) && isset( $request['content'] ) ) {
if ( is_string( $request['content'] ) ) {
$prepared_nav_item['menu-item-content'] = $request['content'];
} elseif ( isset( $request['content']['raw'] ) ) {
$prepared_nav_item['menu-item-content'] = $request['content']['raw'];
}
}

$taxonomy = get_taxonomy( 'nav_menu' );
$base = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name;
// If menus submitted, cast to int.
Expand Down Expand Up @@ -596,6 +606,20 @@ public function prepare_item_for_response( $post, $request ) {
$data['object_id'] = absint( $menu_item->object_id );
}

if ( rest_is_field_included( 'content', $fields ) ) {
$data['content'] = array();
}
if ( rest_is_field_included( 'content.raw', $fields ) ) {
$data['content']['raw'] = $menu_item->content;
}
if ( rest_is_field_included( 'content.rendered', $fields ) ) {
/** This filter is documented in wp-includes/post-template.php */
$data['content']['rendered'] = apply_filters( 'the_content', $menu_item->content );
}
if ( rest_is_field_included( 'content.block_version', $fields ) ) {
$data['content']['block_version'] = block_version( $menu_item->content );
}

if ( in_array( 'parent', $fields, true ) ) {
// Same as post_parent, expose as integer.
$data['parent'] = absint( $menu_item->menu_item_parent );
Expand Down Expand Up @@ -787,7 +811,7 @@ public function get_item_schema() {
$schema['properties']['type'] = array(
'description' => __( 'The family of objects originally represented, such as "post_type" or "taxonomy".', 'gutenberg' ),
'type' => 'string',
'enum' => array( 'taxonomy', 'post_type', 'post_type_archive', 'custom' ),
'enum' => array( 'taxonomy', 'post_type', 'post_type_archive', 'custom', 'html' ),
'context' => array( 'view', 'edit', 'embed' ),
'default' => 'custom',
);
Expand Down Expand Up @@ -861,6 +885,35 @@ public function get_item_schema() {
'default' => 0,
);

$schema['properties']['content'] = array(
'description' => __( 'HTML content to display for this menu item. May contain blocks.', 'gutenberg' ),
'context' => array( 'view', 'edit', 'embed' ),
'type' => 'object',
'arg_options' => array(
'sanitize_callback' => null, // Note: sanitization implemented in self::prepare_item_for_database().
'validate_callback' => null, // Note: validation implemented in self::prepare_item_for_database().
),
'properties' => array(
'raw' => array(
'description' => __( 'HTML content, as it exists in the database.', 'gutenberg' ),
'type' => 'string',
'context' => array( 'edit' ),
),
'rendered' => array(
'description' => __( 'HTML content, transformed for display.', 'gutenberg' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
'readonly' => true,
),
'block_version' => array(
'description' => __( 'Version of the block format used in the HTML content.', 'gutenberg' ),
'type' => 'integer',
'context' => array( 'edit' ),
'readonly' => true,
),
),
);

$schema['properties']['target'] = array(
'description' => __( 'The target attribute of the link element for this menu item.', 'gutenberg' ),
'type' => 'string',
Expand Down
60 changes: 55 additions & 5 deletions lib/compat.php
Original file line number Diff line number Diff line change
Expand Up @@ -415,18 +415,20 @@ function gutenberg_render_block_with_assigned_block_context( $pre_render, $parse
$parsed_block = apply_filters( 'render_block_data', $parsed_block, $source_block );

$context = array(
'postId' => $post->ID,
'query' => array( 'categoryIds' => array() ),
);

if ( isset( $post ) ) {
$context['postId'] = $post->ID;

/*
* The `postType` context is largely unnecessary server-side, since the
* ID is usually sufficient on its own. That being said, since a block's
* manifest is expected to be shared between the server and the client,
* it should be included to consistently fulfill the expectation.
*/
'postType' => $post->post_type,

'query' => array( 'categoryIds' => array() ),
);
$context['postType'] = $post->post_type;
}

if ( isset( $wp_query->tax_query->queried_terms['category'] ) ) {
foreach ( $wp_query->tax_query->queried_terms['category']['terms'] as $category_slug_or_id ) {
Expand Down Expand Up @@ -461,3 +463,51 @@ function gutenberg_render_block_with_assigned_block_context( $pre_render, $parse
* @see WP_Block::render
*/
remove_action( 'enqueue_block_assets', 'wp_enqueue_registered_block_scripts_and_styles' );

function gutenberg_update_nav_menu_item_content( $menu_id, $menu_item_db_id, $args ) {
global $wp_customize;

// Support setting content in customize_save admin-ajax.php requests by
// grabbing the unsanitized $_POST values.
if ( isset( $wp_customize ) ) {
$values = $wp_customize->unsanitized_post_values();
if ( isset( $values[ "nav_menu_item[$menu_item_db_id]" ]['content'] ) ) {
if ( is_string( $values[ "nav_menu_item[$menu_item_db_id]" ]['content'] ) ) {
$args['menu-item-content'] = $values[ "nav_menu_item[$menu_item_db_id]" ]['content'];
} elseif ( isset( $values[ "nav_menu_item[$menu_item_db_id]" ]['content']['raw'] ) ) {
$args['menu-item-content'] = $values[ "nav_menu_item[$menu_item_db_id]" ]['content']['raw'];
}
}
}

$defaults = array(
'menu-item-content' => '',
);

$args = wp_parse_args( $args, $defaults );

update_post_meta( $menu_item_db_id, '_menu_item_content', $args['menu-item-content'] );
}
add_action( 'wp_update_nav_menu_item', 'gutenberg_update_nav_menu_item_content', 10, 3 );

function gutenberg_setup_html_nav_menu_item( $menu_item ) {
if ( 'html' === $menu_item->type ) {
$menu_item->type_label = __( 'HTML', 'gutenberg' );
$menu_item->content = ! isset( $menu_item->content ) ? get_post_meta( $menu_item->db_id, '_menu_item_content', true ) : $menu_item->content;
}

return $menu_item;
}
add_filter( 'wp_setup_nav_menu_item', 'gutenberg_setup_html_nav_menu_item' );

function gutenberg_output_html_nav_menu_item( $item_output, $item, $depth, $args ) {
if ( 'html' === $item->type ) {
$item_output = $args->before;
/** This filter is documented in wp-includes/post-template.php */
$item_output .= apply_filters( 'the_content', $item->content );
$item_output .= $args->after;
}

return $item_output;
}
add_filter( 'walker_nav_menu_start_el', 'gutenberg_output_html_nav_menu_item', 10, 4 );
5 changes: 4 additions & 1 deletion packages/block-library/src/navigation/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,10 @@ function Navigation( {
>
<InnerBlocks
ref={ ref }
allowedBlocks={ [ 'core/navigation-link' ] }
allowedBlocks={ [
'core/navigation-link',
'core/search',
] }
renderAppender={
( isImmediateParentOfSelectedBlock &&
! selectedBlockHasDescendants ) ||
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { useDispatch, useSelect } from '@wordpress/data';
import { useEffect, useState } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import apiFetch from '@wordpress/api-fetch';
import { serialize } from '@wordpress/blocks';

/**
* Internal dependencies
Expand Down Expand Up @@ -139,11 +140,26 @@ function computeCustomizedAttribute( blocks, menuId, menuItemsRef ) {

function linkBlockToRequestItem( block, parentId, position ) {
const menuItem = omit( getMenuItemForBlock( block ), 'menus', 'meta' );

let attributes;

if ( block.name === 'core/navigation-link' ) {
attributes = {
type: 'custom',
title: block.attributes?.label,
url: block.attributes.url,
};
} else {
attributes = {
type: 'html',
content: serialize( block ),
};
}

return {
...menuItem,
...attributes,
position,
title: block.attributes?.label,
url: block.attributes.url,
original_title: '',
classes: ( menuItem.classes || [] ).join( ' ' ),
xfn: ( menuItem.xfn || [] ).join( ' ' ),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { keyBy, groupBy, sortBy } from 'lodash';
/**
* WordPress dependencies
*/
import { createBlock } from '@wordpress/blocks';
import { createBlock, parse } from '@wordpress/blocks';
import { useState, useRef, useEffect } from '@wordpress/element';

/**
Expand Down Expand Up @@ -88,19 +88,39 @@ function menuItemToLinkBlock(
innerBlocks = [],
existingBlock = null
) {
const attributes = {
label: menuItem.title.rendered,
url: menuItem.url,
};
let linkBlock;

if ( menuItem.type === 'html' ) {
const [ parsedBlock ] = parse( menuItem.content.raw ); // TODO: Handle multiple blocks?

if ( parsedBlock ) {
linkBlock = parsedBlock;
} else {
linkBlock = createBlock( 'core/freeform', {
originalContent: menuItem.content.raw,
} );
}
} else {
linkBlock = createBlock(
'core/navigation-link',
{
label: menuItem.title.rendered,
url: menuItem.url,
},
innerBlocks
);
}

if ( existingBlock ) {
return {
...existingBlock,
attributes,
innerBlocks,
name: linkBlock.name,
attributes: linkBlock.attributes,
innerBlocks: linkBlock.innerBlocks,
};
}
return createBlock( 'core/navigation-link', attributes, innerBlocks );

return linkBlock;
}

const mapBlocksByMenuId = ( blocks, menuItemsByClientId ) => {
Expand Down

0 comments on commit 3d04332

Please sign in to comment.