array( 'group' => 'facetapi', ), 'facetapi_dependencies' => array( 'group' => 'facetapi', ), 'facetapi_empty_behaviors' => array( 'group' => 'facetapi', ), 'facetapi_facet_info' => array( 'group' => 'facetapi', ), 'facetapi_filters' => array( 'group' => 'facetapi', ), 'facetapi_query_types' => array( 'group' => 'facetapi', ), 'facetapi_realm_info' => array( 'group' => 'facetapi', ), 'facetapi_sort_info' => array( 'group' => 'facetapi', ), 'facetapi_url_processors' => array( 'group' => 'facetapi', ), 'facetapi_widgets' => array( 'group' => 'facetapi', ), 'current_search_items' => array( 'group' => 'facetapi', ), ); } /** * Implements hook_menu(). */ function facetapi_menu() { $items = array(); // Builds the realm settings forms for each searcher. foreach (facetapi_get_searcher_info() as $searcher => $searcher_info) { // Only build router items automatically if a path is provided. if (empty($searcher_info['path'])) { continue; } // Builds realm settings. $first = TRUE; foreach (facetapi_get_realm_info() as $realm_name => $realm) { if ($first) { $first = FALSE; // Add the first realm as a default local task. $items[$searcher_info['path'] . '/facets'] = array( 'title' => 'Facets', 'page callback' => 'drupal_get_form', 'page arguments' => array( 'facetapi_realm_settings_form', $searcher, $realm_name, ), 'access callback' => 'facetapi_access_callback', 'type' => MENU_LOCAL_TASK, 'file' => 'facetapi.admin.inc', ); $items[$searcher_info['path'] . '/facets/' . $realm_name] = array( 'title' => $realm['label'], 'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => $realm['weight'], ); } else { // Add all additional realms as local tasks. $items[$searcher_info['path'] . '/facets/' . $realm_name] = array( 'title' => $realm['label'], 'page callback' => 'drupal_get_form', 'page arguments' => array( 'facetapi_realm_settings_form', $searcher, $realm_name, ), 'access callback' => 'facetapi_access_callback', 'type' => MENU_LOCAL_TASK, 'file' => 'facetapi.admin.inc', ); } } } $items['admin/config/search/facetapi/%facetapi_adapter/%facetapi_realm/%facetapi_facet/edit'] = array( 'title' => 'Configure facet display', 'load arguments' => array(4), 'page callback' => 'drupal_get_form', 'page arguments' => array('facetapi_facet_display_form', 4, 5, 6), 'access callback' => 'facetapi_access_callback', 'type' => MENU_LOCAL_ACTION, 'context' => MENU_CONTEXT_INLINE, 'weight' => -15, 'file' => 'facetapi.admin.inc', ); $items['admin/config/search/facetapi/%facetapi_adapter/%facetapi_realm/%facetapi_dependencies/dependencies'] = array( 'title' => 'Configure facet dependencies', 'load arguments' => array(4), 'page callback' => 'drupal_get_form', 'page arguments' => array('facetapi_facet_dependencies_form', 4, 5, 6), 'access callback' => 'facetapi_access_callback', 'type' => MENU_LOCAL_ACTION, 'context' => MENU_CONTEXT_INLINE, 'weight' => -10, 'file' => 'facetapi.admin.inc', ); $items['admin/config/search/facetapi/%facetapi_adapter/%facetapi_realm/%facetapi_filters/filters'] = array( 'title' => 'Configure facet filters', 'load arguments' => array(4), 'page callback' => 'drupal_get_form', 'page arguments' => array('facetapi_facet_filters_form', 4, 5, 6), 'access callback' => 'facetapi_access_callback', 'type' => MENU_LOCAL_ACTION, 'context' => MENU_CONTEXT_INLINE, 'weight' => -5, 'file' => 'facetapi.admin.inc', ); $items['admin/config/search/facetapi/%facetapi_adapter/%facetapi_realm/%facetapi_facet/export'] = array( 'title' => 'Export facet configuration', 'load arguments' => array(4), 'page callback' => 'drupal_get_form', 'page arguments' => array('facetapi_export_form', 4, 5, 6), 'access callback' => 'facetapi_access_callback', 'type' => MENU_NORMAL_ITEM, 'file' => 'facetapi.admin.inc', ); $items['admin/config/search/facetapi/%facetapi_adapter/%facetapi_realm/%facetapi_facet/revert'] = array( 'title' => 'Revert facet configuration', 'load arguments' => array(4), 'page callback' => 'drupal_get_form', 'page arguments' => array('facetapi_revert_form', 4, 5, 6), 'access callback' => 'facetapi_access_callback', 'type' => MENU_NORMAL_ITEM, 'file' => 'facetapi.admin.inc', ); return $items; } /** * Implements hook_ctools_plugin_type(). */ function facetapi_ctools_plugin_type() { return array( 'adapters' => array( 'use hooks' => TRUE, ), 'dependencies' => array( 'use hooks' => TRUE, ), 'empty_behaviors' => array( 'use hooks' => TRUE, ), 'filters' => array( 'use hooks' => TRUE, ), 'query_types' => array( 'use hooks' => TRUE, ), 'url_processors' => array( 'use hooks' => TRUE, ), 'widgets' => array( 'use hooks' => TRUE, ), ); } /** * Implements hook_theme(). */ function facetapi_theme() { return array( 'facetapi_title' => array( 'variables' => array('title' => NULL, 'facet' => array()), 'file' => 'facetapi.theme.inc', ), 'facetapi_facet_missing' => array( 'variables' => array('field_name' => NULL), 'file' => 'facetapi.theme.inc', ), 'facetapi_count' => array( 'variables' => array('count' => NULL), 'file' => 'facetapi.theme.inc', ), 'facetapi_link_inactive' => array( 'variables' => array( 'text' => NULL, 'path' => NULL, 'options' => array(), 'count' => 0, ), 'file' => 'facetapi.theme.inc', ), 'facetapi_link_active' => array( 'variables' => array('text' => NULL, 'path' => NULL, 'options' => array()), 'file' => 'facetapi.theme.inc', ), 'facetapi_deactivate_widget' => array( 'variables' => array('text' => NULL), 'file' => 'facetapi.theme.inc', ), 'facetapi_accessible_markup' => array( 'variables' => array('text' => NULL, 'active' => NULL), 'file' => 'facetapi.theme.inc', ), 'facetapi_realm_settings_table' => array( 'render element' => 'element', 'file' => 'facetapi.admin.inc', ), 'facetapi_sort_settings_table' => array( 'render element' => 'element', 'file' => 'facetapi.admin.inc', ), 'facetapi_filter_settings_table' => array( 'render element' => 'element', 'file' => 'facetapi.admin.inc', ), ); } /** * Returns the access callback. * * Custom access callback. Checks if the user has either the "administer search" * OR "administer facets" permissions. * * @param stdObject|NULL $account * (optional) The account to check, if not given use currently logged in user. * * @return bool * TRUE if the user has access to the resource, FALSE otherwise. */ function facetapi_access_callback($account = NULL) { global $user; if (!isset($account)) { $account = $user; } return user_access('administer search', $account) || user_access('administer facets', $account); } /** * Implements hook_permission(). */ function facetapi_permission() { return array( 'administer facets' => array( 'title' => t('Administer Facets'), ), ); } /** * Implements hook_i18n_string_info(). */ function facetapi_i18n_string_info() { $groups['facetapi'] = array( 'title' => t('Facet API'), 'description' => t('Translatable link text.'), 'format' => FALSE, 'list' => TRUE, ); return $groups; } /** * Implements hook_i18n_string_list(). */ function facetapi_i18n_string_list($group) { $strings = $texts = array(); if ($group == 'facetapi') { // Get all enabled facets by looping over all searchers and realms. foreach (facetapi_get_searcher_info() as $searcher => $searcher_info) { $adapter = facetapi_adapter_load($searcher_info['name']); foreach (facetapi_get_realm_info() as $realm) { // Retrieve the "Show more/fewer" strings from the facet settings. foreach ($adapter->getEnabledFacets() as $facet) { $settings = $adapter->getFacetSettings($facet, $realm); // Avoid adding duplicate strings by using the string itself as key. $strings['facetapi']['link_text'][$settings->settings['facet_more_text']]['text'] = $settings->settings['facet_more_text']; $strings['facetapi']['link_text'][$settings->settings['facet_fewer_text']]['text'] = $settings->settings['facet_fewer_text']; // If title has been overridden, we should translate it. if ($settings->settings['title_override']) { $strings['facetapi']['title_text'][$settings->settings['title']]['text'] = $settings->settings['title']; } } } } } return $strings; } /** * Instantiates the adapter plugin associated with the searcher. * * @param $searcher * The machine readable name of searcher. * * @return FacetapiAdapter * The adapter object, FALSE if the object can't be loaded. */ function facetapi_adapter_load($searcher) { $adapters = &drupal_static(__FUNCTION__, array()); if (!isset($adapters[$searcher])) { $searcher_info = facetapi_get_searcher_info(); if (isset($searcher_info[$searcher]['adapter'])) { ctools_include('plugins'); $id = $searcher_info[$searcher]['adapter']; $class = ctools_plugin_load_class('facetapi', 'adapters', $id, 'handler'); $adapters[$searcher] = ($class) ? new $class($searcher_info[$searcher]) : FALSE; } else { $adapters[$searcher] = FALSE; } } return $adapters[$searcher]; } /** * Loads the dependency plugins associated with the facet. * * @param string $facet_name * The machine readable name of the facet. * @param string $searcher * The machine readable name of the searcher module. * * @return array * An array of FacetapiDependency objects, FALSE if no plugins. */ function facetapi_dependencies_load($facet_name, $searcher) { $dependencies = array(); $facet = facetapi_facet_load($facet_name, $searcher); if ($facet && ($adapter = facetapi_adapter_load($searcher))) { foreach ($facet['dependency plugins'] as $id) { // NOTE: CTools plugin component is loaded by facetapi_adapter_load(). $class = ctools_plugin_load_class('facetapi', 'dependencies', $id, 'handler'); $settings = $adapter->getFacet($facet)->getSettings(); $dependencies[] = new $class($id, $adapter, $facet, $settings); } } return ($dependencies) ? $dependencies : FALSE; } /** * Returns array of filter options available to the facet. * * @param string $facet_name * The machine readable name of the facet. * @param string $searcher * The machine readable name of the searcher. * * @return array * An array of FacetapiFilter objects, FALSE if no plugins. */ function facetapi_filters_load($facet_name, $searcher) { $filters = array('plugins' => array()); if ($filters['facet'] = facetapi_facet_load($facet_name, $searcher)) { $filters['plugins'] = facetapi_get_filters($filters['facet']); } return ($filters['plugins']) ? $filters : FALSE; } /** * Returns a realm definition. * * @param string $realm_name * The machine readable name of the realm. * * @return array * An array containing the realm definition, FALSE if the realm is invalid. * - name: The machine name of the realm. * - label: The human readable name of the realm displayed in the admin UI. * - description: The description of the realm displayed in the admin UI. * - element type: The type of element facets are rendered as, such as 'links' * or 'form elements'. * - default widget: The default widget plugin id for facets in the realm. * - settings callback: A callback that alters the realm settings form. * - sortable: Whether the facets can be sorted via the admin UI. * - weight: The weight of the realm's menu item in comparison to the others. */ function facetapi_realm_load($realm_name) { $realm_info = facetapi_get_realm_info(); return (isset($realm_info[$realm_name])) ? $realm_info[$realm_name] : FALSE; } /** * Returns a facet definition. * * @param string $facet_name * The machine readable name of the facet. * @param string $searcher * The machine readable name of the searcher. * * @return array * An array containing the facet definition, FALSE if the facet is invalid. * - name: Machine readable name of the facet. * - label: Human readable name of the facet displayed in settings forms. * - description: Description of the facet displayed in settings forms. * - field: The field name used by the backend to store and retrieve data from * the search index it is associated with. * - field alias: The query string variable inside of the filter key used to * pass the filter information through the query string. * - field api name: The machine readable name of the Field API field data the * facet is associated with, FALSE if it is not associated with a field. * - field api bundles: An array of entity names that this field contains * bundle information for. * - query types: The query type plugins that that this facet supports. For * example, numeric fields support "term" and "range_filter" queries. * - alter callbacks: Callbacks that alter the initialized render array * returned by the query type plugin. Defaults to an empty array. * - dependency plugins: An array of dependency plugin IDs that are supported * by this facet. * - default widget: The widget plugin ID used if no plugin has been selected * or the one selected is not valid. * - allowed operators: An array keyed by operator constant to boolean values * specifying whether the operator is supported. * - facet missing allowed: Whether or not missing facets are allowed. * - facet mincount allowed: Whether or not the facet supports the "minimum * facet count" setting. * - weight: The weight of the facet * - map callback: The callback used to map the raw values returned by the * index to something human readable. * - map options: An array of options passed to the map callback. * - hierarchy callback: A callback that maps the parent / child relationships * of the facet data, defaults to FALSE meaning the list is flat. * - values callback: In instances where facet data is not returned by the * backend, provide a list of values that can be used. * - min callback: For facets containing ranges, a callback returning the * minimum value in the index. * - max callback: For facets containing ranges, a callback returning the * maximum value in the index. * - default sorts: An array of available sorts. Each item is an array * containing two values, the first being the item being filtered on, the * second being the SORT_* constant. */ function facetapi_facet_load($facet_name, $searcher) { $facet_info = facetapi_get_facet_info($searcher); return (isset($facet_info[$facet_name])) ? $facet_info[$facet_name] : FALSE; } /** * Returns all defined searcher definitions. * * @return array * An array of searcher information. Each array is keyed by the machine * readable searcher name and contains the following items: * - name: The machine readable name of the searcher. * - label: The human readable name of the searcher displayed in the admin UI. * - adapter: The adapter plugin ID associated with the searcher. * - url processor: The URL processor plugin ID associated with the searcher. * - types: An array containing the types of content indexed by the searcher. * A type is usually an entity such as 'node', but it can be a non-entity * value as well. * - path: The MENU_DEFAULT_LOCAL_TASK item which the admin UI page is added * to as a MENU_LOCAL_TASK. An empty string if the backend manages the admin * UI menu items internally. * - supports facet missing: TRUE if the searcher supports "missing" facets. * - supports facet mincount: TRUE if the searcher supports the minimum facet * count setting. * - include default facets: TRUE if the searcher should include the facets * defined in facetapi_facetapi_facet_info() when indexing node content, * FALSE if they should be skipped. */ function facetapi_get_searcher_info() { $searcher_info = array(); foreach (module_implements('facetapi_searcher_info') as $module) { // Iterates over the module's searcher definition. $searchers = (array) module_invoke($module, 'facetapi_searcher_info'); foreach ($searchers as $searcher => $info) { // @see http://drupal.org/node/1167974 // Converts "type" to an array and stores in "types". // @todo Remove in later versions. if (isset($info['type']) && !isset($info['types'])) { $info['types'] = array($info['type']); } // @see http://drupal.org/node/1304010 // Converts "url_processor" to "url processor" for consistency. // @todo Remove in later versions. if (isset($info['url_processor']) && !isset($info['url processor'])) { $info['url processor'] = $info['url_processor']; } $info += array( 'module' => $module, 'name' => $searcher, 'path' => '', 'types' => array('node'), 'url processor' => 'standard', 'supports facet missing' => FALSE, 'supports facet mincount' => FALSE, 'include default facets' => TRUE, ); // @see http://drupal.org/node/1167974 // Makes sure old style "type" is present. if (!isset($info['type'])) { $info['type'] = $info['types'][key($info['types'])]; } // Maps "types" so we can do faster lookups via isset(). $info['types'] = drupal_map_assoc($info['types']); $searcher_info[$searcher] = $info; } } drupal_alter('facetapi_searcher_info', $searcher_info); array_walk($searcher_info, 'facetapi_map_assoc', 'types'); return $searcher_info; } /** * Returns a list of active searchers. * * An active searcher means that facet data is parsed and processed by the * backend. Any searcher's adapter who's FacetapiAdapter::addActiveFilters() was * called is automatically added to this list. * * @return array * An associative array of active adapters */ function facetapi_get_active_searchers() { $searchers = &drupal_static('facetapi_active_searchers', array()); return $searchers; } /** * Returns all defined realm definitions. * * @return array * An array of realm definitions. Each definition is an array keyed by the * machine readable name of the realm. See the return value of the * facetapi_realm_load() function for the structure of the definitions. */ function facetapi_get_realm_info() { $realm_info = &drupal_static(__FUNCTION__); if (NULL === $realm_info) { $realm_info = module_invoke_all('facetapi_realm_info'); foreach ($realm_info as $realm_name => $realm) { $realm_info[$realm_name] += array( 'name' => $realm_name, 'label' => $realm_name, 'description' => '', 'default widget' => '', 'settings callback' => FALSE, 'element type' => 'links', 'sortable' => TRUE, 'weight' => 0, ); } drupal_alter('facetapi_realm_info', $realm_info); uasort($realm_info, 'drupal_sort_weight'); } return $realm_info; } /** * Returns all defined facet definitions available to the searcher. * * @param string $searcher * A string containing the machine readable name of the searcher. * * @return array * An array of facet definitions. Each definition is an array keyed by the * machine readable name of the facet. See the return value of the * facetapi_facet_load() function for the structure of the definitions. */ function facetapi_get_facet_info($searcher) { $facet_info = &drupal_static(__FUNCTION__, array()); // Gets facet info if we haven't gotten it already. if (!isset($facet_info[$searcher])) { // Builds cache ID. global $language; $cid = 'facetapi:facet_info:' . $searcher . ':' . $language->language; // Checks if our results are cached. $cache = cache_get($cid); if (!empty($cache->data)) { $facet_info[$searcher] = $cache->data; } else { $searcher_info = facetapi_get_searcher_info(); $facet_info[$searcher] = array(); // Invokes hook_facetapi_facet_info(), normalizes facets. foreach (module_implements('facetapi_facet_info') as $module) { $facets = call_user_func($module . '_facetapi_facet_info', $searcher_info[$searcher]); if (!$facets || !is_array($facets)) { $facets = array(); } // Iterates over facet definitions, merges defaults. foreach ($facets as $facet_name => $info) { // @see http://drupal.org/node/1161434 // Converts "query type" to an array and stores in "query types". // @todo Remove in later versions. if (isset($info['query type']) && !isset($info['query types'])) { $info['query types'] = array($info['query type']); } $facet_info[$searcher][$facet_name] = $info; $facet_info[$searcher][$facet_name] += array( 'name' => $facet_name, 'label' => $facet_name, 'description' => '', 'field' => $facet_name, 'field alias' => isset($info['field']) ? $info['field'] : $facet_name, 'field api name' => FALSE, 'field api bundles' => array(), 'query types' => array('term'), 'alter callbacks' => array(), 'dependency plugins' => array(), 'default widget' => FALSE, 'allowed operators' => array( FACETAPI_OPERATOR_AND => TRUE, FACETAPI_OPERATOR_OR => TRUE ), 'facet missing allowed' => FALSE, 'facet mincount allowed' => FALSE, 'weight' => 0, 'map callback' => FALSE, 'map options' => array(), 'hierarchy callback' => FALSE, 'values callback' => FALSE, 'min callback' => FALSE, 'max callback' => FALSE, 'default sorts' => array( array('active', SORT_DESC), array('count', SORT_DESC), array('display', SORT_ASC), ), ); // @see http://drupal.org/node/1161434 // Makes sure old style "query type" is present. // @todo Remove in later versions. if (!isset($facet_info[$searcher][$facet_name]['query type'])) { $type = key($facet_info[$searcher][$facet_name]['query types']); $facet_info[$searcher][$facet_name]['type'] = $type; } } } // Invokes alter hook, sorts and returns. drupal_alter('facetapi_facet_info', $facet_info[$searcher], $searcher_info[$searcher]); array_walk($facet_info[$searcher], 'facetapi_map_assoc', 'field api bundles'); uasort($facet_info[$searcher], 'drupal_sort_weight'); // Caches the result. cache_set($cid, $facet_info[$searcher], 'cache', CACHE_TEMPORARY); } } return $facet_info[$searcher]; } /** * Implements hook_field_create_instance(). */ function facetapi_field_create_instance($instance) { cache_clear_all('facetapi:facet_info:', 'cache', TRUE); } /** * Implements hook_field_delete_instance(). */ function facetapi_field_delete_instance($instance) { cache_clear_all('facetapi:facet_info:', 'cache', TRUE); } /** * Wrapper around drupal_map_assoc() for a key in all items of an array. * * Useful as an array_walk() callback. * * @param array &$array * The array being modified. * @param string $name * The key of the array being modified, usually the name of a definition. * @param array $key * The key in the array being passed to drupal_map_assoc(). */ function facetapi_map_assoc(&$array, $name, $key) { if (array_key_exists($key, $array)) { $array[$key] = drupal_map_assoc($array[$key]); } } /** * Returns all sort definitions. * * @return array * An associative array of sort definitions keyed by sort name. Each sort * definition contains: * - name: The machine readable name of the sort. * - title: The human readable name of the sort displayed in the admin UI. * - callback: The uasort() callback the render array is passed to. * - description: The description of the sort displayed in the admin UI. * - weight: The default weight of the sort specifying its processing order. */ function facetapi_get_sort_info() { $sort_info = &drupal_static(__FUNCTION__); if (NULL === $sort_info) { $sort_info = module_invoke_all('facetapi_sort_info'); foreach ($sort_info as $sort_name => $info) { $sort_info[$sort_name] += array( 'name' => $sort_name, 'label' => $sort_name, 'callback' => '', 'requirements' => array(), 'description' => '', 'weight' => 0, ); } drupal_alter('facetapi_sort_info', $sort_info); } return $sort_info; } /** * Returns all filter definitions available to the facet. * * Each filter plugin must pass all the requirements checks specified in its * definition. Only plugins that pass all requirements are returned. * * @param array $facet * The facet definition as returned by facetapi_facet_load(). * * @return array * An associative array of filter plugin definitions keyed by the plugin ID. * Each filter plugin definition contains: * - handler: An associative array containing: * - label: The human readable name of the plugin displayed in the admin UI. * - description: The description of the plugin displayed in the admin UI. * - class: The class containing the plugin. */ function facetapi_get_filters(array $facet) { $plugins = array(); // Iterates over all defined plugins. foreach (ctools_get_plugins('facetapi', 'filters') as $id => $plugin) { $plugin['handler'] += array( 'label' => $id, 'description' => '', 'requirements' => array(), ); // Checks requirements. if (facetapi_check_requirements($plugin['handler']['requirements'], array(), $facet)) { $plugins[$id] = $plugin; } } return $plugins; } /** * Gets raw settings from the database, caches as a static variable. * * Avoid using this function directly as it will not load default settings. Use * the FacetapiAdapter::getFacetSettings*() method instead. * * @param string $searcher * A string containing the searcher. * * @return array * An array of settings keyed by name. * * @see FacetapiAdapter::getFacetSettings() * @see FacetapiAdapter::getFacetSettingsGlobal() */ function facetapi_get_searcher_settings($searcher) { $settings = &drupal_static(__FUNCTION__, array()); if (!isset($settings[$searcher])) { ctools_include('export'); $args = array('searcher' => $searcher); $settings[$searcher] = ctools_export_load_object('facetapi', 'conditions', $args); } return $settings[$searcher]; } /** * Returns all enabled facet definitions available to the searcher. * * If a realm is passed, this function returns all facets enabled in the realm. * If no realm is passed, this function returns all facets that are enabled in * at least one realm. * * @param string $searcher * The machine readable name of the searcher. * @param string $realm_name * The machine readable name of the realm, pass NULL to return all facets that * are enabled in at least one realm. * * @return array * An array of facet definitions. Each definition is an array keyed by the * machine readable name of the facet. See the return value of the * facetapi_facet_load() function for the structure of the definitions. */ function facetapi_get_enabled_facets($searcher, $realm_name = NULL) { $enabled_facets = &drupal_static(__FUNCTION__, array()); $cid = $searcher . ':' . (string) $realm_name; if (!isset($enabled_facets[$cid])) { $facets = array(); // Gets cached settings, finds enabled facets. $cached = facetapi_get_searcher_settings($searcher); foreach ($cached as $name => $settings) { $test_enabled = (NULL === $realm_name || $realm_name == $settings->realm); if ($test_enabled && $settings->enabled) { $facets[$settings->facet] = $settings->facet; } } // Gets facet definitions for all enabled facets. $facet_info = facetapi_get_facet_info($searcher); $enabled_facets[$cid] = array_intersect_key($facet_info, $facets); // Alter enabled facets on the fly. drupal_alter('facetapi_enabled_facets', $enabled_facets[$cid], $searcher, $realm_name); } return $enabled_facets[$cid]; } /** * Translates a string via the translator module. * * @param string $name * The name of the string in "textgroup:object_type:object_key:property_name" * format. * @param string $string * The string being translated. * @param string $langcode * The language code to translate to a language other than what is used to * display the page. Defaults to NULL, which uses the current language. * * @return string * The translated string. */ function facetapi_translate_string($name, $string, $langcode = NULL) { if ($module = variable_get('facetapi:translator_module', NULL)) { $function = $module . '_facetapi_translate_string'; if (function_exists($function)) { $string = $function($name, $string, $langcode); } } return $string; } /** * Tests whether a searcher is active or not. * * @param string $searcher * The machine readable name of the searcher. * * @return FacetapiAdapter * The adapter object, FALSE if the object can't be loaded. */ function facetapi_is_active_searcher($searcher) { $searchers = facetapi_get_active_searchers(); return (isset($searchers[$searcher])); } /** * Adds an active searcher to the list. * * @param string $searcher * The machine readable name of the searcher. * * @see facetapi_get_active_searchers(); */ function facetapi_add_active_searcher($searcher) { $searchers = &drupal_static('facetapi_active_searchers', array()); $searchers[$searcher] = $searcher; } /** * Tests whether a single facet is enabled in a given realm. * * @param string $searcher * The machine readable name of the searcher. * @param string $realm_name * The machine readable name of the realm, pass NULL to test if the facet is * enabled in at least one realm. * @param string $facet_name * The machine readable name of the facet. * * @return bool * A boolean flagging whether the facet is enabled in the passed realm. */ function facetapi_facet_enabled($searcher, $realm_name, $facet_name) { $enabled_facets = facetapi_get_enabled_facets($searcher, $realm_name, $facet_name); return isset($enabled_facets[$facet_name]); } /** * Builds a facet realm. * * Converts the facet data into a render array suitable for passing to the * drupal_render() function. * * @param string $searcher * The machine readable name of the searcher. * @param string $realm_name * The machine readable name of the realm. * * @return array * The realm's render array. */ function facetapi_build_realm($searcher, $realm_name) { $adapter = facetapi_adapter_load($searcher); return ($adapter) ? $adapter->buildRealm($realm_name) : array(); } /** * Checks requirements. * * Requirements fail if at least one requirements callback returns FALSE. Note * that if no requirement callbacks are passed, this function will return TRUE. * * @param array $requirements * The requirements keyed by callback to options. * @param array $realm * The realm definition. * @param array $facet * The facet definition. * * @return bool * A boolean flagging whether all requirements were passed. */ function facetapi_check_requirements(array $requirements, array $realm, array $facet, $operator = 'AND') { $return = TRUE; module_load_include('inc', 'facetapi', 'facetapi.requirements'); foreach ($requirements as $callback => $options) { if (!call_user_func($callback, $realm, $facet, $options, $operator)) { $return = FALSE; break; } } return $return; } /** * Enables or disables a facet for this page load only. * * @param string $searcher * The machine readable name of the searcher. * @param string $realm_name * The machine readable name of the realm, pass NULL for all realms. * @param string $facet_name * The machine readable name of the facet. * @param bool $status * A boolean flagging whether the facet is enabled or disabled. * @param bool $batch_process * A boolean flagging whether batch processing is being performed. If set to * TRUE, the list of enabled facets won't be rebuild and the active items * won't be re-processed. Note that these tasks will have to be performed * manually in order for the status to be properly set. */ function facetapi_set_facet_status($searcher, $realm_name, $facet_name, $status, $batch_process) { // Rebuild static if not batch processing. if (!$batch_process) { drupal_static('facetapi_get_enabled_facets', array(), TRUE); } // Pulls the list of enabled facets so we can modify it here. facetapi_get_enabled_facets($searcher, $realm_name); $enabled_facets = &drupal_static('facetapi_get_enabled_facets', array()); // Performs the operation by setting or unsetting the facet. $cid = $searcher . ':' . (string) $realm_name; if ($status && !isset($enabled_facets[$cid][$facet_name])) { if ($facet = facetapi_facet_load($facet_name, $searcher)) { // Add facet to static, which enables it. $enabled_facets[$cid][$facet_name] = $facet; // If facet isn't already globally enabled, enable it. if (!isset($enabled_facets[$searcher . ':'][$facet_name])) { // Ensure sure static is set before modifying it. facetapi_get_enabled_facets($searcher, NULL); $enabled_facets[$searcher . ':'][$facet_name] = $facet; } } } elseif (!$status && isset($enabled_facets[$cid][$facet_name])) { // Removes facet to static, which disables it. unset($enabled_facets[$cid][$facet_name]); // If acting globally, disable facet in all realms. if (!$realm_name) { foreach (facetapi_get_realm_info() as $realm) { // Ensure sure static is set before unsetting the facet. facetapi_get_enabled_facets($searcher, $realm['name']); unset($enabled_facets[$searcher . ':' . $realm['name']][$facet_name]); } } } else { return; } // Re-process the active items since the list of active facets has changed. if (!$batch_process && ($adapter = facetapi_adapter_load($searcher))) { $adapter->processActiveItems(); } } /** * Enables a facet for this page load only. * * If you are enabling facets in the block realm, you will have to force the * delta mapping so that the block can be configured even if it is disabled via * the Facet API interface. Otherwise you will not be able to assign the block * to a region because it won't be available in admin/structure/block. * * @param $searcher * The machine readable name of the searcher. * @param $realm_name * The machine readable name of the realm, pass NULL for all realms. * @param $facet_name * The machine readable name of the facet. * @param $batch_process * A boolean flagging whether batch processing is being performed. * * @see facetapi_set_facet_status() * @see hook_facetapi_force_delta_mapping() */ function facetapi_set_facet_enabled($searcher, $realm_name, $facet_name, $batch_process = FALSE) { return facetapi_set_facet_status($searcher, $realm_name, $facet_name, TRUE, $batch_process); } /** * Disables a facet for this page load only. * * @param string $searcher * The machine readable name of the searcher. * @param string $realm_name * The machine readable name of the realm, pass NULL for all realms. * @param string $facet_name * The machine readable name of the facet. * @param bool $batch_process * A boolean flagging whether batch processing is being performed. * * @see facetapi_set_facet_status() */ function facetapi_set_facet_disabled($searcher, $realm_name, $facet_name, $batch_process = FALSE) { return facetapi_set_facet_status($searcher, $realm_name, $facet_name, FALSE, $batch_process); } /** * Sets the facet status in a given realm, stores settings in the database. * * @param FacetapiAdapter $adapter * The adapter object of the searcher the settings are being modified for. * @param array $realm * The realm definition as returned by facetapi_realm_load(). * @param array $facet * The facet definition as returned by facetapi_facet_load(). * @param bool $status * Flags whether or not the facet is being enabled or disabled. * @param bool $weight * If the realm is sortable, allows the assigning of a weight. Pass FALSE to * maintain the previously stored value. * @param bool $batch_process * A boolean flagging whether batch processing is being performed. If set to * TRUE, the caches and statics won't be reset. * * @reutrn * TRUE if the operation succeeded, FALSE otherwise. */ function facetapi_save_facet_status(FacetapiAdapter $adapter, array $realm, array $facet, $status, $weight, $batch_process) { // Loads the realm settings, sets enabled flag and weight. $settings = $adapter->getFacet($facet)->getSettings($realm); $settings->enabled = ($status) ? 1 : 0; if (FALSE !== $weight) { $settings->settings['weight'] = $realm['sortable'] ? $weight : 0; } // Saves the settings in the database, stores the result. // NOTE: CTools export componenet loaded in the getSettings() method. $success = (FALSE !== ctools_export_crud_save('facetapi', $settings)); // Clears caches and statics if we are not batch processing. if ($success && !$batch_process) { drupal_static('facetapi_get_searcher_settings', array(), TRUE); drupal_static('facetapi_get_enabled_facets', array(), TRUE); if ('block' == $realm['name']) { cache_clear_all(NULL, 'cache_block'); cache_clear_all('facetapi:delta_map', 'cache'); } } return $success; } /** * Enables a facet in a given realm, stores settings in the database. * * @param FacetapiAdapter $adapter * The adapter object of the searcher the settings are being modified for. * @param array $realm * The realm definition as returned by facetapi_realm_load(). * @param array $facet * The facet definition as returned by facetapi_facet_load(). * @param string $weight * If the realm is sortable, allows the assigning of a weight. Pass FALSE to * maintain the previously stored value. * @param bool $batch_process * A boolean flagging whether batch processing is being performed. * * @reutrn * TRUE if the operation succeeded, FALSE otherwise. */ function facetapi_save_facet_enabled(FacetapiAdapter $adapter, array $realm, array $facet, $weight = FALSE, $batch_process = FALSE) { return facetapi_save_facet_status($adapter, $realm, $facet, TRUE, $weight, $batch_process); } /** * Disables a facet in a given realm, stores settings in the database. * * @param FacetapiAdapter $adapter * The adapter object of the searcher the settings are being modified for. * @param array $realm * The realm definition as returned by facetapi_realm_load(). * @param array $facet * The facet definition as returned by facetapi_facet_load(). * @param bool $weight * If the realm is sortable, allows the assigning of a weight. Pass FALSE to * maintain the previously stored value. * @param bool $batch_process * A boolean flagging whether batch processing is being performed. * * @reutrn bool * TRUE if the operation succeeded, FALSE otherwise. */ function facetapi_save_facet_disabled(FacetapiAdapter $adapter, array $realm, array $facet, $weight = FALSE, $batch_process = FALSE) { return facetapi_save_facet_status($adapter, $realm, $facet, FALSE, $weight, $batch_process); } /** * Translates string for FacetAPI. */ function facetapi_i18n_string_translate($name, $string) { return i18n_string_translate( $name, $string, array( 'format' => I18N_STRING_FILTER_XSS, ) ); }