Skip to content

Instantly share code, notes, and snippets.

@kadamwhite
Last active August 29, 2015 14:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kadamwhite/e941506b6cf8c9cce263 to your computer and use it in GitHub Desktop.
Save kadamwhite/e941506b6cf8c9cce263 to your computer and use it in GitHub Desktop.
Proposed solution for embedding custom types into taxonomies
diff --git a/lib/class-wp-json-posts.php b/lib/class-wp-json-posts.php
index 941c796..a06ed0f 100644
--- a/lib/class-wp-json-posts.php
+++ b/lib/class-wp-json-posts.php
@@ -519,9 +519,10 @@ class WP_JSON_Posts {
*
* @param string|object $type Type name, or type object (internal use)
* @param boolean $_in_collection Is this in a collection? (internal use)
+ * @param boolean $_in_taxonomy Is this request being added to a taxonomy record? (internal use)
* @return array Post type data
*/
- public function get_post_type( $type, $_in_collection = false ) {
+ public function get_post_type( $type, $_in_collection = false, $_in_taxonomy = false ) {
if ( ! is_object( $type ) )
$type = get_post_type_object($type);
@@ -542,7 +543,7 @@ class WP_JSON_Posts {
),
);
- if ( $_in_collection )
+ if ( $_in_collection || $_in_taxonomy )
$data['meta']['links']['self'] = json_url( '/posts/types/' . $type->name );
else
$data['meta']['links']['collection'] = json_url( '/posts/types' );
@@ -554,7 +555,7 @@ class WP_JSON_Posts {
$data['meta']['links']['archives'] = json_url( add_query_arg( 'type', $type->name, '/posts' ) );
}
- return apply_filters( 'json_post_type_data', $data, $type );
+ return apply_filters( 'json_post_type_data', $data, $type, $_in_taxonomy );
}
/**
@@ -1090,6 +1091,22 @@ class WP_JSON_Posts {
}
/**
+ * Embed post type data into taxonomy data
+ *
+ * @uses self::get_post_type()
+ * @param array $data Taxonomy data
+ * @param array $taxonomy Internal taxonomy data
+ * @return array Filtered data
+ */
+ public function add_post_type_data( $data, $taxonomy ) {
+ foreach( $taxonomy->object_type as $type ) {
+ $data['types'][ $type ] = $this->get_post_type( $type, false, true );
+ }
+
+ return $data;
+ }
+
+ /**
* Helper method for {@see new_post} and {@see edit_post}, containing shared logic.
*
* @since 3.4.0
diff --git a/lib/class-wp-json-taxonomies.php b/lib/class-wp-json-taxonomies.php
index b05ca9e..cc9b0ac 100644
--- a/lib/class-wp-json-taxonomies.php
+++ b/lib/class-wp-json-taxonomies.php
@@ -134,7 +134,7 @@ class WP_JSON_Taxonomies {
),
);
- return apply_filters( 'json_prepare_taxonomy', $data );
+ return apply_filters( 'json_prepare_taxonomy', $data, $taxonomy );
}
/**
@@ -142,10 +142,13 @@ class WP_JSON_Taxonomies {
*
* @param array $data Type data
* @param array $post Internal type data
+ * @param boolean $_in_taxonomy The record being filtered is a taxonomy object (internal use)
* @return array Filtered data
*/
- public function add_taxonomy_data( $data, $type ) {
- $data['taxonomies'] = $this->get_taxonomies( $type->name );
+ public function add_taxonomy_data( $data, $type, $_in_taxonomy = false ) {
+ if ( ! $_in_taxonomy ) {
+ $data['taxonomies'] = $this->get_taxonomies( $type->name );
+ }
return $data;
}
diff --git a/plugin.php b/plugin.php
index 3571b04..82067b3 100644
--- a/plugin.php
+++ b/plugin.php
@@ -75,6 +75,7 @@ function json_api_default_filters($server) {
// Posts
$wp_json_posts = new WP_JSON_Posts($server);
add_filter( 'json_endpoints', array( $wp_json_posts, 'register_routes' ), 0 );
+ add_filter( 'json_prepare_taxonomy', array( $wp_json_posts, 'add_post_type_data' ), 10, 2 );
// Users
$wp_json_users = new WP_JSON_Users($server);
@@ -97,7 +98,7 @@ function json_api_default_filters($server) {
// Posts
$wp_json_taxonomies = new WP_JSON_Taxonomies($server);
add_filter( 'json_endpoints', array( $wp_json_taxonomies, 'register_routes' ), 2 );
- add_filter( 'json_post_type_data', array( $wp_json_taxonomies, 'add_taxonomy_data' ), 10, 2 );
+ add_filter( 'json_post_type_data', array( $wp_json_taxonomies, 'add_taxonomy_data' ), 10, 3 );
add_filter( 'json_prepare_post', array( $wp_json_taxonomies, 'add_term_data' ), 10, 3 );
}
add_action( 'wp_json_server_before_serve', 'json_api_default_filters', 10, 1 );
diff --git a/tests/test_json_taxonomies.php b/tests/test_json_taxonomies.php
index 4f8acd9..202d9d5 100644
--- a/tests/test_json_taxonomies.php
+++ b/tests/test_json_taxonomies.php
@@ -126,4 +126,18 @@ class WP_Test_JSON_Taxonomies extends WP_UnitTestCase {
$this->assertEquals( $category->description, $data['description'] );
$this->assertEquals( $category->count, $data['count'] );
}
+
+ public function test_add_taxonomy_data() {
+ // Mock type
+ $type = new stdClass;
+ $type->name = 'post';
+
+ // This record is not a taxonomy record: taxonomies should be embedded
+ $data = $this->endpoint->add_taxonomy_data( array(), $type, false );
+ $this->assertArrayHasKey( 'taxonomies', $data );
+
+ // This record is a taxonomy record: taxonomies should NOT be embedded
+ $data_within_taxonomy = $this->endpoint->add_taxonomy_data( array(), $type, true );
+ $this->assertArrayNotHasKey( 'taxonomies', $data_within_taxonomy );
+ }
}
@kadamwhite
Copy link
Author

This follows what I perceived to be the model for embedding that we use to add taxonomies to types, users to posts, etcetera. Specifically,

  • An add_post_type_data method is added to the posts class to augment a Taxonomy data object with that taxonomy's associated post types.
  • A hook is added in plugin.php to run that add_post_type_data on the json_prepare_taxonomy filter
  • The add_taxonomy_data method (hooked to the json_post_type_data filter) is passed a new parameter indicating whether the post type object in question is being embedded from within a taxonomy object; this prevents circular references where add_post_type_data adds post type objects which each have taxonomy objects added through add_taxonomy_data which in turn again have post type objects embedded.... and so on.

Passing $_in_taxonomy all the way through to add_taxonomy_data feels a little weird, but the only alternative I see is to add a separate filter and that feels even more duplicative.

@kadamwhite
Copy link
Author

Added unit test

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment