Completed
Push — develop ( 844154...ac08d5 )
by David
02:57 queued 11s
created

Wordlift_Term_JsonLd_Adapter   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 218
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 0
Metric Value
dl 0
loc 218
rs 10
c 0
b 0
f 0
wmc 26
lcom 1
cbo 2

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 1
A get_instance() 0 4 1
B get_carousel_jsonld() 0 59 9
A get_posts() 0 17 3
A wp_head() 0 20 4
B get() 0 45 5
A get_term_url() 0 13 3
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