ManyToOne.php 5.87 KB
Newer Older
merlinofchaos's avatar
merlinofchaos committed
1 2 3 4
<?php

/**
 * @file
5
 * Definition of Drupal\views\Plugin\views\argument\ManyToOne.
merlinofchaos's avatar
merlinofchaos committed
6 7
 */

8
namespace Drupal\views\Plugin\views\argument;
9

10
use Drupal\views\ViewExecutable;
11
use Drupal\views\Plugin\views\display\DisplayPluginBase;
12
use Drupal\Component\Annotation\PluginID;
dawehner's avatar
dawehner committed
13
use Drupal\views\ManyToOneHelper;
14

merlinofchaos's avatar
merlinofchaos committed
15 16 17 18 19 20 21 22 23 24 25 26
/**
 * An argument handler for use in fields that have a many to one relationship
 * with the table(s) to the left. This adds a bunch of options that are
 * reasonably common with this type of relationship.
 * Definition terms:
 * - numeric: If true, the field will be considered numeric. Probably should
 *   always be set TRUE as views_handler_argument_string has many to one
 *   capabilities.
 * - zero is null: If true, a 0 will be handled as empty, so for example
 *   a default argument can be provided or a summary can be shown.
 *
 * @ingroup views_argument_handlers
27
 *
28
 * @PluginID("many_to_one")
29
 */
30
class ManyToOne extends ArgumentPluginBase {
31

32 33 34 35 36 37
  /**
   * Overrides \Drupal\views\Plugin\views\argument\ArgumentPluginBase::init().
   */
  public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) {
    parent::init($view, $display, $options);

dawehner's avatar
dawehner committed
38
    $this->helper = new ManyToOneHelper($this);
merlinofchaos's avatar
merlinofchaos committed
39 40 41 42 43 44

    // Ensure defaults for these, during summaries and stuff:
    $this->operator = 'or';
    $this->value = array();
  }

45 46
  protected function defineOptions() {
    $options = parent::defineOptions();
merlinofchaos's avatar
merlinofchaos committed
47 48 49 50 51 52 53 54 55

    if (!empty($this->definition['numeric'])) {
      $options['break_phrase'] = array('default' => FALSE, 'bool' => TRUE);
    }

    $options['add_table'] = array('default' => FALSE, 'bool' => TRUE);
    $options['require_value'] = array('default' => FALSE, 'bool' => TRUE);

    if (isset($this->helper)) {
56
      $this->helper->defineOptions($options);
merlinofchaos's avatar
merlinofchaos committed
57 58
    }
    else {
dawehner's avatar
dawehner committed
59
      $helper = new ManyToOneHelper($this);
60
      $helper->defineOptions($options);
merlinofchaos's avatar
merlinofchaos committed
61 62 63 64 65
    }

    return $options;
  }

66 67
  public function buildOptionsForm(&$form, &$form_state) {
    parent::buildOptionsForm($form, $form_state);
merlinofchaos's avatar
merlinofchaos committed
68 69

    // allow + for or, , for and
70 71 72 73 74 75 76
    $form['break_phrase'] = array(
      '#type' => 'checkbox',
      '#title' => t('Allow multiple values'),
      '#description' => t('If selected, users can enter multiple values in the form of 1+2+3 (for OR) or 1,2,3 (for AND).'),
      '#default_value' => !empty($this->options['break_phrase']),
      '#fieldset' => 'more',
    );
merlinofchaos's avatar
merlinofchaos committed
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92

    $form['add_table'] = array(
      '#type' => 'checkbox',
      '#title' => t('Allow multiple filter values to work together'),
      '#description' => t('If selected, multiple instances of this filter can work together, as though multiple values were supplied to the same filter. This setting is not compatible with the "Reduce duplicates" setting.'),
      '#default_value' => !empty($this->options['add_table']),
      '#fieldset' => 'more',
    );

    $form['require_value'] = array(
      '#type' => 'checkbox',
      '#title' => t('Do not display items with no value in summary'),
      '#default_value' => !empty($this->options['require_value']),
      '#fieldset' => 'more',
    );

93
    $this->helper->buildOptionsForm($form, $form_state);
merlinofchaos's avatar
merlinofchaos committed
94 95 96
  }

  /**
97
   * Override ensureMyTable so we can control how this joins in.
merlinofchaos's avatar
merlinofchaos committed
98 99
   * The operator actually has influence over joining.
   */
100 101
  public function ensureMyTable() {
    $this->helper->ensureMyTable();
merlinofchaos's avatar
merlinofchaos committed
102 103
  }

104
  public function query($group_by = FALSE) {
merlinofchaos's avatar
merlinofchaos committed
105 106 107 108 109 110 111 112 113 114 115 116
    $empty = FALSE;
    if (isset($this->definition['zero is null']) && $this->definition['zero is null']) {
      if (empty($this->argument)) {
        $empty = TRUE;
      }
    }
    else {
      if (!isset($this->argument)) {
        $empty = TRUE;
      }
    }
    if ($empty) {
117
      parent::ensureMyTable();
118
      $this->query->add_where(0, "$this->tableAlias.$this->realField", NULL, 'IS NULL');
merlinofchaos's avatar
merlinofchaos committed
119 120 121 122
      return;
    }

    if (!empty($this->options['break_phrase'])) {
123 124
      if (!empty($this->definition['numeric'])) {
        $this->breakPhrase($this->argument, $this);
125 126
      }
      else {
127
        $this->breakPhraseString($this->argument, $this);
128
      }
merlinofchaos's avatar
merlinofchaos committed
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
    }
    else {
      $this->value = array($this->argument);
      $this->operator = 'or';
    }

    $this->helper->add_filter();
  }

  function title() {
    if (!$this->argument) {
      return !empty($this->definition['empty field name']) ? $this->definition['empty field name'] : t('Uncategorized');
    }

    if (!empty($this->options['break_phrase'])) {
144
      $this->breakPhrase($this->argument, $this);
merlinofchaos's avatar
merlinofchaos committed
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
    }
    else {
      $this->value = array($this->argument);
      $this->operator = 'or';
    }

    // @todo -- both of these should check definition for alternate keywords.

    if (empty($this->value)) {
      return !empty($this->definition['empty field name']) ? $this->definition['empty field name'] : t('Uncategorized');
    }

    if ($this->value === array(-1)) {
      return !empty($this->definition['invalid input']) ? $this->definition['invalid input'] : t('Invalid input');
    }

    return implode($this->operator == 'or' ? ' + ' : ', ', $this->title_query());
  }

  function summary_query() {
    $field = $this->table . '.' . $this->field;
166
    $join = $this->getJoin();
merlinofchaos's avatar
merlinofchaos committed
167 168 169 170 171 172

    if (!empty($this->options['require_value'])) {
      $join->type = 'INNER';
    }

    if (empty($this->options['add_table']) || empty($this->view->many_to_one_tables[$field])) {
173
      $this->tableAlias = $this->query->ensure_table($this->table, $this->relationship, $join);
merlinofchaos's avatar
merlinofchaos committed
174 175
    }
    else {
176
      $this->tableAlias = $this->helper->summary_join();
merlinofchaos's avatar
merlinofchaos committed
177 178 179
    }

    // Add the field.
180
    $this->base_alias = $this->query->add_field($this->tableAlias, $this->realField);
merlinofchaos's avatar
merlinofchaos committed
181 182 183

    $this->summary_name_field();

184
    return $this->summaryBasics();
merlinofchaos's avatar
merlinofchaos committed
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
  }

  function summary_argument($data) {
    $value = $data->{$this->base_alias};
    if (empty($value)) {
      $value = 0;
    }

    return $value;
  }

  /**
   * Override for specific title lookups.
   */
  function title_query() {
    return $this->value;
  }
202

merlinofchaos's avatar
merlinofchaos committed
203
}