Skip to content

Commit 103304a

Browse files
Merge pull request #1 from WebDevStudios/feature/filter-default-post-type
Adds ability to filter posts type
2 parents c2e24ff + 6cfd293 commit 103304a

File tree

8 files changed

+3840
-1020
lines changed

8 files changed

+3840
-1020
lines changed

assets/css/wds-react-post-search.css

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
.search-form-input {
2-
margin-bottom: 50px;
32
position: relative;
43
}
54

5+
.search-form-performing-action {
6+
margin-bottom: 50px;
7+
}
8+
69
.search-form-input .search-input,
710
.search-results-container {
811
width: 100%;

assets/js/components/searchForm.js

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import React from 'react';
2+
import qs from 'query-string';
23
import SearchResults from './searchResults';
34

45
export default class SearchForm extends React.Component {
56

67
constructor( props ) {
78
super( props );
89

9-
this.getResults = this.getResults.bind( this );
10+
this.getResults = this.getResults.bind( this );
11+
this.getFormClass = this.getFormClass.bind( this );
1012

1113
this.state = {
1214
results: [],
@@ -41,8 +43,20 @@ export default class SearchForm extends React.Component {
4143
empty: false,
4244
} );
4345

44-
let url = wds_react_post_search.rest_search_posts.replace( '%s', search );
46+
const postType = this.props.postType;
4547

48+
let url = wds_react_post_search.rest_search_posts.replace( '%s', search );
49+
let query = {
50+
s: search
51+
};
52+
53+
if ( postType ) {
54+
query.type = postType;
55+
};
56+
57+
const queryString = qs.stringify( query );
58+
url = `${ url }?${ queryString }`;
59+
4660
let json = fetch( url )
4761
.then(
4862
response => {
@@ -67,9 +81,23 @@ export default class SearchForm extends React.Component {
6781
}
6882
}
6983

84+
getFormClass() {
85+
let className = 'search-form-input';
86+
87+
if ( this.state.results.length > 0 || this.state.loading || this.state.lengthError || this.state.searched ) {
88+
className += ' search-form-performing-action';
89+
}
90+
91+
if ( this.state.empty ) {
92+
className = 'search-form-input';
93+
}
94+
95+
return className;
96+
}
97+
7098
render() {
7199
return (
72-
<div className="search-form-input">
100+
<div className={ `${ this.getFormClass() }` }>
73101
<input className="search-input" type="text" onChange={ this.getResults } />
74102
<SearchResults searched={ this.state.searched } loading={ this.state.loading } results={ this.state.results } lengthError={ this.state.lengthError } empty={ this.state.empty } />
75103
</div>

assets/js/components/searchResult.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export default class SearchResult extends React.Component {
99
render() {
1010
return (
1111
<li className="search-results-item">
12-
<a href={ this.props.result.link }>{ this.props.result.title.rendered }</a>
12+
<a href={ this.props.result.link }>{ this.props.result.title }</a>
1313
</li>
1414
)
1515
}

assets/js/public.js

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,20 @@ import React from 'react';
22
import ReactDOM from 'react-dom';
33
import SearchForm from './components/searchForm';
44

5-
const searchFormElement = <SearchForm />,
6-
searchFields = document.getElementsByClassName( wds_react_post_search.search_form_class );
5+
const searchFields = document.getElementsByClassName( wds_react_post_search.search_form_class );
76

87
if ( searchFields.length ) {
98

10-
for ( let i=0; i < searchFields.length; i++ ) {
9+
for ( let i = 0; i < searchFields.length; i++ ) {
10+
const searchForm = searchFields[ i ];
11+
let postType = '';
12+
13+
if( searchForm.querySelector('input[name=post_type]') ) {
14+
postType = searchForm.querySelector('input[name=post_type]').value;
15+
}
16+
1117
ReactDOM.render(
12-
searchFormElement,
18+
<SearchForm postType={ postType } />,
1319
searchFields[ i ]
1420
)
1521
}

assets/js/public.min.js

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

class-wds-react-post-search.php

Lines changed: 84 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ public function requirements_not_met_notice() {
231231
*/
232232
public function hooks() {
233233
add_filter( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ), 1 );
234+
add_action( 'rest_api_init', array( $this, 'rest_api_init' ), 10, 2 );
234235
add_action( 'rest_post_query', array( $this, 'add_post_types_to_query' ), 10, 2 );
235236
}
236237

@@ -248,7 +249,7 @@ public function enqueue_scripts() {
248249
wp_enqueue_style( 'wds-react-post-search-styles' );
249250

250251
wp_localize_script( 'wds-react-post-search', 'wds_react_post_search', array(
251-
'rest_search_posts' => rest_url( 'wp/v2/posts?' . $this->get_post_types_to_search() . 'search=%s' ),
252+
'rest_search_posts' => rest_url( 'wds-react-post-search/v1/search' ),
252253
'loading_text' => apply_filters( 'wds_react_post_search_loading_text', esc_html__( 'Loading results...', 'wds-react-post-search' ) ),
253254
'no_results_text' => apply_filters( 'wds_react_post_search_no_results_text', esc_html__( 'No results found.', 'wds-react-post-search' ) ),
254255
'length_error' => apply_filters( 'wds_react_post_search_length_error_text', esc_html__( 'Please enter at least 3 characters.', 'wds-react-post-search' ) ),
@@ -308,41 +309,105 @@ public function add_post_types_to_query( $args, $request ) {
308309
* }
309310
* add_filter( 'wds_react_post_search_filter_post_types', '_s_filter_post_types_to_query' );
310311
*
311-
* @param array $post_types Array of post types to be used.
312312
* @author Corey Collins
313313
*/
314-
public function post_types_to_search( $post_types = array() ) {
314+
public function post_types_to_search() {
315315

316-
$default_post_types = array(
317-
'post',
316+
$post_types = array(
317+
'any',
318318
);
319319

320-
$all_post_types = array_merge( $default_post_types, apply_filters( 'wds_react_post_search_filter_post_types', $post_types ) );
320+
$all_post_types = apply_filters( 'wds_react_post_search_filter_post_types', $post_types );
321321

322322
return $all_post_types;
323323
}
324324

325325
/**
326-
* Get the string of post types to search for our REST API query.
326+
* Register REST API search results route.
327327
*
328-
* @return void Bail if we don't even have filtered post types – we'll just search posts.
329-
* @author Corey Collins
328+
* @return void
330329
*/
331-
public function get_post_types_to_search() {
332-
333-
$post_types = $this->post_types_to_search();
330+
public function rest_api_init() {
331+
register_rest_route('wds-react-post-search/v1', '/search', [
332+
'methods' => WP_REST_Server::READABLE,
333+
'callback' => array( $this, 'search_posts' ),
334+
'args' => $this->get_search_args(),
335+
]);
336+
}
334337

335-
if ( ! $post_types ) {
336-
return;
337-
}
338+
/**
339+
* Define the arguments our endpoint receives.
340+
*/
341+
public function get_search_args() {
342+
$args = [];
343+
344+
$args['s'] = [
345+
'description' => esc_html__( 'The search term.', 'wds-react-post-search' ),
346+
'type' => 'string',
347+
];
348+
349+
$args['type'] = [
350+
'description' => esc_html__( 'Post Types.', 'wds-react-post-search' ),
351+
'type' => 'array',
352+
'default' => [],
353+
'items' => [
354+
'type' => 'string',
355+
],
356+
];
338357

339-
$post_types_string = '';
358+
return $args;
359+
}
340360

341-
foreach ( $post_types as $post_type ) {
342-
$post_types_string .= 'type[]=' . esc_attr( $post_type ) . '&';
361+
/**
362+
* Get search post types.
363+
*
364+
* @param array $request HTTP request variables.
365+
* @return mixed
366+
*/
367+
public function get_valid_search_post_types( $request ) {
368+
if ( is_array( $request['type'] ) && ! empty( $request['type'] ) ) {
369+
return array_map( 'sanitize_text_field', $request['type'] );
370+
} elseif ( $request['type'] ) {
371+
return sanitize_text_field( $request['type'] );
372+
} else {
373+
return $this->post_types_to_search();
343374
}
375+
}
344376

345-
return $post_types_string;
377+
/**
378+
* Search posts.
379+
*
380+
* @param array $request HTTP request variables.
381+
* @return array Search results or error.
382+
*/
383+
public function search_posts( $request ) {
384+
$posts = [];
385+
$results = [];
386+
387+
if ( isset( $request['s'] ) ) :
388+
$filter = [
389+
'posts_per_page' => -1,
390+
'post_type' => $this->get_valid_search_post_types( $request ),
391+
's' => sanitize_text_field( $request['s'] ),
392+
];
393+
394+
// Get posts.
395+
$posts = get_posts( $filter );
396+
397+
// Return title and link.
398+
foreach ( $posts as $post ) :
399+
$results[] = [
400+
'title' => $post->post_title,
401+
'link' => get_permalink( $post->ID ),
402+
];
403+
endforeach;
404+
endif;
405+
406+
if ( empty( $results ) ) :
407+
return new WP_Error( 'wds-react-post-search-results', apply_filters( 'wds_react_post_search_no_results_text', esc_html__( 'No results found.', 'wds-react-post-search' ) ) );
408+
endif;
409+
410+
return rest_ensure_response( $results );
346411
}
347412
}
348413

0 commit comments

Comments
 (0)