Completed
Push — develop ( fc3971...71605d )
by David
03:09 queued 11s
created

Linked_Data_Autocomplete_Service::do_query()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
nc 3
nop 3
dl 0
loc 26
rs 9.504
c 0
b 0
f 0
1
<?php
2
/**
3
 * This file provides the Linked Data autocomplete service.
4
 *
5
 * @author David Riccitelli <[email protected]>
6
 * @since 3.24.2
7
 * @package Wordlift\Autocomplete
8
 */
9
10
namespace Wordlift\Autocomplete;
11
12
use Wordlift\Entity\Entity_Helper;
13
use Wordlift_Log_Service;
14
use Wordlift_Post_Excerpt_Helper;
15
16
class Linked_Data_Autocomplete_Service implements Autocomplete_Service {
17
18
	/**
19
	 * The {@link Wordlift_Configuration_Service} instance.
20
	 *
21
	 * @since  3.15.0
22
	 * @access private
23
	 * @var \Wordlift_Configuration_Service $configuration_service The {@link Wordlift_Configuration_Service} instance.
24
	 */
25
	private $configuration_service;
26
27
	/**
28
	 * A {@link Wordlift_Log_Service} instance.
29
	 *
30
	 * @since  3.15.0
31
	 * @access private
32
	 * @var \Wordlift_Log_Service $log A {@link Wordlift_Log_Service} instance.
33
	 */
34
	private $log;
35
	private $entity_helper;
36
	private $entity_uri_service;
37
	/**
38
	 * @var \Wordlift_Entity_Service
39
	 */
40
	private $entity_service;
41
42
	/**
43
	 * The {@link Class_Wordlift_Autocomplete_Service} instance.
44
	 *
45
	 * @param \Wordlift_Configuration_Service $configuration_service The {@link Wordlift_Configuration_Service} instance.
46
	 * @param Entity_Helper $entity_helper
47
	 * @param \Wordlift_Entity_Uri_Service $entity_uri_service
48
	 * @param \Wordlift_Entity_Service $entity_service
49
	 *
50
	 * @since 3.15.0
51
	 */
52 View Code Duplication
	public function __construct( $configuration_service, $entity_helper, $entity_uri_service, $entity_service ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
53
54
		$this->log = Wordlift_Log_Service::get_logger( 'Wordlift_Autocomplete_Service' );
55
56
		$this->configuration_service = $configuration_service;
57
		$this->entity_helper         = $entity_helper;
58
		$this->entity_uri_service    = $entity_uri_service;
59
		$this->entity_service        = $entity_service;
60
61
	}
62
63
	/**
64
	 * Make request to external API and return the response.
65
	 *
66
	 * @param string $query The search string.
67
	 * @param string $scope The search scope: "local" will search only in the local dataset; "cloud" will search also
68
	 *                      in Wikipedia. By default is "cloud".
69
	 * @param array|string $excludes The exclude parameter string.
70
	 *
71
	 * @return array $response The API response.
72
	 * @since 3.15.0
73
	 *
74
	 */
75
	public function query( $query, $scope = 'cloud', $excludes = array() ) {
76
77
		$results = $this->do_query( $query, $scope, $excludes );
0 ignored issues
show
Bug introduced by
It seems like $excludes defined by parameter $excludes on line 75 can also be of type array; however, Wordlift\Autocomplete\Li...ete_Service::do_query() does only seem to accept string, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
78
79
		$uris = array_reduce( $results, function ( $carry, $result ) {
80
81
			$carry[] = $result['id'];
82
83
			return array_merge( $carry, $result['sameAss'] );
84
		}, array() );
85
86
		$mappings = $this->entity_helper->map_many_to_local( $uris );
87
88
		$that           = $this;
89
		$mapped_results = array_map( function ( $result ) use ( $that, $mappings ) {
90
91
			if ( $that->entity_uri_service->is_internal( $result['id'] ) ) {
92
				return $result;
93
			}
94
95
			$uris = array_merge( (array) $result['id'], $result['sameAss'] );
96
97
			foreach ( $uris as $uri ) {
98
				if ( isset( $mappings[ $uri ] ) ) {
99
					$local_entity = $that->entity_uri_service->get_entity( $mappings[ $uri ] );
100
101
					return $that->post_to_autocomplete_result( $mappings[ $uri ], $local_entity );
102
				}
103
			}
104
105
			return $result;
106
		}, $results );
107
108
		return $mapped_results;
109
	}
110
111
	private function do_query( $query, $scope = 'cloud', $exclude = '' ) {
112
		$url = $this->build_request_url( $query, $exclude, $scope );
113
114
		// Return the response.
115
		$response = wp_remote_get( $url, array(
116
			'timeout' => 30
117
		) );
118
119
		// If the response is valid, then send the suggestions.
120
		if ( ! is_wp_error( $response ) && 200 === (int) $response['response']['code'] ) {
121
			// Echo the response.
122
			return json_decode( wp_remote_retrieve_body( $response ), true );
123
		} else {
124
			// Default error message.
125
			$error_message = 'Something went wrong.';
126
127
			// Get the real error message if there is WP_Error.
128
			if ( is_wp_error( $response ) ) {
129
				$error_message = $response->get_error_message();
130
			}
131
132
			$this->log->error( $error_message );
133
134
			return array();
135
		}
136
	}
137
138
	/**
139
	 * Build the autocomplete url.
140
	 *
141
	 * @param string $query The search string.
142
	 * @param array|string $exclude The exclude parameter.
143
	 * @param string $scope The search scope: "local" will search only in the local dataset; "cloud" will search also
144
	 *                      in Wikipedia. By default is "cloud".
145
	 *
146
	 * @return string Built url.
147
	 * @since 3.15.0
148
	 *
149
	 */
150
	private function build_request_url( $query, $exclude, $scope ) {
151
		$args = array(
152
			'key'      => $this->configuration_service->get_key(),
153
			'language' => $this->configuration_service->get_language_code(),
154
			'query'    => $query,
155
			'scope'    => $scope,
156
			'limit'    => 10,
157
		);
158
159
		// Add args to URL.
160
		$request_url = add_query_arg(
161
			urlencode_deep( $args ),
162
			$this->configuration_service->get_autocomplete_url()
163
		);
164
165
		// Add the exclude parameter.
166
		if ( ! empty( $exclude ) ) {
167
			$request_url .= "&exclude=" . implode( '&exclude=', array_map( 'urlencode', (array) $exclude ) );
168
		}
169
170
		// return the built url.
171
		return $request_url;
172
	}
173
174
	private function post_to_autocomplete_result( $uri, $post ) {
175
176
		return array(
177
			'id'           => $uri,
178
			'label'        => array( $post->post_title ),
179
			'labels'       => $this->entity_service->get_alternative_labels( $post->ID ),
180
			'descriptions' => array( Wordlift_Post_Excerpt_Helper::get_text_excerpt( $post ) ),
181
			'scope'        => 'local',
182
			'sameAss'      => get_post_meta( $post->ID, \Wordlift_Schema_Service::FIELD_SAME_AS ),
183
			// The following properties are less relevant because we're linking entities that exist already in the
184
			// vocabulary. That's why we don't make an effort to load the real data.
185
			'types'        => array( 'http://schema.org/Thing' ),
186
			'urls'         => array(),
187
			'images'       => array(),
188
		);
189
	}
190
191
}
192