Issue #1984490 by Nick_vh: Added support for OR logic in requirements.
[project/facetapi.git] / facetapi.api.php
1 <?php
2
3 /**
4 * @file
5 * Hooks provided by the Facet API module.
6 */
7
8 /**
9 * @addtogroup hooks
10 * @{
11 */
12
13 /**
14 * Define all searchers provided by the module.
15 *
16 * Searchers are synonymous with search pages, or environments. Multiple
17 * searchers can share the same adapter class, but each searcher will spawn a
18 * separate instance of the adapter. Each searcher must be unique, so it is
19 * common practice to prefix the name with the module implementing the hook,
20 * such as "apachesolr@searcher-x", "search_api@searcher-y", etc.
21 *
22 * @return array
23 * An associative array keyed by unique name of the searcher. Each searcher is
24 * an associative array containing:
25 * - label: The human readable name of the searcher displayed in the admin UI.
26 * - adapter: The adapter plugin ID associated with the searcher.
27 * - url processor: (optional) The URL processor plugin ID associated with the
28 * searcher. Defaults to "standard".
29 * - types: (optional) An array containing the types of content indexed by the
30 * searcher. A type is usually an entity such as 'node', but it can contain
31 * non-entities as well. Defaults to array('node').
32 * - path: (optional) The MENU_DEFAULT_LOCAL_TASK item which the admin UI page
33 * is added to as a MENU_LOCAL_TASK. An empty string if the backend manages
34 * the admin UI menu items internally. Defaults to an empty string meaning
35 * the backend is responsible for adding the admin UI menu items.
36 * - supports facet missing: (optional) TRUE if the searcher supports
37 * "missing" facets. Defaults to FALSE.
38 * - supports facet mincount: (optional) TRUE if the searcher supports the
39 * minimum facet count setting. Defaults to FALSE.
40 * - include default facets: (optional) TRUE if the searcher should include
41 * the facets defined in facetapi_facetapi_facet_info() when indexing node
42 * content, FALSE if they should be skipped.
43 *
44 * @see FacetapiAdapter
45 */
46 function hook_facetapi_searcher_info() {
47 return array(
48 'search' => array(
49 'label' => t('Search'),
50 'adapter' => 'search',
51 'url processor' => 'standard',
52 'types' => array('node'),
53 'path' => 'admin/config/search/settings',
54 'supports facet missing' => TRUE,
55 'supports facet mincount' => TRUE,
56 'include default facets' => TRUE,
57 ),
58 );
59 }
60
61 /**
62 * Allows for alterations to the searcher definitions.
63 *
64 * @param array &$searcher_info
65 * The return values of hook_facetapi_searcher_info() implementations.
66 *
67 * @see hook_facetapi_searcher_info()
68 */
69 function hook_facetapi_searcher_info_alter(array &$searcher_info) {
70 $searcher_info['search']['label'] = t('Core search module');
71 }
72
73 /**
74 * Define all realms provided by the module.
75 *
76 * A realm is a group of facets that are rendered in a similar fashion. For
77 * example, the "block" realm displays each facet in a separate block, whereas
78 * the "fieldset" realm displays facets as form elements in a fieldset under the
79 * search form.
80 *
81 * @return array
82 * An associative array keyed by unique name of the realm. Each realm is an
83 * associative array containing:
84 * - label: The human readable name of the realm displayed in the admin UI.
85 * - description: The description of the realm displayed in the admin UI.
86 * - element type: The type of element facets are rendered as, such as "links"
87 * or "form elements".
88 * - default widget: The default widget plugin id for facets.
89 * - settings callback: (optional) A callback that alters the realm settings
90 * form, defaults to FALSE meaning no callback is defined.
91 * - sortable: (optional) Whether the facets can be sorted via the admin UI,
92 * defaults to TRUE.
93 * - weight: (optional) The weight of the realm's menu item in comparison to
94 * the others, defaults to 0.
95 */
96 function hook_facetapi_realm_info() {
97 return array(
98 'block' => array(
99 'label' => t('Blocks'),
100 'sortable' => FALSE,
101 'weight' => -10,
102 'default widget' => 'facetapi_links',
103 'element type' => 'links',
104 'settings callback' => 'facetapi_block_realm_settings',
105 'description' => t(
106 'The <em>Blocks</em> realm displays each facet in a separate <a href="@block-page">block</a>. Users are able to refine their searches in a drill-down fashion.',
107 array('@block-page' => url('admin/structure/block', array('query' => array('destination' => current_path()))))
108 ),
109 ),
110 );
111 }
112
113 /**
114 * Allows for alterations to the realm definitions.
115 *
116 * @param array &$realm_info
117 * The return values of hook_facetapi_realm_info() implementations.
118 *
119 * @see hook_facetapi_realm_info()
120 */
121 function hook_facetapi_realm_info_alter(array &$realm_info) {
122 $realm_info['block']['weight'] = 5;
123 }
124
125 /**
126 * Define all facets provided by the module.
127 *
128 * Facets correspond with fields in the search index and are usually related to
129 * entity properties and fields. However, it is not a requirement that the
130 * source data be stored in Drupal. For example, if you are indexing external
131 * RSS feeds, facets can be defined that filter by the field in the index that
132 * stores the publication dates.
133 *
134 * @param array $searcher_info
135 * The definition of the searcher that facets are being collected for.
136 *
137 * @return array
138 * An associative array keyed by unique name of the facet. Each facet is an
139 * associative array containing:
140 * - name: Machine readable name of the facet.
141 * - label: Human readable name of the facet displayed in settings forms.
142 * - description: Description of the facet displayed in settings forms.
143 * - field: The field name used by the backend to store and retrieve data from
144 * the search index it is associated with. Defaults to the machine name of
145 * the facet.
146 * - field alias: The query string variable inside of the filter key used to
147 * pass the filter information through the query string. Defaults to the
148 * machine name of the facet.
149 * - field api name: (optional) The machine readable name of the Field API
150 * field data the facet is associated with, FALSE if it is not associated
151 * with a field.
152 * - field api bundles: (optional) An array of entity names that this field
153 * contains bundle information for. Defaults to an empty array.
154 * - query types: The query type plugins that that this facet supports. For
155 * example, numeric fields support "term" and "range_filter" queries.
156 * - alter callbacks: (optional) Callbacks that alter the initialized render
157 * array returned by the query type plugin. Defaults to an empty array.
158 * - dependency plugins: (optional) An array of dependency plugin IDs that are
159 * supported by this facet.
160 * - default widget: (optional) The widget plugin ID used if no plugin has
161 * been selected or the one selected is not valid. Defaults to FALSE which
162 * sets the default widget as the one defined by the realm.
163 * - allowed operators: (optional) An array keyed by operator constant to
164 * boolean values specifying whether the operator is supported. Defaults to
165 * an array containing:
166 * - FACETAPI_OPERATOR_AND: TRUE
167 * - facet missing allowed: (optional) Whether or not missing facets are
168 * allowed for this facet. Defaults to FALSE.
169 * - facet mincount allowed: (optional) Whether or not the facet supports the
170 * "minimum facet count" setting. Defaults to FALSE.
171 * - weight: (optional) The weight of the facet. Defaults to 0.
172 * - map callback: (optional) The callback used to map the raw values returned
173 * by the index to something human readable. Defaults to FALSE
174 * - map options: (optional) An array of options passed to the map callback,
175 * defaults to en empty array.
176 * - hierarchy callback: (optional) A callback that maps the parent / child
177 * relationships of the facet data, defaults to FALSE meaning the list is
178 * flat.
179 * - values callback: (optional) In instances where facet data is not returned
180 * by the backend, provide a list of values that can be used. Defaults to
181 * FALSE.
182 * - min callback: (optional) For facets containing ranges, a callback
183 * returning the minimum value in the index. Defaults to FALSE.
184 * - max callback: (optional) For facets containing ranges, a callback
185 * returning the maximum value in the index. Defaults to FALSE.
186 * - default sorts: (optional) An array of available sorts. Each item is an
187 * array containing two values, the first being the item being filtered on,
188 * the second being the SORT_* constant. Defaults to an array containing:
189 * - active: SORT_DESC
190 * - count: SORT_DESC
191 * - display: SORT_ASC
192 */
193 function hook_facetapi_facet_info(array $searcher_info) {
194 $facets = array();
195
196 // Facets are usually associated with the type of content stored in the index.
197 if (isset($searcher_info['types']['my_type'])) {
198
199 $facets['my_field'] = array(
200 'name' => 'my_field',
201 'label' => t('My field'),
202 'description' => t('My field index some content we can facet by.'),
203 'field' => 'my_field_index_field_name',
204 'field alias' => 'my_alias',
205 'field api name' => FALSE,
206 'field api bundles' => array(),
207 'query types' => array('term', 'date'),
208 'dependency plugins' => array('role'),
209 'default widget' => 'links',
210 'allowed operators' => array(FACETAPI_OPERATOR_AND => TRUE, FACETAPI_OPERATOR_OR => TRUE),
211 'facet missing allowed' => FALSE,
212 'facet mincount allowed' => FALSE,
213 'weight' => 0,
214 'map callback' => 'mymodule_map_my_field',
215 'map options' => array('field_option_1', 'field_option_2'),
216 'hierarchy callback' => FALSE,
217 'values callback' => FALSE,
218 'min callback' => FALSE,
219 'max callback' => FALSE,
220 'default sorts' => array(
221 array('active', SORT_DESC),
222 array('count', SORT_DESC),
223 array('display', SORT_ASC),
224 ),
225 );
226 }
227
228 return $facets;
229 }
230
231 /**
232 * Allows for alterations to the facet definitions.
233 *
234 * @param array &$facet_info
235 * The return values of hook_facetapi_facet_info() implementations.
236 * @param array $searcher_info
237 * The definition of the searcher that facets are being collected for.
238 *
239 * @see hook_facetapi_facet_info()
240 */
241 function hook_facetapi_facet_info_alter(array &$facet_info, array $searcher_info) {
242 // Change the author index field for Apache Solr searchers indexing node data.
243 if ('apachesolr' == $searcher_info['adapter'] && isset($searcher_info['types']['node'])) {
244 $facet_info['author']['field'] = 'is_uid';
245 }
246 }
247
248 /**
249 * Define all facets sorting algorithms provided by the module.
250 *
251 * Sorts are applied in the FacetapiWidget::sortFacet() method which is called
252 * by FacetapiWidget::init().
253 *
254 * @return array
255 * An associative array keyed by unique name of the sort. Each sort is an
256 * associative array containing:
257 * - title: The human readable name of the sort displayed in the admin UI.
258 * - callback: The uasort() callback the render array is passed to.
259 * - description: The description of the sort displayed in the admin UI.
260 * - weight: (optional) The default weight of the sort specifying its
261 * default processing order. Defaults to 0.
262 *
263 * @see FacetapiWidget::init()
264 * @see FacetapiWidget::sortFacet()
265 */
266 function hook_facetapi_sort_info() {
267 $sorts = array();
268
269 $sorts['active'] = array(
270 'label' => t('Facet active'),
271 'callback' => 'facetapi_sort_active',
272 'description' => t('Sort by whether the facet is active or not.'),
273 'weight' => -50,
274 );
275
276 return $sorts;
277 }
278
279 /**
280 * Allows for alterations to the sort definitions.
281 *
282 * @param array &$sort_info
283 * The return values of hook_facetapi_sort_info() implementations.
284 *
285 * @see hook_facetapi_sort_info()
286 */
287 function hook_facetapi_sort_info_alter(array &$sort_info) {
288 $sort_info['active']['weight'] = 10;
289 }
290
291 /**
292 * Define all adapter plugins provided by the module.
293 *
294 * See the FacetapiAdapter docblock for more information on what an adapter does
295 * and how it interacts with the implementing search module.
296 *
297 * @return array
298 * An associative array keyed by unique name of the adapter. Each adapter is
299 * an associative array keyed by "handler" containing:
300 * - class: The name of the plugin class.
301 *
302 * @see FacetapiAdapter
303 */
304 function hook_facetapi_adapters() {
305 return array(
306 'apachesolr' => array(
307 'handler' => array(
308 'class' => 'FacetapiApachesolrFacetapiAdapter',
309 ),
310 ),
311 );
312 }
313
314 /**
315 * Define all dependency plugins provided by the module.
316 *
317 * See the FacetapiDependency docblock for more information on what dependency
318 * plugins do and what their responsibilities are.
319 *
320 * @return array
321 * An associative array keyed by unique name of the dependency. Each
322 * dependency is an associative array keyed by "handler" containing:
323 * - label: The human readable name of the plugin displayed in the admin UI.
324 * - class: The name of the plugin class.
325 *
326 * @see FacetapiDependency
327 */
328 function hook_facetapi_dependencies() {
329 return array(
330 'bundle' => array(
331 'handler' => array(
332 'label' => t('Content types'),
333 'class' => 'FacetapiDependencyBundle',
334 ),
335 ),
336 );
337 }
338
339 /**
340 * Define all empty behavior plugins provided by the module.
341 *
342 * See the FacetapiEmptyBehavior docblock for more information on what empty
343 * behavior plugins do and what their responsibilities are.
344 *
345 * @return array
346 * An associative array keyed by unique name of the empty behavior. Each empty
347 * behavior is an associative array keyed by "handler" containing:
348 * - label: The human readable name of the plugin displayed in the admin UI.
349 * - class: The name of the plugin class.
350 *
351 * @see FacetapiEmptyBehavior
352 */
353 function hook_facetapi_empty_behaviors() {
354 return array(
355 'none' => array(
356 'handler' => array(
357 'label' => t('Do not display facet'),
358 'class' => 'FacetapiEmptyBehaviorNone',
359 ),
360 ),
361 );
362 }
363
364 /**
365 * Define all filter plugins provided by the module.
366 *
367 * See the FacetapiFilter docblock for more information on what filter plugins
368 * do and what their responsibilities are.
369 *
370 * @return array
371 * An associative array keyed by unique name of the filter. Each filter is an
372 * associative array keyed by "handler" containing:
373 * - label: The human readable name of the plugin displayed in the admin UI.
374 * - class: The name of the plugin class.
375 *
376 * @see FacetapiFilter
377 */
378 function hook_facetapi_filters() {
379 return array(
380 'active_items' => array(
381 'handler' => array(
382 'label' => t('Do not display active items'),
383 'class' => 'FacetapiFilterActiveItems',
384 ),
385 ),
386 );
387 }
388
389 /**
390 * Define all query type plugins provided by the module.
391 *
392 * See the FacetapiQueryTypeInterface docblock for more information on what
393 * query type plugins do and what their responsibilities are.
394 *
395 * @return array
396 * An associative array keyed by unique name of the query type. Each query
397 * type is an associative array keyed by "handler" containing:
398 * - class: The name of the plugin class.
399 * - adapter: The adapter that the query type plugin is associated with.
400 *
401 * @see FacetapiQueryTypeInterface
402 */
403 function hook_facetapi_query_types() {
404 return array(
405 'apachesolr_term' => array(
406 'handler' => array(
407 'class' => 'FacetapiApachesolrTerm',
408 'adapter' => 'apachesolr',
409 ),
410 ),
411 );
412 }
413
414 /**
415 * Define all URL processor plugins provided by the module.
416 *
417 * See the FacetapiUrlProcessor docblock for more information on what url
418 * processor plugins do and what their responsibilities are.
419 *
420 * @return array
421 * An associative array keyed by unique name of the URL processor. Each URL
422 * processor is an associative array keyed by "handler" containing:
423 * - label: The human readable name of the plugin displayed in the admin UI.
424 * - class: The name of the plugin class.
425 *
426 * @see FacetapiUrlProcessor
427 */
428 function hook_facetapi_url_processors() {
429 return array(
430 'standard' => array(
431 'handler' => array(
432 'label' => t('Standard URL processors'),
433 'class' => 'FacetapiUrlProcessorStandard',
434 ),
435 ),
436 );
437 }
438
439 /**
440 * Define all widget plugins provided by the module.
441 *
442 * See the FacetapiWidget docblock for more information on what widget plugins
443 * do and what their responsibilities are.
444 *
445 * @return array
446 * An associative array keyed by unique name of the widget. Each widget is an
447 * associative array keyed by "handler" containing:
448 * - label: The human readable name of the plugin displayed in the admin UI.
449 * - class: The name of the plugin class.
450 * - query types: An array of query-types that this widget is compatible with.
451 * - requirements: An array of requirements that must pass in order for this
452 * widget to be displayed. Requirements are associative arrays keyed by
453 * function to requirement options. The value defaults to a requirement that
454 * the "element type" realm property is equal to "links".
455 *
456 * @see FacetapiWidget
457 * @see facetapi_get_widgets()
458 */
459 function hook_facetapi_widgets() {
460 return array(
461 'facetapi_links' => array(
462 'handler' => array(
463 'label' => t('Links'),
464 'class' => 'FacetapiWidgetLinks',
465 'query types' => array('term', 'date'),
466 'requirements' => array(
467 'facetapi_requirement_realm_property' => array('element type' => 'links')
468 ),
469 ),
470 ),
471 );
472 }
473
474 /**
475 * Forces delta mapping of a facet block.
476 *
477 * This obscure hook is useful for cases where facets are disabled, but their
478 * block positioning needs to be set anyways. If a facet is enabled via the
479 * facetapi_set_facet_enabled() API function, its block needs to be enabled
480 * and assigned to a region despite the facet not being enabled in the Facet API
481 * interface, which would normally prevent the block from being listed.
482 *
483 * @return array
484 * An associative array keyed by searcher. Each sub array is an associative
485 * array keyed by realm name to facet names whose delta mappings are forced.
486 */
487 function hook_facetapi_force_delta_mapping() {
488 return array(
489 // The machine-readable name of the searcher.
490 'my_searcher' => array(
491 // The realm we are mapping, usually block.
492 'block' => array(
493 // Machine readable names of facets whose mappping are being forced.
494 // Regardless of whether they are enabled via the Facet API interface,
495 // their blocks will be available to enable and position via
496 // admin/structure/block.
497 'facet_one',
498 'facet_two',
499 ),
500 ),
501 );
502 }
503
504 /**
505 * Implemented by the translator module to translate a string.
506 *
507 * This hook is invoked by the facetapi_translate_string() function. The
508 * "facetapi:translator_module" variable stores which translator module is
509 * active since it wouldn't make sense to have multiple translator modules.
510 *
511 * @param $name
512 * The name of the string in "textgroup:object_type:object_key:property_name"
513 * format.
514 * @param $string
515 * The string being translated.
516 * @param $langcode
517 * The language code to translate to a language other than what is used to
518 * display the page. Defaults to NULL, which uses the current language.
519 *
520 * @return
521 * The translated string.
522 *
523 * @see facetapi_translate_string()
524 */
525 function hook_facetapi_translate_string($name, $string, $langcode = NULL) {
526 // In this instance, the translator module integrates with the i18n project.
527 return i18n_string($name, $string, array('langcode' => $langcode));
528 }
529
530 /**
531 * @} End of "addtogroup hooks".
532 */