You are here

mefibs.module in MEFIBS - More exposed forms in blocks 8

Same filename and directory in other branches
  1. 7 mefibs.module

Primarily Drupal hooks and global API functions to manipulate views and to provide an additional block with an exposed filter form.

This is the main module file for Mefibs.

File

mefibs.module
View source
<?php

/**
 * @file
 * Primarily Drupal hooks and global API functions to manipulate views and to
 * provide an additional block with an exposed filter form.
 *
 * This is the main module file for Mefibs.
 */

/**
 * General purpose prefix for mefibs forms.
 */
define('MEFIBS_VIEW_DISPLAY_PREFIX', 'mefibs-form');

/**
 * Implements hook_theme().
 */
function mefibs_theme($existing, $type, $theme, $path) {
  return array(
    'mefibs_views_ui_block_list' => array(
      'render element' => 'form',
      'file' => 'mefibs.theme.inc',
    ),
  );
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function mefibs_form_views_ui_edit_display_form_alter(&$form, $form_state) {
  if (!in_array($form_state['section'], array(
    'pager_options',
    'exposed_form_options',
  ))) {
    return;
  }
  $view = $form_state['view'];
  $display_id = $form_state['display_id'];
  $display = $view
    ->getExecutable()->displayHandlers
    ->get($display_id);
  if (!$display
    ->getOption('exposed_block')) {
    return;
  }
  if (!mefibs_display_is_mefibs_enabled($display)) {
    return;
  }
  $mefibs_options = $display
    ->getOption('mefibs');
  $blocks = $display->extender['mefibs']
    ->getEnabledBlocks();

  // Add block selector for exposed items_per_page options
  if ($form_state['section'] == 'pager_options') {
    $form['options']['pager_options']['expose']['items_per_page']['#weight'] = -1;
    $form['options']['pager_options']['expose']['items_per_page_label']['#weight'] = -1;
    $form['options']['pager_options']['expose']['items_per_page_options']['#weight'] = -1;
    $form['options']['pager_options']['expose']['mefibs_block_items_per_page'] = array(
      '#type' => 'select',
      '#title' => t('Show in block'),
      '#options' => array(
        '' => 'default',
      ) + $blocks,
      '#default_value' => isset($mefibs_options[$display_id]['other']['items_per_page']) ? $mefibs_options[$display_id]['other']['items_per_page'] : '',
      '#states' => array(
        'invisible' => array(
          'input[name="pager_options[expose][items_per_page]"]' => array(
            'checked' => FALSE,
          ),
        ),
      ),
      '#weight' => 0,
    );
    $form['options']['pager_options']['expose']['mefibs_block_offset'] = array(
      '#type' => 'select',
      '#title' => t('Show in block'),
      '#options' => array(
        '' => 'default',
      ) + $blocks,
      '#default_value' => isset($mefibs_options[$display_id]['other']['offset']) ? $mefibs_options[$display_id]['other']['offset'] : '',
      '#states' => array(
        'invisible' => array(
          'input[name="pager_options[expose][offset]"]' => array(
            'checked' => FALSE,
          ),
        ),
      ),
      '#weight' => 1,
    );
  }

  // Add blockselector for exposed form plugin settings.
  if ($form_state['section'] == 'exposed_form_options') {
    $form['options']['mefibs_block_sort'] = array(
      '#type' => 'select',
      '#title' => t('Show in block'),
      '#description' => t('Set where exposed sort items will be displayed.'),
      '#options' => array(
        '' => 'default',
      ) + $blocks,
      '#default_value' => isset($mefibs_options[$display_id]['sort_block']) ? $mefibs_options[$display_id]['sort_block'] : '',
    );
  }
  array_unshift($form['actions']['submit']['#submit'], 'mefibs_form_views_ui_edit_display_form_submit');
}

/**
 * Submit callback for the views_ui_edit_display form.
 */
function mefibs_form_views_ui_edit_display_form_submit($form, &$form_state) {
  $values = $form_state['values'];
  $view = $form_state['view'];
  $display_id = $form_state['display_id'];
  $view
    ->getExecutable()
    ->initDisplay();
  $display = $view
    ->getExecutable()->displayHandlers
    ->get($display_id);
  if (!$display
    ->getOption('exposed_block')) {
    return;
  }
  $mefibs_options = $display
    ->getOption('mefibs');
  if ($form_state['section'] == 'pager_options') {
    $block_items_per_page = $values['pager_options']['expose']['mefibs_block_items_per_page'];
    if ($block_items_per_page != '') {
      $mefibs_options[$display_id]['other']['items_per_page'] = $block_items_per_page;
    }
    else {
      unset($mefibs_options[$display_id]['other']['items_per_page']);
    }
    $block_offset = $values['pager_options']['expose']['mefibs_block_offset'];
    if ($block_offset != '') {
      $mefibs_options[$display_id]['other']['offset'] = $block_offset;
    }
    else {
      unset($mefibs_options[$display_id]['other']['offset']);
    }
    $display
      ->setOption('mefibs', $mefibs_options);
  }
  if ($form_state['section'] == 'exposed_form_options') {
    $block_sort = $values['mefibs_block_sort'];
    $exposed_items = mefibs_get_exposed_items($display);
    if ($block_sort != '') {
      $mefibs_options[$display_id]['sort_block'] = $block_sort;
    }
    else {
      $mefibs_options[$display_id]['sort_block'] = 'default';
    }
    $display
      ->setOption('mefibs', $mefibs_options);
  }
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function mefibs_form_views_ui_config_item_form_alter(&$form, $form_state) {
  $view = $form_state['view'];
  $display_id = $form_state['display_id'];
  $display = $view
    ->getExecutable()->displayHandlers
    ->get($display_id);
  if (!$display
    ->getOption('exposed_block')) {
    return;
  }
  if (!mefibs_display_is_mefibs_enabled($display)) {
    return;
  }
  $section = $form_state['section'];
  $type = $form_state['type'];
  if (!in_array($section, array(
    'filters',
  ))) {
    return;
  }
  $mefibs = $display->extender['mefibs'];
  $section_settings = $display
    ->getOption($section);
  $element_name = $form_state['id'];

  // Check if mefibs is configured
  $mefibs_options = $display
    ->getOption('mefibs');
  $blocks = $mefibs
    ->getEnabledBlocks();
  $default_value = isset($mefibs_options[$display_id][$type][$element_name]) ? $mefibs_options[$display_id][$type][$element_name] : '';
  $element = $section_settings[$element_name];
  if (isset($element['exposed']) && $element['exposed'] && count($blocks)) {
    $form['options']['expose']['mefibs_block'] = array(
      '#type' => 'select',
      '#title' => t('Show in block'),
      '#options' => array(
        '' => 'default',
      ) + $blocks,
      '#default_value' => $default_value,
    );
    array_unshift($form['actions']['submit']['#submit'], 'mefibs_form_views_ui_config_item_form_submit');
  }
}

/**
 * Customer submit callback for the views_ui_config_item_form.
 *
 * React on update of a filter or sort item. Handle submission of our custom
 * form elements and save the configured options into the views_ui cache.
 */
function mefibs_form_views_ui_config_item_form_submit($form, &$form_state) {
  $view = $form_state['view'];
  $display_id = $form_state['display_id'];
  $section = $form_state['section'];
  $view
    ->getExecutable()
    ->initDisplay();
  $display = $view
    ->getExecutable()->displayHandlers
    ->get($display_id);

  // Extract 'filter' or 'sort'.
  $type = substr($section, 0, strlen($section) - 1);
  $element_name = $form_state['id'];
  $values = $form_state['values'];
  $mefibs_options = $display
    ->getOption('mefibs');
  if (!isset($mefibs_options[$display_id][$type]) || !is_array($mefibs_options[$display_id][$type])) {
    $mefibs_options[$display_id][$type] = array();
  }
  $block_id = $values['options']['expose']['mefibs_block'];
  if ($block_id != '') {
    $mefibs_options[$display_id][$type][$element_name] = $block_id;
  }
  else {
    unset($mefibs_options[$display_id][$type][$element_name]);
  }
  $display
    ->setOption('mefibs', $mefibs_options);
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function mefibs_form_views_exposed_form_alter(&$form, $form_state) {
  $view = $form_state['view'];
  $display = $view->display_handler;
  $display_id = $view->current_display;
  if (!mefibs_display_is_mefibs_enabled($display)) {
    return;
  }
  $mefibs = $display->extender['mefibs'];
  $block_id = 'default';
  if (isset($form_state['exposed_form_override']) && isset($form_state['mefibs_block_id'])) {
    $form['mefibs_block_id'] = array(
      '#type' => 'hidden',
      '#name' => 'mefibs_block_id',
      '#value' => $form_state['mefibs_block_id'],
    );
    $block_id = $form_state['mefibs_block_id'];
  }

  // Hide exposed items from other form blocks.
  $mefibs
    ->hideExposedFormItems($form, $block_id);

  // Set default values to reflect the current filter states.
  $mefibs
    ->setDefaultValues($form, $block_id);
}

/**
 * Recursivly assign a value to a form property and all its children.
 *
 * @param array $form
 *   Form API array.
 * @param string $property
 *   The name of the property, that is the array key without the leading #.
 * @param mixed $value
 *   The new value for the property.
 * @param array $exclude
 *   Array with the name of form form children that should not be affected.
 */
function mefibs_set_form_property_recursive(&$form, $property, $value, $exclude = array()) {
  foreach (element_children($form) as $element) {
    if (count($exclude) && in_array($element, $exclude)) {
      continue;
    }
    $form[$element]['#' . $property] = $value;
    if (count(element_children($form[$element]))) {
      mefibs_set_form_property_recursive($form[$element], $property, $value, $exclude);
    }
  }
}

/**
 * Recursivly prefix the #id attribute of all elements in a form.
 *
 * @param array $form
 *   Form API array.
 * @param string $prefix
 *   The string to use as a prefix.
 */
function mefibs_set_form_id_recursive(&$form, $prefix) {
  foreach (element_children($form) as $element) {
    if ($element == 'mefibs_form') {
      continue;
    }
    $form[$element]['#id'] = drupal_html_id($prefix . '-' . $form[$element]['#id']);
    if (count(element_children($form[$element]))) {
      mefibs_set_form_id_recursive($form[$element], $prefix);
    }
  }
}

/**
 * Retrieve all exposed fields of a given type (filter, sort).
 *
 * @param object $view
 *   A fully loaded views display object.
 * @param string $type
 *   The type of exposed element: 'filter' or 'sort'.
 *
 * @return array
 *   Array containing the internal names of exposed elements.
 */
function mefibs_get_exposed_items($display) {
  $items = array();
  foreach (array(
    'sort',
    'filter',
  ) as $type) {
    $handlers = $display
      ->getHandlers($type);
    foreach ($handlers as $handler) {
      if ($handler->options['exposed'] && in_array($type, array(
        'filter',
        'sort',
      ))) {
        if ($type == 'filter') {
          $items[$type][$handler->options['expose']['identifier']] = $handler->options['id'];
        }
        else {
          $items[$type][] = $handler->options['id'];
        }
      }
    }
  }
  $pager = $display
    ->getPlugin('pager');
  if ($pager
    ->usesExposed()) {
    if ($pager->options['expose']['items_per_page']) {
      $items['other'][] = 'items_per_page';
    }
    if ($pager->options['expose']['offset']) {
      $items['other'][] = 'offset';
    }
  }
  return $items;
}

/**
 * Retrieve the elements that should go into the additional form.
 *
 * @param object $view
 *   A fully loaded views object.
 * @param string $block_id
 * @param string $item_type
 *
 * @return array
 *   An array of view specific unique names of the elements for the additional
 *   form.
 */
function mefibs_get_expected_items_for_exposed_form_block($view, $block_id) {
  $display_id = $view->current_display;
  $display = $view
    ->getDisplay($display_id);
  $mefibs_options = $view
    ->getDisplay()
    ->getOption('mefibs');
  $elements = array(
    'filter' => array(),
    'sort' => array(),
    'other' => array(),
  );
  $exposed_items = mefibs_get_exposed_items($display);
  foreach (array(
    'filter',
    'other',
  ) as $type) {
    foreach ($exposed_items[$type] as $key => $item) {
      if (!isset($mefibs_options[$display_id][$type])) {
        continue;
      }
      $type_def = $mefibs_options[$display_id][$type];

      // Filters can have exposed operators so in case this is an operator we
      // build a special base name without the attached '_op'.
      $is_operator = strrpos($item, '_op') == strlen($item) - 3;
      $base = $is_operator ? substr($item, 0, strlen($item) - 3) : $item;

      // Check for normal items and operators in special block.
      if (isset($type_def[$base]) && $block_id == $type_def[$base]) {
        $elements[$type][$key] = $item;
      }
      elseif (!isset($type_def[$item]) && $block_id == 'default') {
        $elements[$type][$key] = $item;
      }
    }
  }
  if (isset($mefibs_options[$display_id]['sort_block']) && $mefibs_options[$display_id]['sort_block'] == $block_id) {
    $elements['sort'] = $exposed_items['sort'];
  }
  $context = array(
    'view' => clone $view,
    'display_id' => $display_id,
    'block_id' => $block_id,
    'type' => 'expected_items',
  );
  drupal_alter('mefibs_elements', $elements, $context);
  return $elements;
}

/**
 * Check if mefibs is enabled for the given display handler.
 *
 * @param object $display
 * @return boolean
 */
function mefibs_display_is_mefibs_enabled($display) {
  if (!is_object($display) || !isset($display->extender['mefibs'])) {
    return FALSE;
  }
  return count($display->extender['mefibs']
    ->getEnabledBlocks()) > 0;
}

/**
 * Callback function for a blocks machine_name form element.
 *
 * @param string $value 
 * @return boolean
 */
function mefibs_block_machine_name_exists($value, $element, $form_state) {

  // Check which button has triggered the submit. We need to verify uniqueness
  // of the given value only when a new block should be added.
  $button = $form_state['triggering_element'];
  if (!isset($button['#group'])) {
    return FALSE;
  }
  if ($button['#group'] !== 'add') {
    return FALSE;
  }
  if (!isset($form_state['view']->form_cache['blocks'])) {
    return FALSE;
  }
  $blocks = $form_state['view']->form_cache['blocks'];
  foreach ($blocks as $block) {
    if ($block['machine_name'] == $value) {
      return TRUE;
    }
  }
  return FALSE;
}

Functions

Namesort descending Description
mefibs_block_machine_name_exists Callback function for a blocks machine_name form element.
mefibs_display_is_mefibs_enabled Check if mefibs is enabled for the given display handler.
mefibs_form_views_exposed_form_alter Implements hook_form_FORM_ID_alter().
mefibs_form_views_ui_config_item_form_alter Implements hook_form_FORM_ID_alter().
mefibs_form_views_ui_config_item_form_submit Customer submit callback for the views_ui_config_item_form.
mefibs_form_views_ui_edit_display_form_alter Implements hook_form_FORM_ID_alter().
mefibs_form_views_ui_edit_display_form_submit Submit callback for the views_ui_edit_display form.
mefibs_get_expected_items_for_exposed_form_block Retrieve the elements that should go into the additional form.
mefibs_get_exposed_items Retrieve all exposed fields of a given type (filter, sort).
mefibs_set_form_id_recursive Recursivly prefix the #id attribute of all elements in a form.
mefibs_set_form_property_recursive Recursivly assign a value to a form property and all its children.
mefibs_theme Implements hook_theme().

Constants

Namesort descending Description
MEFIBS_VIEW_DISPLAY_PREFIX General purpose prefix for mefibs forms.