facetapi_pretty_paths.module in Facet API Pretty Paths 7
Same filename and directory in other branches
The FacetAPI Pretty Paths module.
File
facetapi_pretty_paths.moduleView source
<?php
/**
* @file
* The FacetAPI Pretty Paths module.
*/
/**
* Implements hook_facetapi_url_processors().
*/
function facetapi_pretty_paths_facetapi_url_processors() {
return array(
'pretty_paths' => array(
'handler' => array(
'label' => t('Pretty paths'),
'class' => 'FacetapiUrlProcessorPrettyPaths',
),
),
);
}
/**
* Allows for alterations to the searcher definitions.
*
* @param array &$searcher_info
* The return values of hook_facetapi_searcher_info() implementations.
*
* Implements hook_facetapi_searcher_info().
*/
function facetapi_pretty_paths_facetapi_searcher_info_alter(array &$searcher_info) {
foreach ($searcher_info as &$info) {
// Activate pretty paths optionally per searcher, as configured.
$id = 'facetapi_pretty_paths_searcher_' . $info['name'];
$info['url processor'] = variable_get($id) ? 'pretty_paths' : 'standard';
$info['facetapi pretty paths coder'] = 'default';
}
}
/**
* Add pretty path settings to facet configuration.
*
* Implements hook_form_BASE_FORM_ID_alter().
*/
function facetapi_pretty_paths_form_facetapi_facet_display_form_alter(&$form, &$form_state, $form_id) {
if (!user_access('administer facetapi pretty paths')) {
return;
}
// Get global facet settings.
$adapter = $form['#facetapi']['adapter'];
$processor = new FacetapiUrlProcessorPrettyPaths($adapter);
$facet = $form['#facetapi']['facet'];
$pretty_paths_alias = $processor
->getFacetPrettyPathsAlias($facet);
// Add pretty paths alias option to global facet settings.
$form['global']['pretty_paths_alias'] = array(
'#type' => 'textfield',
'#title' => t('Pretty path alias'),
'#default_value' => $pretty_paths_alias,
'#description' => t('Pretty paths will be generated as "search/url/segment1/segment2/".') . '<br/>' . t('By default, a segment will look like: "@default_segment".', array(
'@default_segment' => '<alias>/<value>',
)) . '<br/>' . t('For taxonomy terms it outputs the id as well: "@taxonomy_segment".', array(
'@taxonomy_segment' => '<alias>/<term-name>-<term-id>',
)),
);
// Taxonomy Pathauto Coder settings.
// 1. Check if pathauto is enabled.
// 2. Check for Apache Solr taxonomy term fields.
// 3. Check for Search API taxonomy term fields.
if (module_exists('pathauto') && (!empty($facet['map options']['module_name']) && $facet['map options']['module_name'] == 'Taxonomy' || !empty($facet['field type']) && $facet['field type'] == 'taxonomy_term')) {
$facet_settings = $adapter
->getFacetSettingsGlobal($facet);
$form['global']['pretty_paths_taxonomy_pathauto'] = array(
'#type' => 'checkbox',
'#title' => t('Reuse term aliases'),
'#default_value' => !empty($facet_settings->settings['pretty_paths_taxonomy_pathauto']) ? TRUE : FALSE,
'#description' => t('If set, the term alias from the pathauto settings will be reused, which avoids term ids in the facet aliases. This setting only works if the default taxonomy path pattern \'[term:vocabulary]/[term:name]\' is used.'),
);
$options = array();
foreach (taxonomy_get_vocabularies() as $voc) {
$options[$voc->machine_name] = $voc->name;
}
$vocabulary = facetapi_pretty_paths_taxonomy_facet_get_vocabulary($facet);
$default_voc_name = $vocabulary ? $vocabulary->machine_name : array();
$form['global']['pretty_paths_taxonomy_pathauto_vocabulary'] = array(
'#type' => 'select',
'#title' => t('Vocabulary for pathauto'),
'#options' => $options,
'#default_value' => !empty($facet_settings->settings['pretty_paths_taxonomy_pathauto_vocabulary']) ? $facet_settings->settings['pretty_paths_taxonomy_pathauto_vocabulary'] : $default_voc_name,
'#description' => t('Select the appropriate vocabulary for this facet. In case the facet values come from a taxonomy field, the appropriate vocabulary is calculated.'),
'#disabled' => !empty($default_voc_name),
'#states' => array(
'visible' => array(
':input[name="global[pretty_paths_taxonomy_pathauto]"]' => array(
'checked' => TRUE,
),
),
),
);
}
$form['#submit'][] = 'facetapi_pretty_paths_facetapi_facet_display_form_submit';
}
/**
* Additional form submission handler for 'facetapi_facet_display_form'.
*/
function facetapi_pretty_paths_facetapi_facet_display_form_submit($form, &$form_state) {
// Clear the facet api cache as the settings for the pretty paths might have
// changed.
cache_clear_all('facetapi:facet_info:', 'cache', TRUE);
}
/**
* Helper function that returns the vocabulary for a taxonomy facet.
*/
function facetapi_pretty_paths_taxonomy_facet_get_vocabulary($facet_info) {
if (isset($facet_info['field'])) {
$facet_field_name = $facet_info['field'];
// The Search API chains properties with ':'. The last taxonomy field in
// this chain is the key for the vocabulary.
// The Apache Solr module only contains Field API names. In this case
// the explode function returns the whole string in the first array
// value.
$exploded = explode(':', $facet_field_name);
foreach (array_reverse($exploded) as $property_name) {
$field_info = field_info_field($property_name);
if ($field_info && isset($field_info['settings']['allowed_values'][0]['vocabulary'])) {
$voc = taxonomy_vocabulary_machine_name_load($field_info['settings']['allowed_values'][0]['vocabulary']);
if ($voc) {
return $voc;
}
}
}
}
return FALSE;
}
/**
* Implements hook_menu().
*/
function facetapi_pretty_paths_menu() {
$items = array();
$items['admin/config/search/facetapi_pretty_paths'] = array(
'title' => 'FacetAPI Pretty Paths',
'description' => 'Configure pretty paths settings',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'facetapi_pretty_paths_admin_form',
),
'access arguments' => array(
'administer facetapi pretty paths',
),
'type' => MENU_NORMAL_ITEM,
);
return $items;
}
/**
* Implements hook_permission().
*/
function facetapi_pretty_paths_permission() {
return array(
'administer facetapi pretty paths' => array(
'title' => t('Administer Facet API Pretty Paths'),
),
);
}
/**
* Administration form.
*/
function facetapi_pretty_paths_admin_form($form, &$form_state) {
// Include necessary ctools inc files.
ctools_include('plugins');
// Allow to enable / disable pretty paths per searcher.
$searcher_info = facetapi_get_searcher_info();
$form['searcher'] = array(
'#type' => 'fieldset',
'#title' => t('Enable pretty paths per searcher'),
'#type' => 'fieldset',
);
foreach (facetapi_get_searcher_info() as $info) {
$id = 'facetapi_pretty_paths_searcher_' . $info['name'];
// Add a checkbox to enable pretty paths per searcher.
$form['searcher'][$id] = array(
'#type' => 'checkbox',
'#title' => t('@searcher', array(
'@searcher' => $info['name'],
)),
'#default_value' => variable_get($id, $info['url processor'] == 'pretty_paths'),
'#description' => t("Use pretty paths for the @searcher_label", array(
"@searcher_label" => $info['label'],
)),
);
// An additional fieldset provides additional options per searcher.
$options = variable_get($id . '_options');
$form['searcher'][$id . '_options'] = array(
'#type' => 'fieldset',
'#title' => t('Options for @searcher', array(
'@searcher' => $info['name'],
)),
'#tree' => TRUE,
'#states' => array(
'visible' => array(
':input[name="' . $id . '"]' => array(
'checked' => TRUE,
),
),
),
);
$form['searcher'][$id . '_options']['sort_path_segments'] = array(
'#type' => 'checkbox',
'#title' => t('Make paths unique by sorting them.'),
'#default_value' => isset($options['sort_path_segments']) ? $options['sort_path_segments'] : FALSE,
'#description' => t("Sorted paths lead to unique, canonical urls. Keep in mind that this will replace the order in which user clicked the facets."),
);
// Allow to select a base path provider plugin.
$base_path_providers = ctools_get_plugins('facetapi_pretty_paths', 'base_path_provider');
$base_path_providers_form_item = array(
'#type' => 'radios',
'#title' => t('Base path provider'),
'#options' => array(),
'#default_value' => isset($options['base_path_provider']) ? $options['base_path_provider'] : 'default',
'#description' => t("Select a base path provider or implement your own using <em>hook_facetapi_pretty_paths_base_path_provider</em>."),
);
foreach ($base_path_providers as $key => $base_path_provider) {
$base_path_providers_form_item['#options'][$key] = $base_path_provider['handler']['label'];
$base_path_providers_form_item[$key]['#description'] = $base_path_provider['handler']['description'];
}
$form['searcher'][$id . '_options']['base_path_provider'] = $base_path_providers_form_item;
}
return system_settings_form($form);
}
/**
* Implements hook_ctools_plugin_type().
*/
function facetapi_pretty_paths_ctools_plugin_type() {
$plugins['base_path_provider'] = array(
'use hooks' => TRUE,
);
$plugins['coders'] = array(
'use hooks' => TRUE,
);
return $plugins;
}
/**
* Implements hook_facetapi_pretty_paths_base_path_provider().
*/
function facetapi_pretty_paths_facetapi_pretty_paths_base_path_provider() {
$base_path_providers = array(
'default' => array(
'handler' => array(
'label' => t('Default base path provider'),
'class' => 'FacetApiPrettyPathsDefaultBasePathProvider',
'description' => 'Calculates the base path by subtracting facet path segments from the current url.',
),
),
'adapter' => array(
'handler' => array(
'label' => t('Adapter base path provider'),
'class' => 'FacetApiPrettyPathsAdapterBasePathProvider',
'description' => 'Relies on the FacetapiAdapter::getSearchPath() method to generate the base path. This one is likely overridden by SearchApiFacetapiAdapter::getSearchPath() or ApacheSolrFacetapiAdapter::getSearchPath().',
),
),
);
// Allow other modules to alter the base path provider definitions.
drupal_alter('facetapi_pretty_paths_base_path_provider', $base_path_providers);
return $base_path_providers;
}
/**
* Implements hook_facetapi_pretty_paths_coders().
*/
function facetapi_pretty_paths_facetapi_pretty_paths_coders() {
$coders = array(
'default' => array(
'handler' => array(
'label' => t('Default pretty paths coder'),
'class' => 'FacetApiPrettyPathsCoderDefault',
),
),
'taxonomy' => array(
'handler' => array(
'label' => t('Taxonomy specific pretty paths coder'),
'class' => 'FacetApiPrettyPathsCoderTaxonomy',
),
),
'taxonomy_pathauto' => array(
'handler' => array(
'label' => t('Taxonomy specific pathauto coder'),
'class' => 'FacetApiPrettyPathsCoderTaxonomyPathauto',
),
),
);
// Allow other modules to alter the coder definitions.
drupal_alter('facetapi_pretty_paths_coders', $coders);
// @todo Remove deprecated 7.x-1.x hook in next major version.
drupal_alter('facetapi_pretty_paths_facetapi_pretty_paths_coders', $coders);
return $coders;
}
/**
* Implements hook_facetapi_facet_info_alter().
*/
function facetapi_pretty_paths_facetapi_facet_info_alter(array &$facet_info, array $searcher_info) {
/*
* In order to get settings for a facet normally we would need to
* load the adapter for a given searcher. However doing so with
* facetapi_adapter_load() causes the adapter class in context
* to be instantiated which in the case of this module results
* in the fetchParams method of the FacetapiUrlProcessorPrettyPaths
* class being called which results in active facets in the URL
* being processed before the logic below can alter the facet
* settings.
*
* The normal way to get facet settings would be via the adapter
* class using getFacetSettings() and/or getFacetSettingsGlobal().
* Instead we have to use the raw settings getter function below.
*/
$searcher_settings = facetapi_get_searcher_settings($searcher_info['name']);
foreach ($facet_info as &$facet) {
$taxonomy_coder = 'taxonomy';
$facet_settings_key = $searcher_info['name'] . '::' . $facet['field'];
if (isset($searcher_settings[$facet_settings_key]) && isset($searcher_settings[$facet_settings_key]->settings)) {
$facet_settings = $searcher_settings[$facet_settings_key];
if (module_exists('pathauto') && !empty($facet_settings->settings['pretty_paths_taxonomy_pathauto'])) {
$taxonomy_coder = 'taxonomy_pathauto';
}
}
// Check for Apache Solr Taxonomy Term fields.
if (!empty($facet['map options']['module_name']) && $facet['map options']['module_name'] == 'Taxonomy') {
$facet['facetapi pretty paths coder'] = $taxonomy_coder;
}
else {
if (!empty($facet['field type']) && $facet['field type'] == 'taxonomy_term') {
$facet['facetapi pretty paths coder'] = $taxonomy_coder;
}
}
}
drupal_static_reset('facetapi_get_enabled_facets');
}
/**
* Helper function for calling coder callbacks.
*/
function facetapi_pretty_paths_coder_callback($callback, $args) {
$id = 'default';
if (isset($args['facet']) && isset($args['facet']['facetapi pretty paths coder'])) {
$id = $args['facet']['facetapi pretty paths coder'];
}
if ($class = ctools_plugin_load_class('facetapi_pretty_paths', 'coders', $id, 'handler')) {
$args = func_get_args();
// Remove $callback from the arguments.
unset($args[0]);
$instance = new $class();
return call_user_func_array(array(
$instance,
$callback,
), $args);
}
}