|
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 ) { |
|
|
|
|
|
|
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 ); |
|
|
|
|
|
|
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
|
|
|
|
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.