Completed
Push — try/search-in-dev-mode ( 01eac0 )
by
unknown
06:19
created

Jetpack_Search_Local_Endpoint::get_post_result()   B

Complexity

Conditions 9
Paths 9

Size

Total Lines 48

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
nc 9
nop 2
dl 0
loc 48
rs 7.5789
c 0
b 0
f 0
1
<?php
2
3
class Jetpack_Search_Local_Endpoint {
4 View Code Duplication
	public function register_routes() {
5
		register_rest_route(
6
			'jetpack/v4',
7
			'/search-local',
8
			array(
9
				array(
10
					'methods'             => WP_REST_Server::READABLE,
11
					'callback'            => array( $this, 'get_items' ),
12
					'permission_callback' => array( $this, 'get_items_permissions_check' ),
13
					'args'                => $this->get_request_args(),
14
				),
15
				'schema' => array( $this, 'get_schema' ),
16
			)
17
		);
18
	}
19
20
	public function get_request_args() {
21
		return array(
22
			'context' => 'view',
23
			'size' => array(
24
				'type' => 'integer',
25
				'minimum' => 1,
26
				'maximum' => 20,
27
				'default' => 10,
28
			),
29
			'from' => array(
30
				'type' => 'integer',
31
				'minimum' => 0,
32
				'maximum' => 200,
33
				'default' => 0,
34
			),
35
			'fields' => array(
36
				'type' => 'array',
37
				'items' => array(
38
					'type' => 'string',
39
				),
40
				'default' => array( 'blog_id', 'post_id' ),
41
			),
42
			'highlight_fields' => array(
43
				'items' => array(
44
					'type' => 'string',
45
				),
46
			),
47
			'query' => array(
48
				'type' => 'string',
49
				'required' => true,
50
			),
51
			'sort' => array(
52
				'type' => 'string',
53
				'default' => 'score_default',
54
				'enum' => array(
55
					'score_default',
56
					'date_desc',
57
					'date_asc',
58
				),
59
			),
60
			'page_handle' => array(
61
				'type' => 'string',
62
			),
63
		);
64
	}
65
66
	public function get_schema() {
67
		return array(
68
			'$schema'    => 'http://json-schema.org/draft-04/schema#',
69
			'title'      => 'search-local-result',
70
			'type'       => 'object',
71
			'properties' => array(
72
				'aggregations' => array(
73
					'type'    => 'array',
74
					'context' => array( 'view', 'edit' ),
75
				),
76
				'corrected_query' => array(
77
					'type' => array( 'string', 'boolean' ),
78
					'context' => array( 'view', 'edit' ),
79
				),
80
				'page_handle' => array(
81
					'type' => array( 'string', 'boolean' ),
82
					'context' => array( 'view', 'edit' ),
83
				),
84
				'results' => array(
85
					'type' => 'array',
86
					'items' => array(
87
						'type' => 'object',
88
						'properties' => array(
89
							'fields' => array(
90
								'type' => 'object',
91
								'properties' => array(
92
									'blog_id' => array(
93
										'type' => 'integer',
94
									),
95
									'post_id' => array(
96
										'type' => 'integer',
97
									),
98
									'date' => array(
99
										'type' => 'string',
100
										'format' => 'date-time',
101
									),
102
									'post_type' => array(
103
										'type' => 'string',
104
									),
105
									'permalink.url.raw' => array(
106
										'type' => 'string',
107
									),
108
									'has.image' => array(
109
										'type' => 'integer',
110
									),
111
									'category.name.default' => array(
112
										'type' => 'string',
113
									),
114
								),
115
							),
116
							'highlight' => array(
117
								'type' => 'object',
118
								'properties' => array(
119
									'content' => array(
120
										'type' => array(
121
											'items' => array(
122
												'type' => 'string',
123
											),
124
										),
125
									),
126
									'title' => array(
127
										'type' => array(
128
											'items' => array(
129
												'type' => 'string',
130
											),
131
										),
132
									),
133
								),
134
							),
135
							'railcar' => array(
136
								'type' => 'object',
137
							),
138
							'result_type' => array(
139
								'type' => 'string',
140
							),
141
						),
142
					),
143
				),
144
				'suggestions' => array(
145
					'type' => 'array',
146
				),
147
				'total' => array(
148
					'type' => 'integer',
149
				),
150
			),
151
		);
152
	}
153
154
	public function get_items_permissions_check() {
155
		return Jetpack::is_development_mode()
156
			? true
157
			: new WP_Error(
158
				'development_mode_only',
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'development_mode_only'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
159
				__( "This endpoint is meant only for local testing and is only available in Jetpack's Development Mode." ),
160
				array(
161
					'status' => 400,
162
				)
163
			);
164
	}
165
166
	// @todo - page_handle
167
	// @todo - search comments
168
	public function get_items( $request ) {
169
		if ( 'score_default' === $request['sort'] ) {
170
			$orderby = 'relevance';
171
			$order   = 'DESC';
172
		} else {
173
			$orderby = 'date';
174
			$order   = 'date_desc' === $request['sort'] ? 'DESC' : 'ASC';
175
		}
176
177
		$post_query = new WP_Query( array(
178
			'posts_per_page' => $request['size'],
179
			'offset'         => $request['from'],
180
			'orderby'        => $orderby,
181
			'order'          => $order,
182
			's'              => $request['query'],
183
184
			'fields' => 'ids',
185
		) );
186
187
		$terms = preg_split( '/\\s+/', wp_kses( $request['query'], 'strip' ) );
188
189
		$term_regex = '/(' . join( '|', array_map( function( $term ) {
190
			return preg_quote( $term, '/' );
191
		}, $terms ) ) . ')/i';
192
193
		$fields = $request['fields'];
194
195
		$results = array();
196
		foreach ( $post_query->posts as $post_id ) {
197
			$result = $this->get_post_result( $post_id, $fields );
198
			foreach ( $result['highlight'] as &$highlight ) {
199
				foreach ( $highlight as &$text ) {
200
					$text = preg_replace( $term_regex, '<mark>\\1</mark>', $text );
201
				}
202
			}
203
204
			$results[] = $result;
205
		}
206
207
		return array(
208
			'results'   => $results,
209
			'total'     => (int) $post_query->found_posts,
210
211
			// Unsupported
212
			'aggregations'    => array(),
213
			'corrected_query' => false,
214
			'page_handle'     => false,
215
			'suggestions'     => array(),
216
		);
217
	}
218
219
	// @todo has.image
220
	// @todo _score
221
	private function get_post_result( $post_id, $fields ) {
222
		$post = get_post( $post_id );
223
		$blog_id = get_current_blog_id();
224
225
		$return = array(
226
			'fields'      => array(),
227
			'highlight'   => array(
228
				'title' => array(
229
					// strip_tags() to remove HTML comments.
230
					strip_tags( wp_kses( $post->post_title, 'strip' ) ),
231
				),
232
				'content' => array(
233
					strip_tags( wp_kses( $post->post_content, 'strip' ) ),
234
				),
235
			),
236
			'railcar'     => array(),
237
			'result_type' => 'post',
238
			'_score'      => 1,
239
		);
240
241
		foreach ( $fields as $field ) {
242
			switch ( $field ) {
243
				case 'blog_id' :
244
					$return['fields'][ $field ] = (int) $blog_id;
245
					break;
246
				case 'post_id' :
247
					$return['fields'][ $field ] = (int) $post_id;
248
					break;
249
				case 'date' :
250
					$return['fields'][ $field ] = (string) $post->post_date;
251
					break;
252
				case 'post_type' :
253
					$return['fields'][ $field ] = (string) $post->post_type;
254
					break;
255
				case 'permalink.url.raw' :
256
					$return['fields'][ $field ] = (string) get_permalink( $post );
257
					break;
258
				case 'has.image' :
259
					$return['fields'][ $field ] = (int) 0;
260
					break;
261
				case 'category.name.default' :
262
					$return['fields'][ $field ] = (string) get_the_category( $post )[0]->name;
263
					break;
264
			}
265
		}
266
267
		return $return;
268
	}
269
}
270