Repository navigation
Expand file tree
/
Copy pathsame-posts-rest.php
More file actions
128 lines (110 loc) · 3.65 KB
/
Copy pathsame-posts-rest.php
File metadata and controls
128 lines (110 loc) · 3.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
<?php
/**
* REST route that feeds the block editor's taxonomy and term filters.
*
* The classic widget's form builds its "Filter" section on the server: it
* walks the public taxonomies, groups them by post type and lists the terms of
* each. The block editor needs the same data, and it needs it grouped the same
* way, or the two forms would offer different choices.
*
* Rather than rebuild that grouping in JavaScript from several core routes,
* this route hands over the finished structure and reuses
* Widget::initPostTypesAndTaxes() for the taxonomy-to-post-type mapping and
* for the default taxonomy per post type -- the same method the widget uses.
*
* @package samePosts
*
* @since 1.2.0
*/
namespace samePosts;
const REST_NAMESPACE = 'same-posts/v1';
/**
* Registers the route.
*/
function register_rest_routes() {
register_rest_route(
REST_NAMESPACE,
'/taxonomies',
array(
'methods' => 'GET',
'callback' => __NAMESPACE__ . '\rest_taxonomies',
'permission_callback' => __NAMESPACE__ . '\rest_can_edit_posts',
)
);
}
add_action( 'rest_api_init', __NAMESPACE__ . '\register_rest_routes' );
/**
* The route only serves the editor, so it needs the editor's capability.
*
* @return bool
*/
function rest_can_edit_posts() {
return current_user_can( 'edit_posts' );
}
/**
* Builds the post type => taxonomies => terms structure.
*
* Mirrors Widget::form(): only public taxonomies, only those that have terms,
* terms including empty ones, grouped under the post type that
* initPostTypesAndTaxes() associated with the taxonomy.
*
* @return array<int, array<string, mixed>> One entry per post type that has
* at least one taxonomy with terms.
*/
function taxonomy_choices() {
$widget = new Widget();
$instance = array();
// Fills $instance['post_types'] (taxonomy => post type + hierarchical) and
// $instance['include_tax'] (post type => default taxonomy).
$widget->initPostTypesAndTaxes( $instance );
$post_types = isset( $instance['post_types'] ) ? $instance['post_types'] : array();
$include_tax = isset( $instance['include_tax'] ) ? $instance['include_tax'] : array();
$grouped = array();
foreach ( get_taxonomies( array( 'public' => true ), 'objects' ) as $taxonomy ) {
if ( ! isset( $post_types[ $taxonomy->name ]['post_type'] ) ) {
continue;
}
$terms = get_terms(
array(
'taxonomy' => $taxonomy->name,
'hide_empty' => false, // Show not yet populated terms as well.
'fields' => 'id=>name',
)
);
if ( is_wp_error( $terms ) || empty( $terms ) ) {
continue; // The widget's form skips taxonomies without terms.
}
$post_type = $post_types[ $taxonomy->name ]['post_type'];
$term_list = array();
foreach ( $terms as $term_id => $term_name ) {
$term_list[] = array(
'id' => (int) $term_id,
'name' => $term_name,
);
}
if ( ! isset( $grouped[ $post_type ] ) ) {
$post_type_object = get_post_type_object( $post_type );
$grouped[ $post_type ] = array(
'postType' => $post_type,
'label' => $post_type_object ? $post_type_object->label : $post_type,
'defaultTaxonomy' => isset( $include_tax[ $post_type ] ) ? $include_tax[ $post_type ] : '',
'taxonomies' => array(),
);
}
$grouped[ $post_type ]['taxonomies'][] = array(
'name' => $taxonomy->name,
'label' => $taxonomy->labels->name,
'hierarchical' => (bool) $taxonomy->hierarchical,
'terms' => $term_list,
);
}
return array_values( $grouped );
}
/**
* Route callback.
*
* @return \WP_REST_Response
*/
function rest_taxonomies() {
return rest_ensure_response( taxonomy_choices() );
}