-
Notifications
You must be signed in to change notification settings - Fork 1
/
service.inc
219 lines (191 loc) · 6.51 KB
/
service.inc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
<?php
/**
* @file
* Contains SearchApiAlgoliaService.
*/
/**
* Indexes and searches items using Algolia.
*/
class SearchApiAlgoliaService extends SearchApiAbstractService implements SearchApiServiceInterface {
/**
* Implements SearchApiServiceInterface::__construct().
*
* The sets $this->server and $this->options.
* Also initiates the Algolia client as $this->client if the options for YourApplicationID and YourAPIKey
* have been set.
*/
public function __construct(SearchApiServer $server) {
libraries_load('algolia_api');
$this->server = $server;
$this->options = &$server->options;
if ($this->isConfigured()) {
$this->client = new \AlgoliaSearch\Client($this->options['application_id'], $this->options['api_key']);
}
}
/**
* Do we have the properties to instantiate the API client?
* @return boolean
*/
protected function isConfigured() {
return isset($this->options['application_id']) && isset($this->options['api_key']);
}
/**
* Form constructor for the server configuration form.
*
* Might be called with an incomplete server (no ID). In this case, the form
* is displayed for the initial creation of the server.
*
* @param array $form
* The server options part of the form.
* @param array $form_state
* The current form state.
*
* @return array
* A form array for setting service-specific options.
*/
public function configurationForm(array $form, array &$form_state) {
$form['application_id'] = array(
'#type' => 'textfield',
'#title' => t('Algolia Application ID'),
'#size' => 20,
'#maxlength' => 20,
'#required' => TRUE,
);
$form['api_key'] = array(
'#type' => 'textfield',
'#title' => t('Algolia API Key'),
'#size' => 40,
'#maxlength' => 40,
'#required' => TRUE,
);
$form['search_only_api_key'] = array(
'#type' => 'textfield',
'#title' => t('Algolia Search only API Key'),
'#size' => 40,
'#maxlength' => 40,
'#required' => TRUE,
);
// Set default values in form if they exist.
foreach ($form as $key => $value) {
if (isset($this->options[$key])) {
$form[$key]['#default_value'] = $this->options[$key];
}
}
return $form;
}
/**
* Indexes the specified items.
*
* @param SearchApiIndex $index
* The search index for which items should be indexed.
* @param array $items
* An array of items to be indexed, keyed by their id. The values are
* associative arrays of the fields to be stored, where each field is an
* array with the following keys:
* - type: One of the data types recognized by the Search API, or the
* special type "tokens" for fulltext fields.
* - original_type: The original type of the property, as defined by the
* datasource controller for the index's item type.
* - value: The value to index.
*
* The special field "search_api_language" contains the item's language and
* should always be indexed.
*
* The value of fields with the "tokens" type is an array of tokens. Each
* token is an array containing the following keys:
* - value: The word that the token represents.
* - score: A score for the importance of that word.
*
* @return array
* An array of the ids of all items that were successfully indexed.
*
* @throws SearchApiException
* If indexing was prevented by a fundamental configuration error.
*/
public function indexItems(SearchApiIndex $index, array $items) {
// Store original keys before any hooks alter them.
$original_keys = array_keys($items);
// Note the max size of a record for Algolia is 10KB.
$algolia_data = array();
foreach ($items as $id => $item) {
$algolia_data[$id] = array('objectID' => $id);
foreach ($item as $key => $field) {
$algolia_data[$id][$key] = $field['value'];
}
}
// Initiate index (not an expensive operation - does not make any API calls).
$algolia_index = $this->client->initIndex($index->machine_name);
// Let other modules alter the data that is indexed.
drupal_alter('search_api_algolia_data', $algolia_data, $algolia_index);
// Send data to Algolia.
try {
$algolia_index->addObjects(array_values($algolia_data));
}
catch (AlgoliaException $e) {
throw new SearchApiException($e->getMessage());
}
return $original_keys;
}
/**
* Deletes indexed items from this server.
*
* Might be either used to delete some items (given by their ids) from a
* specified index, or all items from that index, or all items from all
* indexes on this server.
*
* @param $ids
* Either an array containing the ids of the items that should be deleted,
* or 'all' if all items should be deleted. Other formats might be
* recognized by implementing classes, but these are not standardized.
* @param SearchApiIndex $index
* The index from which items should be deleted, or NULL if all indexes on
* this server should be cleared (then, $ids has to be 'all').
*
* @throws SearchApiException
* If an error occurred while trying to delete the items.
*/
public function deleteItems($ids = 'all', SearchApiIndex $index = NULL) {
$algolia_index = $this->client->initIndex($index->machine_name);
try {
if ($ids == 'all') {
$algolia_index->clearIndex();
}
else {
// Let other modules alter the ids of the data that is indexed.
drupal_alter('search_api_algolia_ids', $ids, $algolia_index);
$algolia_index->deleteObjects($ids);
}
}
catch (AlgoliaException $e) {
throw new SearchApiException($e->getMessage());
}
}
/**
* Executes a search on the server represented by this object.
*
* @param $query
* The SearchApiQueryInterface object to execute.
*
* @return array
* An associative array containing the search results, as required by
* SearchApiQueryInterface::execute().
*
* @throws SearchApiException
* If an error prevented the search from completing.
*/
public function search(SearchApiQueryInterface $query) {
$count = 0;
$index_name = $query->getIndex()->machine_name;
$indexes = $this->client->listIndexes();
foreach ($indexes['items'] as $index) {
if ($index['name'] == $index_name) {
$count = $index['entries'];
}
}
// Todo - return real results.
return array(
'result count' => $count,
'results' => array()
);
}
}