You are here

class views_dependent_filters_handler_filter_dependent in Views Dependent Filters 7

Hierarchy

Expanded class hierarchy of views_dependent_filters_handler_filter_dependent

2 string references to 'views_dependent_filters_handler_filter_dependent'
views_dependent_filters_handler_filter_dependent::get_filter_options in ./views_dependent_filters_handler_filter_dependent.inc
Helper function to provide form options for lists of filters.
views_dependent_filters_views_data_alter in ./views_dependent_filters.views.inc
Implements hook_views_data_alter().

File

./views_dependent_filters_handler_filter_dependent.inc, line 6

View source
class views_dependent_filters_handler_filter_dependent extends views_handler_filter {

  /**
   * The list of filters subsequent to ourselves that we should remove.
   * An array of keys of $this->view->filter.
   */
  var $filters_kill = array();

  /**
   * Disable the filters we control.
   */
  function filters_disable() {

    // This hacks subsequent handlers' options so they are no longer exposed.
    // Incoming values from these on submit will be simply ignored.
    foreach ($this->filters_kill as $filter_id) {
      $this->view->filter[$filter_id]->options['exposed'] = FALSE;
    }
  }

  /**
   * Enable the filters we control.
   */
  function filters_enable() {
    foreach ($this->filters_kill as $filter_id) {
      $this->view->filter[$filter_id]->options['exposed'] = TRUE;
    }
  }
  function option_definition() {
    $options = parent::option_definition();

    // Override the exposed default. This makes no sense not exposed.
    $options['exposed'] = array(
      'default' => TRUE,
    );
    $options['controller_filter'] = array(
      'default' => NULL,
    );
    $options['controller_values'] = array(
      'default' => NULL,
    );
    $options['dependent_filters'] = array(
      'default' => array(),
    );
    return $options;
  }

  /**
   * Helper function to provide form options for lists of filters.
   *
   * @param $type
   *  One of 'controller' or 'dependent'.
   *
   * @return
   *  An array of filters suitable for use as Form API options.
   */
  function get_filter_options($type) {

    // Due to http://drupal.org/node/1426094 we can't just go looking in the
    // handlers array on the display.
    $filters = $this->view->display_handler
      ->get_handlers('filter');

    // Get the unique id of this handler (ie allow more than one of this handler).
    $this_id = $this->options['id'];
    $filters_controller = array();
    $filters_dependent = array();
    $seen = FALSE;

    // Build up the options from all the fields up to this one but no further.
    foreach ($filters as $filter_id => $handler) {

      // Skip non-exposed filters.
      if (!$handler
        ->is_exposed()) {
        continue;
      }

      // Required filters can't be dependent.
      if ($type == 'dependent' && $handler->options['expose']['required']) {
        continue;
      }

      // Note if we get to ourselves and skip.
      if ($filter_id == $this_id) {
        $seen = TRUE;
        continue;
      }

      // Skip other instances of this filter.
      if ($handler->definition['handler'] == 'views_dependent_filters_handler_filter_dependent') {
        continue;
      }
      $label = $handler
        ->ui_name(TRUE);

      // All filters may be controllers, but to simplify things we just allow
      // the ones that come before us.
      if (!$seen) {
        $filters_controller[$filter_id] = $label;
      }

      // Only filters that follow us in the order may be dependent.
      if ($seen) {
        $filters_dependent[$filter_id] = $label;
      }
    }
    switch ($type) {
      case 'controller':
        return $filters_controller;
      case 'dependent':
        return $filters_dependent;
    }
  }

  /**
   * Provide the basic form which calls through to subforms.
   * If overridden, it is best to call through to the parent,
   * or to at least make sure all of the functions in this form
   * are called.
   */
  function options_form(&$form, &$form_state) {
    parent::options_form($form, $form_state);

    // Lock the exposed checkbox.
    $form['expose_button']['checkbox']['checkbox']['#disabled'] = TRUE;
    $form['expose_button']['checkbox']['checkbox']['#description'] = t('This filter is always exposed.');

    // Not sure what the 'expose' button is for as there's the checkbox, but
    // it's not wanted here.
    unset($form['expose_button']['markup']);
    unset($form['expose_button']['button']);
    $filters = $this->view->display_handler->handlers['filter'];
    if (isset($this->options['controller_filter'])) {

      // Get the handler for the controller filter.
      $controller_filter = $filters[$this->options['controller_filter']];

      // Take copies of the form arrays to pass to the other handler.
      $form_copy = $form;
      $form_state_copy = $form_state;

      // Fixup the form so the handler is fooled.
      // For some reason we need to add this for non-ajax admin operation.
      $form_copy['operator']['#type'] = '';

      // Get the value form from the filter handler.
      $controller_filter
        ->value_form($form_copy, $form_state);
      $controller_values_element = $form_copy['value'];

      // Clean up the form element.
      if ($controller_values_element['#type'] == 'checkboxes') {

        // We have to unset the 'select all' option on checkboxes.
        unset($controller_values_element['#options']['all']);

        // Force multiple.
        $controller_values_element['#multiple'] = TRUE;
      }

      // Add it to our own form element in the real form.
      $form['controller_values'] = array(
        '#title' => t('Controller values'),
        '#description' => t('The values on the controller filter that will cause the dependent filters to be visible.'),
        '#default_value' => isset($this->options['controller_values']) ? $this->options['controller_values'] : array(),
      ) + $controller_values_element;
    }
    $options = $this
      ->get_filter_options('dependent');
    $form['dependent_filters'] = array(
      '#type' => 'checkboxes',
      '#title' => t('Dependent filters'),
      '#options' => $options,
      '#default_value' => isset($this->options['dependent_filters']) ? $this->options['dependent_filters'] : array(),
      '#description' => t('The filters which should only be visible and active when the controller filter has the given values.'),
    );
    if (empty($options)) {
      $form['dependent_filters']['#description'] .= ' ' . t('This filter needs other filters to be placed below it in the order to use as dependents.');
    }
  }
  function has_extra_options() {
    return TRUE;
  }

  /**
   * Provide defaults for the handler.
   */
  function extra_options(&$option) {
  }

  /**
   * Extra settings form: select the controller filter.
   *
   * Selecting the controller filter here allows us to nicely show its value
   * form in the regular options form.
   */
  function extra_options_form(&$form, &$form_state) {
    $options = $this
      ->get_filter_options('controller');
    $form['controller_filter'] = array(
      '#type' => 'radios',
      '#title' => t('Controller filter'),
      '#options' => $options,
      '#default_value' => isset($this->options['controller_filter']) ? $this->options['controller_filter'] : '',
      '#description' => t('The exposed filter whose values will be used to control dependent filters. Only filters that are prior to this one in the order are allowed.'),
    );
  }

  /**
   * Override the options form exposed options subform to show nothing, as the
   * options here don't make sense for us.
   */
  function expose_form(&$form, &$form_state) {
    return;
  }

  /**
   * Display the filter on the administrative summary.
   */
  function admin_summary() {
    $controller_filter = $this->options['controller_filter'];
    $dependent_filters = implode(', ', array_filter($this->options['dependent_filters']));
    return t("@controller controlling @dependents", array(
      '@controller' => $controller_filter,
      '@dependents' => $dependent_filters,
    ));
  }

  /**
   * Make our changes to the form but don't return anything ourselves.
   */
  function exposed_form(&$form, &$form_state) {
    $filters = $this->view->display_handler
      ->get_handlers('filter');

    // Build an array of dependency info.
    $dependency_info = array(
      // An array keyed by controller filter IDs, where the values are arrays
      // of their possible values.
      // In practice there is only one controller filter, but technically there
      // could be several. The problem is that the admin UI to set them up
      // would become a nightmare, and there's the matter of whether to combine
      // them with AND or OR. Hence one for later, if ever required.
      'controllers' => array(),
      // An array of dependent filter IDs.
      'dependents' => array(),
      // A lookup of filter IDs to filter URL identifiers.
      'identifiers' => array(),
    );
    if (!empty($this->options['controller_filter'])) {
      $controller_filter = $this->options['controller_filter'];
      $dependency_info['controllers'][$controller_filter] = array();
      if (!empty($this->options['controller_values'])) {
        if (is_array($this->options['controller_values'])) {

          // Filter out the crud from Form API checkboxes and get rid of the
          // keys to avoid confusion: we compare on values further down.
          $controller_values = array_values(array_filter($this->options['controller_values']));
        }
        else {
          $controller_values = array(
            $this->options['controller_values'],
          );
        }
        $dependency_info['controllers'][$controller_filter] = $controller_values;
        $identifier = $filters[$controller_filter]->options['expose']['identifier'];
        $dependency_info['identifiers'][$controller_filter] = $identifier;
      }
    }
    $dependency_info['dependents'] = array_values(array_filter($this->options['dependent_filters']));

    // Populate the identifiers lookup with our dependent filters.
    foreach ($dependency_info['dependents'] as $dependent_filter_id) {
      $identifier = $filters[$dependent_filter_id]->options['expose']['identifier'];
      $dependency_info['identifiers'][$dependent_filter_id] = $identifier;
    }

    //dsm($form_state['input'], 'input');
    $filters = $this->view->display_handler
      ->get_handlers('filter');
    foreach ($dependency_info['controllers'] as $filter_id => $controller_values) {

      // Get the form identifier.
      $identifier = $filters[$filter_id]->options['expose']['identifier'];

      // Get the input for this filter.
      $input = $form_state['input'][$identifier];

      // Convert values for non-multiple filters to an array.
      if (!$this->view->filter[$filter_id]->options['expose']['multiple']) {
        $input = array(
          $input,
        );
      }
      $intersection = array_intersect($input, $controller_values);
      if (!count($intersection)) {
        $this->filters_kill = $dependency_info['dependents'];
      }
    }

    // We can kill the dependent filters now.
    // $this->filters_disable();
    // ...alternatively, leave them there so their form is shown, but prevent
    // them from collecting input.
    // This means the form element can be subject to CTools dependent visiblity
    // and means the user can refine their filtering without an interim
    // submission of the form.
    // @todo: Allow this as an option, ie have a 'no js' version which would
    // just kill dependent filters now.
    // To make the dependent filters change their visibility we need to add a
    // CTools dependent property, but we can't do that here as the form
    // elements for these don't exist yet.
    // Only way to do this is to register an #after_build on the whole form
    // which lives in module code rather than in this handler.
    // Add our settings to the form state as an array, as we need to account
    // for the possiblity that more than one copy of this handler may be
    // playing at once!
    $form_state['dependent_exposed_filters'][] = $dependency_info;
    $form['#after_build'] = array(
      'views_dependent_filters_exposed_form_after_build',
    );

    // Some clean-up for things that come later.
    // Mark ourselves not being exposed now we've done our work. This isn't
    // necessary for Views itself, but allows compatibility with the
    // better_exposed_filters module whose exposed_form_alter() tries to work
    // with all exposed filters.
    $this->options['exposed'] = FALSE;

    // We do nada to the form ourselves.
    return;
  }

  /**
   * Doctor this so the whole form doesn't add our element to $form['#info'].
   *
   * @see views_exposed_form().
   */
  function exposed_info() {
    return;
  }

  /**
   * Prevent the view from accepting input from ourselves and dependents.
   */
  function accept_exposed_input($input) {

    // Disable our dependent filters just before they have a chance to act
    // on exposed input.
    $this
      ->filters_disable();

    // Doctor this so the whole form doesn't go looking for our exposed input.
    return TRUE;
  }
  function value_form(&$form, &$form_state) {

    // Return nothing for the value form.
    $form['value'] = array();
  }
  function query() {

    // Do nothing: fake filter.
  }

}

Members

Namesort descending Modifiers Type Description Overrides
views_dependent_filters_handler_filter_dependent::$filters_kill property The list of filters subsequent to ourselves that we should remove. An array of keys of $this->view->filter.
views_dependent_filters_handler_filter_dependent::accept_exposed_input function Prevent the view from accepting input from ourselves and dependents. Overrides views_handler_filter::accept_exposed_input
views_dependent_filters_handler_filter_dependent::admin_summary function Display the filter on the administrative summary. Overrides views_handler_filter::admin_summary
views_dependent_filters_handler_filter_dependent::exposed_form function Make our changes to the form but don't return anything ourselves. Overrides views_handler_filter::exposed_form
views_dependent_filters_handler_filter_dependent::exposed_info function Doctor this so the whole form doesn't add our element to $form['#info']. Overrides views_handler_filter::exposed_info
views_dependent_filters_handler_filter_dependent::expose_form function Override the options form exposed options subform to show nothing, as the options here don't make sense for us. Overrides views_handler_filter::expose_form
views_dependent_filters_handler_filter_dependent::extra_options function Provide defaults for the handler. Overrides views_handler::extra_options
views_dependent_filters_handler_filter_dependent::extra_options_form function Extra settings form: select the controller filter. Overrides views_handler::extra_options_form
views_dependent_filters_handler_filter_dependent::filters_disable function Disable the filters we control.
views_dependent_filters_handler_filter_dependent::filters_enable function Enable the filters we control.
views_dependent_filters_handler_filter_dependent::get_filter_options function Helper function to provide form options for lists of filters.
views_dependent_filters_handler_filter_dependent::has_extra_options function If a handler has 'extra options' it will get a little settings widget and another form called extra_options. Overrides views_handler::has_extra_options
views_dependent_filters_handler_filter_dependent::options_form function Provide the basic form which calls through to subforms. If overridden, it is best to call through to the parent, or to at least make sure all of the functions in this form are called. Overrides views_handler_filter::options_form
views_dependent_filters_handler_filter_dependent::option_definition function Information about options for all kinds of purposes will be held here. Overrides views_handler_filter::option_definition
views_dependent_filters_handler_filter_dependent::query function Add this filter to the query. Overrides views_handler_filter::query
views_dependent_filters_handler_filter_dependent::value_form function Options form subform for setting options. Overrides views_handler_filter::value_form
views_handler::$handler_type public property The type of the handler, for example filter/footer/field.
views_handler::$query public property Where the $query object will reside:. 1
views_handler::$real_field public property The actual field in the database table, maybe different on other kind of query plugins/special handlers.
views_handler::$relationship public property The relationship used for this field.
views_handler::$table_alias public property The alias of the table of this handler which is used in the query.
views_handler::$view public property The top object of a view. Overrides views_object::$view
views_handler::access public function Check whether current user has access to this handler. 10
views_handler::broken public function Determine if the handler is considered 'broken'. 6
views_handler::case_transform public function Transform a string by a certain method.
views_handler::ensure_my_table public function Ensure the main table for this handler is in the query. This is used a lot. 8
views_handler::exposed_submit public function Submit the exposed handler form.
views_handler::exposed_validate public function Validate the exposed handler form. 4
views_handler::expose_submit public function Perform any necessary changes to the form exposes prior to storage. There is no need for this function to actually store the data.
views_handler::extra_options_submit public function Perform any necessary changes to the form values prior to storage. There is no need for this function to actually store the data.
views_handler::extra_options_validate public function Validate the options form.
views_handler::get_field public function Shortcut to get a handler's raw field value.
views_handler::get_join public function Get the join object that should be used for this handler.
views_handler::groupby_form public function Provide a form for aggregation settings. 1
views_handler::groupby_form_submit public function Perform any necessary changes to the form values prior to storage. There is no need for this function to actually store the data. 1
views_handler::is_exposed public function Determine if this item is 'exposed', meaning it provides form elements to let users modify the view.
views_handler::needs_style_plugin public function Determine if the argument needs a style plugin. 1
views_handler::placeholder public function Provides a unique placeholders for handlers.
views_handler::post_execute public function Run after the view is executed, before the result is cached. 1
views_handler::pre_query public function Run before the view is built. 1
views_handler::sanitize_value public function Sanitize the value for output.
views_handler::set_relationship public function Called just prior to query(), this lets a handler set up any relationship it needs.
views_handler::show_expose_form public function Shortcut to display the exposed options form.
views_handler::ui_name public function Return a string representing this handler's name in the UI. 9
views_handler::use_group_by public function Provides the handler some groupby. 2
views_handler::validate public function Validates the handler against the complete View. 1
views_handler_filter::$always_multiple public property Disable the possibility to force a single value. 6
views_handler_filter::$always_required public property Disable the possibility to allow a exposed input to be optional.
views_handler_filter::$group_info public property Contains the information of the selected item in a gruped filter.
views_handler_filter::$no_operator public property Disable the possibility to use operators. 2
views_handler_filter::$operator public property Contains the operator which is used on the query.
views_handler_filter::$value public property Contains the actual value of the field.
views_handler_filter::build_group_form public function Build the form to let users create the group of exposed filters.
views_handler_filter::build_group_options public function Provide default options for exposed filters.
views_handler_filter::build_group_submit public function Save new group items, re-enumerates and remove groups marked to delete.
views_handler_filter::build_group_validate public function Validate the build group options form. 1
views_handler_filter::can_build_group public function Determine if a filter can be converted into a group.
views_handler_filter::can_expose public function Determine if a filter can be exposed. Overrides views_handler::can_expose 5
views_handler_filter::can_group public function Can this filter be used in OR groups? 1
views_handler_filter::convert_exposed_input public function Transform the input from a grouped filter into a standard filter.
views_handler_filter::exposed_translate public function Make some translations to a form item to make it more suitable to exposing.
views_handler_filter::expose_options public function Provide default options for exposed filters. Overrides views_handler::expose_options 2
views_handler_filter::expose_validate public function Validate the options form. Overrides views_handler::expose_validate
views_handler_filter::group_form public function Build a form with a group of operator | values to apply as a single filter.
views_handler_filter::group_multiple_exposed_input public function Options available for a grouped filter which uses checkboxes.
views_handler_filter::init public function Provide some extra help to get the operator/value easier to use. Overrides views_handler::init 2
views_handler_filter::is_a_group public function Returns TRUE if the exposed filter works like a grouped filter. Overrides views_handler::is_a_group
views_handler_filter::multiple_exposed_input public function Indicate whether users can select multiple group items. Overrides views_handler::multiple_exposed_input
views_handler_filter::operator_form public function Options form subform for setting the operator. 6
views_handler_filter::operator_options public function Provide a list of options for the default operator form. 4
views_handler_filter::operator_submit public function Perform any necessary changes to the form values prior to storage.
views_handler_filter::operator_validate public function Validate the operator form.
views_handler_filter::options_submit public function Simple submit handler. Overrides views_handler::options_submit
views_handler_filter::options_validate public function Simple validate handler. Overrides views_handler::options_validate 1
views_handler_filter::prepare_filter_select_options public function Sanitizes the HTML select element's options.
views_handler_filter::show_build_group_button public function Shortcut to display the build_group/hide button.
views_handler_filter::show_build_group_form public function Shortcut to display the exposed options form.
views_handler_filter::show_expose_button public function Shortcut to display the expose/hide button. Overrides views_handler::show_expose_button
views_handler_filter::show_operator_form public function Shortcut to display the operator form.
views_handler_filter::show_value_form public function Shortcut to display the value form.
views_handler_filter::store_exposed_input public function Store the exposed input for processing later. Overrides views_handler::store_exposed_input
views_handler_filter::store_group_input public function If set to remember exposed input in the session, store it there.
views_handler_filter::value_submit public function Perform any necessary changes to the form values prior to storage. 1
views_handler_filter::value_validate public function Validate the options form. 3
views_object::$definition public property Handler's definition.
views_object::$options public property Except for displays, options for the object will be held here. 1
views_object::altered_option_definition function Collect this handler's option definition and alter them, ready for use.
views_object::construct public function Views handlers use a special construct function. 4
views_object::destroy public function Destructor. 2
views_object::export_option public function 1
views_object::export_options public function
views_object::export_option_always public function Always exports the option, regardless of the default value.
views_object::options Deprecated public function Set default options on this object. 1
views_object::set_default_options public function Set default options.
views_object::set_definition public function Let the handler know what its full definition is.
views_object::unpack_options public function Unpack options over our existing defaults, drilling down into arrays so that defaults don't get totally blown away.
views_object::unpack_translatable public function Unpack a single option definition.
views_object::unpack_translatables public function Unpacks each handler to store translatable texts.
views_object::_set_option_defaults public function