WP_REST_Menu_Items_Controller::prepare_item_for_database( WP_REST_Request $request ): object|WP_Error

In this article

Prepares a single post for create or update.

Parameters

$requestWP_REST_Requestrequired
Request object.

Return

object|WP_Error

Source

protected function prepare_item_for_database( $request ) {
	$menu_item_db_id = $request['id'];
	$menu_item_obj   = $this->get_nav_menu_item( $menu_item_db_id );
	// Need to persist the menu item data. See https://core.trac.wordpress.org/ticket/28138
	if ( ! is_wp_error( $menu_item_obj ) ) {
		// Correct the menu position if this was the first item. See https://core.trac.wordpress.org/ticket/28140
		$position = ( 0 === $menu_item_obj->menu_order ) ? 1 : $menu_item_obj->menu_order;

		$prepared_nav_item = array(
			'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-parent-id'   => $menu_item_obj->menu_item_parent,
			'menu-item-position'    => $position,
			'menu-item-type'        => $menu_item_obj->type,
			'menu-item-title'       => $menu_item_obj->title,
			'menu-item-url'         => $menu_item_obj->url,
			'menu-item-description' => $menu_item_obj->description,
			'menu-item-attr-title'  => $menu_item_obj->attr_title,
			'menu-item-target'      => $menu_item_obj->target,
			'menu-item-classes'     => $menu_item_obj->classes,
			// Stored in the database as a string.
			'menu-item-xfn'         => explode( ' ', $menu_item_obj->xfn ),
			'menu-item-status'      => $menu_item_obj->post_status,
			'menu-id'               => $this->get_menu_id( $menu_item_db_id ),
		);
	} else {
		$prepared_nav_item = array(
			'menu-id'               => 0,
			'menu-item-db-id'       => 0,
			'menu-item-object-id'   => 0,
			'menu-item-object'      => '',
			'menu-item-parent-id'   => 0,
			'menu-item-position'    => 1,
			'menu-item-type'        => 'custom',
			'menu-item-title'       => '',
			'menu-item-url'         => '',
			'menu-item-description' => '',
			'menu-item-attr-title'  => '',
			'menu-item-target'      => '',
			'menu-item-classes'     => array(),
			'menu-item-xfn'         => array(),
			'menu-item-status'      => 'publish',
		);
	}

	$mapping = array(
		'menu-item-db-id'       => 'id',
		'menu-item-object-id'   => 'object_id',
		'menu-item-object'      => 'object',
		'menu-item-parent-id'   => 'parent',
		'menu-item-position'    => 'menu_order',
		'menu-item-type'        => 'type',
		'menu-item-url'         => 'url',
		'menu-item-description' => 'description',
		'menu-item-attr-title'  => 'attr_title',
		'menu-item-target'      => 'target',
		'menu-item-classes'     => 'classes',
		'menu-item-xfn'         => 'xfn',
		'menu-item-status'      => 'status',
	);

	$schema = $this->get_item_schema();

	foreach ( $mapping as $original => $api_request ) {
		if ( isset( $request[ $api_request ] ) ) {
			$prepared_nav_item[ $original ] = $request[ $api_request ];
		}
	}

	$taxonomy = get_taxonomy( 'nav_menu' );
	$base     = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name;
	// If menus submitted, cast to int.
	if ( ! empty( $request[ $base ] ) ) {
		$prepared_nav_item['menu-id'] = absint( $request[ $base ] );
	}

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

	$error = new WP_Error();

	// Check if object id exists before saving.
	if ( ! $prepared_nav_item['menu-item-object'] ) {
		// If taxonomy, check if term exists.
		if ( 'taxonomy' === $prepared_nav_item['menu-item-type'] ) {
			$original = get_term( absint( $prepared_nav_item['menu-item-object-id'] ) );
			if ( empty( $original ) || is_wp_error( $original ) ) {
				$error->add( 'rest_term_invalid_id', __( 'Invalid term ID.' ), array( 'status' => 400 ) );
			} else {
				$prepared_nav_item['menu-item-object'] = get_term_field( 'taxonomy', $original );
			}
			// If post, check if post object exists.
		} elseif ( 'post_type' === $prepared_nav_item['menu-item-type'] ) {
			$original = get_post( absint( $prepared_nav_item['menu-item-object-id'] ) );
			if ( empty( $original ) ) {
				$error->add( 'rest_post_invalid_id', __( 'Invalid post ID.' ), array( 'status' => 400 ) );
			} else {
				$prepared_nav_item['menu-item-object'] = get_post_type( $original );
			}
		}
	}

	// If post type archive, check if post type exists.
	if ( 'post_type_archive' === $prepared_nav_item['menu-item-type'] ) {
		$post_type = $prepared_nav_item['menu-item-object'] ? $prepared_nav_item['menu-item-object'] : false;
		$original  = get_post_type_object( $post_type );
		if ( ! $original ) {
			$error->add( 'rest_post_invalid_type', __( 'Invalid post type.' ), array( 'status' => 400 ) );
		}
	}

	// Check if menu item is type custom, then title and url are required.
	if ( 'custom' === $prepared_nav_item['menu-item-type'] ) {
		if ( '' === $prepared_nav_item['menu-item-title'] ) {
			$error->add( 'rest_title_required', __( 'The title is required when using a custom menu item type.' ), array( 'status' => 400 ) );
		}
		if ( empty( $prepared_nav_item['menu-item-url'] ) ) {
			$error->add( 'rest_url_required', __( 'The url is required when using a custom menu item type.' ), array( 'status' => 400 ) );
		}
	}

	if ( $error->has_errors() ) {
		return $error;
	}

	// The xfn and classes properties are arrays, but passed to wp_update_nav_menu_item as a string.
	foreach ( array( 'menu-item-xfn', 'menu-item-classes' ) as $key ) {
		$prepared_nav_item[ $key ] = implode( ' ', $prepared_nav_item[ $key ] );
	}

	// Only draft / publish are valid post status for menu items.
	if ( 'publish' !== $prepared_nav_item['menu-item-status'] ) {
		$prepared_nav_item['menu-item-status'] = 'draft';
	}

	$prepared_nav_item = (object) $prepared_nav_item;

	/**
	 * Filters a menu item before it is inserted via the REST API.
	 *
	 * @since 5.9.0
	 *
	 * @param object          $prepared_nav_item An object representing a single menu item prepared
	 *                                           for inserting or updating the database.
	 * @param WP_REST_Request $request           Request object.
	 */
	return apply_filters( 'rest_pre_insert_nav_menu_item', $prepared_nav_item, $request );
}

Hooks

apply_filters( ‘rest_pre_insert_nav_menu_item’, object $prepared_nav_item, WP_REST_Request $request )

Filters a menu item before it is inserted via the REST API.

Changelog

VersionDescription
5.9.0Introduced.

User Contributed Notes

You must log in before being able to contribute a note or feedback.