WordPress.org

Make WordPress Core

Opened 3 years ago

Closed 11 months ago

Last modified 11 months ago

#42209 closed defect (bug) (fixed)

register_taxonomy with a non-sequential array index of post_types causes /wp-json/wp/v2/taxonomies to return an object not an array

Reported by: spectacula Owned by: TimothyBlynJacobs
Milestone: 5.3 Priority: normal
Severity: normal Version: 4.8.2
Component: REST API Keywords: has-unit-tests has-patch
Focuses: Cc:

Description

I logged this as an issue with Gutenberg yesterday but it seems the error if further up the chain.

https://github.com/WordPress/gutenberg/issues/3009

When using register_taxonomy for a taxonomy that is to be shown in REST and to more than one post type the post type array must be sequential and 0 indexed otherwise the REST request will return an object for types rather than an array. This came to my attention as a plug-in had popped out an entry from the middle of an array of post_types and left the array with a gap in its sequence.

Simple test

https://{domain}/wp-json/wp/v2/taxonomies/taxonomy_name/

This returns an object in types

<?php
register_taxonomy(
    'taxonomy_name',
    array( 0 => 'post', 2 => 'page' ),
    array( 'show_in_rest' => true )
);

This returns an array

<?php
register_taxonomy(
    'taxonomy_name',
    array( 0 => 'post', 1 => 'page' ),
    array( 'show_in_rest' => true )
);

Attachments (2)

42209.diff (1.5 KB) - added by birgire 3 years ago.
42209.2.diff (1.9 KB) - added by TimothyBlynJacobs 11 months ago.

Download all attachments as: .zip

Change History (15)

#1 @birgire
3 years ago

Welcome to trac and thanks for the ticket.

We can reproduce this with:

// output: {"0":"post","2":"page"}
$json = wp_json_encode( array( 0 => 'post', 2 => 'page' ) );
	
// output: ["post","page"]
$json = wp_json_encode( array( 0 => 'post', 1 => 'page' ) );

where wp_json_encode() is a wrapper of json_encode().

This seems to be an expected behavior for json_encode().

So you're suggesting to re-index it, to ensure the array output?

#2 @spectacula
3 years ago

The expected and documented output for that part of the REST API is an array and Guttenberg fails because it assumes an array but is given an object.

http://v2.wp-api.org/reference/taxonomies/#schema-types

So passing the post_types array through array_values() before it gets to json_encode() would have the desired effect. Array keys aren't needed within register_taxonomy() so anybody passing the output of get_post_types() will also see this problem.

@birgire
3 years ago

#3 @birgire
3 years ago

  • Keywords has-unit-tests has-patch added

42209.diff adds array_values() for the object type array in WP_Taxonomy::set_props().

Test included.

@spectacula Did you have something like this in mind?

#4 @spectacula
3 years ago

That seems apt and should get in nobody's way.

#5 @spectacula
22 months ago

I've run into this again today and was surprised to see it not fixed. A client wanted a certain taxonomy removed from a custom post type. This causes REST calls to the taxonomy to throw the wrong data type for types.
The taxonomy and post type are created by a plugin that's outside of our control so we'd rather not have to modify it and thus have to maintain it. The change isn't one that'd need to be fed back to the original plugin authors either as it's not a bug just a client preference.

Here's an example that achieves the same effect:

<?php
add_action( 'init', function() {
    register_taxonomy(
        'taxonomy_name',
        array( 'post', 'attachment', 'page' ),
        array( 'show_in_rest' => true )
    );

    unregister_taxonomy_for_object_type( 'taxonomy_name', 'attachment' );
} );

// Make request to https://{domain}/wp-json/wp/v2/taxonomies/taxonomy_name/
// "types":{"0":"post","2":"page"} instead of "types":["post","page"]

This ticket was mentioned in Slack in #core-restapi by timothybjacobs. View the logs.


11 months ago

#7 @kadamwhite
11 months ago

  • Milestone changed from Awaiting Review to 5.3
  • Owner set to timothybjacobs
  • Status changed from new to assigned

Assigning to @timothybjacobs after scrub in REST API slack channel. He's noted that an array_values call within the REST API controller may be safer.

Provisionally accepting for 5.3.

#8 @TimothyBlynJacobs
11 months ago

Added a patch to use array_values when preparing the taxonomy for response.

#9 @TimothyBlynJacobs
11 months ago

  • Owner changed from timothybjacobs to TimothyBlynJacobs

This ticket was mentioned in Slack in #core-restapi by timothybjacobs. View the logs.


11 months ago

#11 @kadamwhite
11 months ago

  • Resolution set to fixed
  • Status changed from assigned to closed

In 45813:

REST API: Always return post types list in taxonomies endpoint response as an array.

Prevents a non-sequential post type array such as [ 0 => 'post', 2 => 'page' ] from being improperly converted to an object in the taxonomy endpoint's response JSON.

Props TimothyBlynJacobs, birgire, spectacula.
Fixes #42209.

#12 @birgire
11 months ago

Thanks @kadamwhite - I just noticed a missing @ticket 42209 annotation on the test method. I think we should add it.

#13 @kadamwhite
11 months ago

In 45815:

REST API: Add @ticket annotation to test from [45813].

Props birgire.
See #42209.

Note: See TracTickets for help on using tickets.