Completed
Pull Request — master (#1095)
by Naveen
02:48
created

Wordlift_Term_JsonLd_Adapter::get()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 1
dl 0
loc 27
rs 9.488
c 0
b 0
f 0
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
	 * @return array|boolean
67
	 */
68
	public function get_carousel_jsonld( $id = null ) {
69
		$posts       = $this->get_posts( $id );
70
		$post_jsonld = array();
71
		if ( ! is_array( $posts ) || count( $posts ) < 2 ) {
72
			// Bail out if no posts are present.
73
			return false;
74
		}
75
76
		if ( ! is_null( $id ) ) {
77
			$term                       = get_term( $id );
78
			$post_jsonld['description'] = $term->description;
79
			$thumbnail_id               = get_term_meta( $id, 'thumbnail_id', true );
80
			if ( ! empty( $thumbnail_id ) ) {
81
				$post_jsonld['image'] = wp_get_attachment_url( $thumbnail_id );
82
			}
83
		}
84
85
		// More than 2 items are present, so construct the post_jsonld data
86
		$post_jsonld['@context']        = 'https://schema.org';
87
		$post_jsonld['@type']           = 'ItemList';
88
		$post_jsonld['url']             = $this->get_term_url( $id );
89
		$post_jsonld['itemListElement'] = array();
90
		$position                       = 1;
91
92
		foreach ( $posts as $post_id ) {
93
			$result = array(
94
				'@type'    => 'ListItem',
95
				'position' => $position,
96
				/**
97
				 * We can't use `item` here unless we change the URL for the item to point to the current page.
98
				 *
99
				 * See https://developers.google.com/search/docs/data-types/carousel
100
				 */
101
				'url'      => get_permalink( $post_id )
102
			);
103
			array_push( $post_jsonld['itemListElement'], $result );
104
			$position += 1;
105
		}
106
107
		return $post_jsonld;
108
	}
109
110
	private function get_posts( $id ) {
111
		global $wp_query;
112
113
		if ( ! is_null( $wp_query->posts ) ) {
114
			return array_map( function ( $post ) {
115
				return $post->ID;
116
			}, $wp_query->posts );
117
		}
118
119
		if ( is_null( $id ) ) {
120
			return null;
121
		}
122
123
		$term = get_term( $id );
124
125
		return get_objects_in_term( $id, $term->taxonomy );
126
	}
127
128
	/**
129
	 * Hook to `wp_head` to print the JSON-LD.
130
	 *
131
	 * @since 3.20.0
132
	 */
133
	public function wp_head() {
134
		// Bail out if it's not a category page.
135
		if ( ! is_tax() && ! is_category() ) {
136
			return;
137
		}
138
139
		$query_object = get_queried_object();
140
		$term_id      = $query_object->term_id;
141
		$jsonld       = $this->get( $term_id );
142
143
		// Bail out if the JSON-LD is empty.
144
		if ( empty( $jsonld ) ) {
145
			return;
146
		}
147
148
		$jsonld_string = wp_json_encode( $jsonld );
149
150
		echo "<script type=\"application/ld+json\">$jsonld_string</script>";
151
152
	}
153
154
	public function get( $id ) {
155
156
		/**
157
		 * Support for carousel rich snippet, get jsonld data present
158
		 * for all the posts shown in the term page, and add the jsonld data
159
		 * to list
160
		 *
161
		 * see here: https://developers.google.com/search/docs/data-types/carousel
162
		 *
163
		 * @since 3.26.0
164
		 */
165
		$carousel_data = $this->get_carousel_jsonld( $id );
166
		$jsonld_array  = array();
167
		if ( $carousel_data ) {
168
			$jsonld_array[] = $carousel_data;
169
		}
170
		$entities_jsonld_array = $this->get_entity_jsonld( $id );
171
172
		/**
173
		 * @since 3.26.3
174
		 * Filter: wl_term_jsonld_array
175
		 * @var $id int Term id
176
		 * @var $jsonld_array array An array containing jsonld for term and entities.
177
		 */
178
		return apply_filters( 'wl_term_jsonld_array', array_merge( $jsonld_array, $entities_jsonld_array ), $id );
179
180
	}
181
182
	private function get_term_url( $id ) {
183
184
		if ( is_null( $id ) ) {
185
			return $_SERVER['REQUEST_URI'];
186
		}
187
188
		$maybe_url = get_term_meta( $id, Wordlift_Url_Property_Service::META_KEY, true );
189
		if ( ! empty( $maybe_url ) ) {
190
			return $maybe_url;
191
		}
192
193
		return get_term_link( $id );
194
	}
195
196
	/**
197
	 * Return jsonld for entities bound to terms.
198
	 *
199
	 * @param $id
200
	 *
201
	 * @return array
202
	 */
203
	private function get_entity_jsonld( $id ) {
204
		// The `_wl_entity_id` are URIs.
205
		$entity_ids         = get_term_meta( $id, '_wl_entity_id' );
206
		$entity_uri_service = $this->entity_uri_service;
207
208
		$local_entity_ids = array_filter( $entity_ids, function ( $uri ) use ( $entity_uri_service ) {
209
			return $entity_uri_service->is_internal( $uri );
210
		} );
211
212
		// Bail out if there are no entities.
213
		if ( empty( $local_entity_ids ) ) {
214
			return array();
215
		}
216
217
		$post   = $this->entity_uri_service->get_entity( array_shift( $local_entity_ids ) );
218
		$jsonld = $this->jsonld_service->get_jsonld( false, $post->ID );
219
		// Reset the `url` to the term page.
220
		$jsonld[0]['url'] = get_term_link( $id );
221
222
		return $jsonld;
223
	}
224
225
}
226