|
1
|
|
|
<?php |
|
2
|
|
|
/** |
|
3
|
|
|
* Taxonomy Term JSON-LD Adapter. |
|
4
|
|
|
* |
|
5
|
|
|
* The {@link Wordlift_Term_JsonLd_Adapter} intercepts calls to terms' pages and loads the related JSON-LD in page. |
|
6
|
|
|
* |
|
7
|
|
|
* @since 3.20.0 |
|
8
|
|
|
* @package Wordlift |
|
9
|
|
|
* @subpackage Wordlift/public |
|
10
|
|
|
*/ |
|
11
|
|
|
|
|
12
|
|
|
/** |
|
13
|
|
|
* Define the {@link Wordlift_Term_JsonLd_Adapter} class. |
|
14
|
|
|
* |
|
15
|
|
|
* @since 3.20.0 |
|
16
|
|
|
*/ |
|
17
|
|
|
class Wordlift_Term_JsonLd_Adapter { |
|
18
|
|
|
|
|
19
|
|
|
/** |
|
20
|
|
|
* The {@link Wordlift_Entity_Uri_Service} instance. |
|
21
|
|
|
* |
|
22
|
|
|
* @since 3.20.0 |
|
23
|
|
|
* @access private |
|
24
|
|
|
* @var \Wordlift_Entity_Uri_Service $entity_uri_service The {@link Wordlift_Entity_Uri_Service} instance. |
|
25
|
|
|
*/ |
|
26
|
|
|
private $entity_uri_service; |
|
27
|
|
|
|
|
28
|
|
|
/** |
|
29
|
|
|
* The {@link Wordlift_Jsonld_Service} instance. |
|
30
|
|
|
* |
|
31
|
|
|
* @since 3.20.0 |
|
32
|
|
|
* @access private |
|
33
|
|
|
* @var \Wordlift_Jsonld_Service $jsonld_service The {@link Wordlift_Jsonld_Service} instance. |
|
34
|
|
|
*/ |
|
35
|
|
|
private $jsonld_service; |
|
36
|
|
|
|
|
37
|
|
|
private static $instance; |
|
38
|
|
|
|
|
39
|
|
|
/** |
|
40
|
|
|
* Wordlift_Term_JsonLd_Adapter constructor. |
|
41
|
|
|
* |
|
42
|
|
|
* @param \Wordlift_Entity_Uri_Service $entity_uri_service The {@link Wordlift_Entity_Uri_Service} instance. |
|
43
|
|
|
* @param \Wordlift_Jsonld_Service $jsonld_service The {@link Wordlift_Jsonld_Service} instance. |
|
44
|
|
|
* |
|
45
|
|
|
* @since 3.20.0 |
|
46
|
|
|
* |
|
47
|
|
|
*/ |
|
48
|
|
|
public function __construct( $entity_uri_service, $jsonld_service ) { |
|
49
|
|
|
|
|
50
|
|
|
add_action( 'wp_head', array( $this, 'wp_head' ) ); |
|
51
|
|
|
|
|
52
|
|
|
$this->entity_uri_service = $entity_uri_service; |
|
53
|
|
|
$this->jsonld_service = $jsonld_service; |
|
54
|
|
|
|
|
55
|
|
|
self::$instance = $this; |
|
56
|
|
|
} |
|
57
|
|
|
|
|
58
|
|
|
public static function get_instance() { |
|
59
|
|
|
|
|
60
|
|
|
return self::$instance; |
|
61
|
|
|
} |
|
62
|
|
|
|
|
63
|
|
|
/** |
|
64
|
|
|
* Adds carousel json ld data to term page if the conditions match |
|
65
|
|
|
* |
|
66
|
|
|
* @param $jsonld array JsonLd Array. |
|
67
|
|
|
* |
|
68
|
|
|
* @return array |
|
69
|
|
|
*/ |
|
70
|
|
|
public function get_carousel_jsonld( $jsonld, $id = null ) { |
|
71
|
|
|
$posts = $this->get_posts( $id ); |
|
72
|
|
|
|
|
73
|
|
|
if ( ! is_array( $posts ) ) { |
|
74
|
|
|
// Bail out if no posts are present. |
|
75
|
|
|
return $jsonld; |
|
76
|
|
|
} |
|
77
|
|
|
|
|
78
|
|
|
$entities = array(); |
|
79
|
|
|
|
|
80
|
|
|
if ( count( $posts ) < 2 ) { |
|
81
|
|
|
return $jsonld; |
|
82
|
|
|
} |
|
83
|
|
|
|
|
84
|
|
|
if ( ! is_null( $id ) ) { |
|
85
|
|
|
$term = get_term( $id ); |
|
86
|
|
|
$jsonld['description'] = $term->description; |
|
87
|
|
|
|
|
88
|
|
|
$thumbnail_id = get_term_meta( $id, 'thumbnail_id', true ); |
|
89
|
|
|
if ( ! empty( $thumbnail_id ) ) { |
|
90
|
|
|
$jsonld['image'] = wp_get_attachment_url( $thumbnail_id ); |
|
91
|
|
|
} |
|
92
|
|
|
} |
|
93
|
|
|
|
|
94
|
|
|
// More than 2 items are present, so construct the jsonld data |
|
95
|
|
|
$jsonld['@context'] = 'https://schema.org'; |
|
96
|
|
|
$jsonld['@type'] = 'ItemList'; |
|
97
|
|
|
$jsonld['url'] = $this->get_term_url( $id ); |
|
98
|
|
|
$jsonld['itemListElement'] = array(); |
|
99
|
|
|
$position = 1; |
|
100
|
|
|
|
|
101
|
|
|
foreach ( $posts as $post_id ) { |
|
102
|
|
|
$post_jsonld = $this->jsonld_service->get_jsonld( false, $post_id ); |
|
103
|
|
|
$result = array( |
|
104
|
|
|
'@type' => 'ListItem', |
|
105
|
|
|
'position' => $position, |
|
106
|
|
|
/** |
|
107
|
|
|
* We can't use `item` here unless we change the URL for the item to point to the current page. |
|
108
|
|
|
* |
|
109
|
|
|
* See https://developers.google.com/search/docs/data-types/carousel |
|
110
|
|
|
*/ |
|
111
|
|
|
// 'item' => array_shift( $post_jsonld ) |
|
112
|
|
|
); |
|
113
|
|
|
if ( is_array( $post_jsonld ) && |
|
114
|
|
|
count( $post_jsonld ) > 0 && |
|
115
|
|
|
array_key_exists( 'url', $post_jsonld[0] ) ) { |
|
116
|
|
|
$result['url'] = $post_jsonld[0]['url']; |
|
117
|
|
|
} |
|
118
|
|
|
array_push( $jsonld['itemListElement'], $result ); |
|
119
|
|
|
|
|
120
|
|
|
$entities = array_merge( $entities, $post_jsonld ); |
|
121
|
|
|
$position += 1; |
|
122
|
|
|
} |
|
123
|
|
|
|
|
124
|
|
|
return array( |
|
125
|
|
|
'post_jsonld' => $jsonld, |
|
126
|
|
|
'entities' => array() |
|
127
|
|
|
); |
|
128
|
|
|
} |
|
129
|
|
|
|
|
130
|
|
|
private function get_posts( $id ) { |
|
131
|
|
|
global $wp_query; |
|
132
|
|
|
|
|
133
|
|
|
if ( ! is_null( $wp_query->posts ) ) { |
|
134
|
|
|
return array_map( function ( $post ) { |
|
135
|
|
|
return $post->ID; |
|
136
|
|
|
}, $wp_query->posts ); |
|
137
|
|
|
} |
|
138
|
|
|
|
|
139
|
|
|
if ( is_null( $id ) ) { |
|
140
|
|
|
return null; |
|
141
|
|
|
} |
|
142
|
|
|
|
|
143
|
|
|
$term = get_term( $id ); |
|
144
|
|
|
|
|
145
|
|
|
return get_objects_in_term( $id, $term->taxonomy ); |
|
146
|
|
|
} |
|
147
|
|
|
|
|
148
|
|
|
/** |
|
149
|
|
|
* Hook to `wp_head` to print the JSON-LD. |
|
150
|
|
|
* |
|
151
|
|
|
* @since 3.20.0 |
|
152
|
|
|
*/ |
|
153
|
|
|
public function wp_head() { |
|
154
|
|
|
// Bail out if it's not a category page. |
|
155
|
|
|
if ( ! is_tax() && ! is_category() ) { |
|
156
|
|
|
return; |
|
157
|
|
|
} |
|
158
|
|
|
|
|
159
|
|
|
$query_object = get_queried_object(); |
|
160
|
|
|
$term_id = $query_object->term_id; |
|
161
|
|
|
$jsonld = $this->get( $term_id ); |
|
162
|
|
|
|
|
163
|
|
|
// Bail out if the JSON-LD is empty. |
|
164
|
|
|
if ( empty( $jsonld ) ) { |
|
165
|
|
|
return; |
|
166
|
|
|
} |
|
167
|
|
|
|
|
168
|
|
|
$jsonld_string = wp_json_encode( $jsonld ); |
|
169
|
|
|
|
|
170
|
|
|
echo "<script type=\"application/ld+json\">$jsonld_string</script>"; |
|
171
|
|
|
|
|
172
|
|
|
} |
|
173
|
|
|
|
|
174
|
|
|
public function get( $id ) { |
|
175
|
|
|
|
|
176
|
|
|
/** |
|
177
|
|
|
* Support for carousel rich snippet, get jsonld data present |
|
178
|
|
|
* for all the posts shown in the term page, and add the jsonld data |
|
179
|
|
|
* to list |
|
180
|
|
|
* |
|
181
|
|
|
* see here: https://developers.google.com/search/docs/data-types/carousel |
|
182
|
|
|
* |
|
183
|
|
|
* @since 3.26.0 |
|
184
|
|
|
*/ |
|
185
|
|
|
$carousel_data = $this->get_carousel_jsonld( array(), $id ); |
|
186
|
|
|
|
|
187
|
|
|
// If the carousel jsonld returns empty array, then fallback to previous jsonld generation. |
|
188
|
|
|
if ( isset( $carousel_data['entities'] ) |
|
189
|
|
|
&& isset( $carousel_data['post_jsonld'] ) |
|
190
|
|
|
&& $carousel_data['post_jsonld'] !== array() ) { |
|
191
|
|
|
|
|
192
|
|
|
$entities = $carousel_data['entities']; |
|
193
|
|
|
$post_jsonld = $carousel_data['post_jsonld']; |
|
194
|
|
|
|
|
195
|
|
|
$jsonld = array( $post_jsonld ); |
|
196
|
|
|
$jsonld = array_merge( $jsonld, $entities ); |
|
197
|
|
|
} else { |
|
198
|
|
|
// The `_wl_entity_id` are URIs. |
|
199
|
|
|
$entity_ids = get_term_meta( $id, '_wl_entity_id' ); |
|
200
|
|
|
$entity_uri_service = $this->entity_uri_service; |
|
201
|
|
|
|
|
202
|
|
|
$local_entity_ids = array_filter( $entity_ids, function ( $uri ) use ( $entity_uri_service ) { |
|
203
|
|
|
return $entity_uri_service->is_internal( $uri ); |
|
204
|
|
|
} ); |
|
205
|
|
|
|
|
206
|
|
|
// Bail out if there are no entities. |
|
207
|
|
|
if ( empty( $local_entity_ids ) ) { |
|
208
|
|
|
return array(); |
|
209
|
|
|
} |
|
210
|
|
|
|
|
211
|
|
|
$post = $this->entity_uri_service->get_entity( $local_entity_ids[0] ); |
|
212
|
|
|
$jsonld = $this->jsonld_service->get_jsonld( false, $post->ID ); |
|
213
|
|
|
// Reset the `url` to the term page. |
|
214
|
|
|
$jsonld[0]['url'] = get_term_link( $id ); |
|
215
|
|
|
} |
|
216
|
|
|
|
|
217
|
|
|
return $jsonld; |
|
218
|
|
|
} |
|
219
|
|
|
|
|
220
|
|
|
private function get_term_url( $id ) { |
|
221
|
|
|
|
|
222
|
|
|
if ( is_null( $id ) ) { |
|
223
|
|
|
return $_SERVER['REQUEST_URI']; |
|
224
|
|
|
} |
|
225
|
|
|
|
|
226
|
|
|
$maybe_url = get_term_meta( $id, Wordlift_Url_Property_Service::META_KEY, true ); |
|
227
|
|
|
if ( ! empty( $maybe_url ) ) { |
|
228
|
|
|
return $maybe_url; |
|
229
|
|
|
} |
|
230
|
|
|
|
|
231
|
|
|
return get_term_link( $id ); |
|
232
|
|
|
} |
|
233
|
|
|
|
|
234
|
|
|
} |
|
235
|
|
|
|