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

/**
 * @file
5
 * Definition of Drupal\views\Plugin\views\argument\String.
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;
dawehner's avatar
dawehner committed
12
use Drupal\views\ManyToOneHelper;
13
use Drupal\Component\Annotation\PluginID;
14

merlinofchaos's avatar
merlinofchaos committed
15 16 17 18 19
/**
 * Basic argument handler to implement string arguments that may have length
 * limits.
 *
 * @ingroup views_argument_handlers
20
 *
21
 * @PluginID("string")
22
 */
23
class String extends ArgumentPluginBase {
24

25 26 27 28 29 30
  /**
   * Overrides \Drupal\views\Plugin\views\argument\ArgumentPluginBase::init().
   */
  public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) {
    parent::init($view, $display, $options);

merlinofchaos's avatar
merlinofchaos committed
31
    if (!empty($this->definition['many to one'])) {
dawehner's avatar
dawehner committed
32
      $this->helper = new ManyToOneHelper($this);
merlinofchaos's avatar
merlinofchaos committed
33 34 35 36 37 38 39

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

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

    $options['glossary'] = array('default' => FALSE, 'bool' => TRUE);
    $options['limit'] = array('default' => 0);
    $options['case'] = array('default' => 'none');
    $options['path_case'] = array('default' => 'none');
    $options['transform_dash'] = array('default' => FALSE, 'bool' => TRUE);
    $options['break_phrase'] = array('default' => FALSE, 'bool' => TRUE);

    if (!empty($this->definition['many to one'])) {
      $options['add_table'] = array('default' => FALSE, 'bool' => TRUE);
      $options['require_value'] = array('default' => FALSE, 'bool' => TRUE);
    }

    return $options;
  }

58 59
  public function buildOptionsForm(&$form, &$form_state) {
    parent::buildOptionsForm($form, $form_state);
merlinofchaos's avatar
merlinofchaos committed
60 61 62 63 64 65 66 67 68 69 70 71 72 73

    $form['glossary'] = array(
      '#type' => 'checkbox',
      '#title' => t('Glossary mode'),
      '#description' => t('Glossary mode applies a limit to the number of characters used in the filter value, which allows the summary view to act as a glossary.'),
      '#default_value' => $this->options['glossary'],
      '#fieldset' => 'more',
    );

    $form['limit'] = array(
      '#type' => 'textfield',
      '#title' => t('Character limit'),
      '#description' => t('How many characters of the filter value to filter against. If set to 1, all fields starting with the first letter in the filter value would be matched.'),
      '#default_value' => $this->options['limit'],
74 75 76 77 78
      '#states' => array(
        'visible' => array(
          ':input[name="options[glossary]"]' => array('checked' => TRUE),
        ),
      ),
merlinofchaos's avatar
merlinofchaos committed
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
      '#fieldset' => 'more',
    );

    $form['case'] = array(
      '#type' => 'select',
      '#title' => t('Case'),
      '#description' => t('When printing the title and summary, how to transform the case of the filter value.'),
      '#options' => array(
        'none' => t('No transform'),
        'upper' => t('Upper case'),
        'lower' => t('Lower case'),
        'ucfirst' => t('Capitalize first letter'),
        'ucwords' => t('Capitalize each word'),
      ),
      '#default_value' => $this->options['case'],
      '#fieldset' => 'more',
    );

    $form['path_case'] = array(
      '#type' => 'select',
      '#title' => t('Case in path'),
      '#description' => t('When printing url paths, how to transform the case of the filter value. Do not use this unless with Postgres as it uses case sensitive comparisons.'),
      '#options' => array(
        'none' => t('No transform'),
        'upper' => t('Upper case'),
        'lower' => t('Lower case'),
        'ucfirst' => t('Capitalize first letter'),
        'ucwords' => t('Capitalize each word'),
      ),
      '#default_value' => $this->options['path_case'],
      '#fieldset' => 'more',
    );

    $form['transform_dash'] = array(
      '#type' => 'checkbox',
      '#title' => t('Transform spaces to dashes in URL'),
      '#default_value' => $this->options['transform_dash'],
      '#fieldset' => 'more',
    );

    if (!empty($this->definition['many to one'])) {
      $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',
      );
    }

    // allow + for or, , for and
    $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',
    );
  }

  /**
   * Build the summary query based on a string
   */
  function summary_query() {
    if (empty($this->definition['many to one'])) {
151
      $this->ensureMyTable();
merlinofchaos's avatar
merlinofchaos committed
152 153
    }
    else {
154
      $this->tableAlias = $this->helper->summary_join();
merlinofchaos's avatar
merlinofchaos committed
155 156 157 158
    }

    if (empty($this->options['glossary'])) {
      // Add the field.
159 160
      $this->base_alias = $this->query->add_field($this->tableAlias, $this->realField);
      $this->query->set_count_field($this->tableAlias, $this->realField);
merlinofchaos's avatar
merlinofchaos committed
161 162 163
    }
    else {
      // Add the field.
164
      $formula = $this->getFormula();
merlinofchaos's avatar
merlinofchaos committed
165 166 167 168 169
      $this->base_alias = $this->query->add_field(NULL, $formula, $this->field . '_truncated');
      $this->query->set_count_field(NULL, $formula, $this->field, $this->field . '_truncated');
    }

    $this->summary_name_field();
170
    return $this->summaryBasics(FALSE);
merlinofchaos's avatar
merlinofchaos committed
171 172 173 174 175
  }

  /**
   * Get the formula for this argument.
   *
176
   * $this->ensureMyTable() MUST have been called prior to this.
merlinofchaos's avatar
merlinofchaos committed
177
   */
178
  public function getFormula() {
179
    return "SUBSTRING($this->tableAlias.$this->realField, 1, " . intval($this->options['limit']) . ")";
merlinofchaos's avatar
merlinofchaos committed
180 181 182 183 184
  }

  /**
   * Build the query based upon the formula
   */
185
  public function query($group_by = FALSE) {
merlinofchaos's avatar
merlinofchaos committed
186 187 188 189 190 191
    $argument = $this->argument;
    if (!empty($this->options['transform_dash'])) {
      $argument = strtr($argument, '-', ' ');
    }

    if (!empty($this->options['break_phrase'])) {
192
      $this->breakPhraseString($argument, $this);
merlinofchaos's avatar
merlinofchaos committed
193 194 195 196 197 198 199 200 201 202
    }
    else {
      $this->value = array($argument);
      $this->operator = 'or';
    }

    if (!empty($this->definition['many to one'])) {
      if (!empty($this->options['glossary'])) {
        $this->helper->formula = TRUE;
      }
203
      $this->helper->ensureMyTable();
merlinofchaos's avatar
merlinofchaos committed
204 205 206 207
      $this->helper->add_filter();
      return;
    }

208
    $this->ensureMyTable();
merlinofchaos's avatar
merlinofchaos committed
209 210
    $formula = FALSE;
    if (empty($this->options['glossary'])) {
211
      $field = "$this->tableAlias.$this->realField";
merlinofchaos's avatar
merlinofchaos committed
212 213 214
    }
    else {
      $formula = TRUE;
215
      $field = $this->getFormula();
merlinofchaos's avatar
merlinofchaos committed
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
    }

    if (count($this->value) > 1) {
      $operator = 'IN';
      $argument = $this->value;
    }
    else {
      $operator = '=';
    }

    if ($formula) {
      $placeholder = $this->placeholder();
      if ($operator == 'IN') {
        $field .= " IN($placeholder)";
      }
      else {
        $field .= ' = ' . $placeholder;
      }
      $placeholders = array(
        $placeholder => $argument,
      );
      $this->query->add_where_expression(0, $field, $placeholders);
    }
    else {
      $this->query->add_where(0, $field, $argument, $operator);
    }
  }

  function summary_argument($data) {
245
    $value = $this->caseTransform($data->{$this->base_alias}, $this->options['path_case']);
merlinofchaos's avatar
merlinofchaos committed
246 247 248 249 250 251
    if (!empty($this->options['transform_dash'])) {
      $value = strtr($value, ' ', '-');
    }
    return $value;
  }

252 253 254 255
  /**
   * {@inheritdoc}
   */
  public function getSortName() {
merlinofchaos's avatar
merlinofchaos committed
256 257 258 259
    return t('Alphabetical', array(), array('context' => 'Sort order'));
  }

  function title() {
260
    $this->argument = $this->caseTransform($this->argument, $this->options['case']);
merlinofchaos's avatar
merlinofchaos committed
261 262 263 264 265
    if (!empty($this->options['transform_dash'])) {
      $this->argument = strtr($this->argument, '-', ' ');
    }

    if (!empty($this->options['break_phrase'])) {
266
      $this->breakPhraseString($this->argument, $this);
merlinofchaos's avatar
merlinofchaos committed
267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291
    }
    else {
      $this->value = array($this->argument);
      $this->operator = 'or';
    }

    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());
  }

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

  function summary_name($data) {
292
    return $this->caseTransform(parent::summary_name($data), $this->options['case']);
merlinofchaos's avatar
merlinofchaos committed
293 294 295
  }

}