Projet

Général

Profil

Paste
Télécharger (112 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / views / plugins / views_plugin_display.inc @ 4003efde

1 85ad3d82 Assos Assos
<?php
2
3
/**
4
 * @file
5 5d12d676 Assos Assos
 * Definition of views_plugin_display.
6 85ad3d82 Assos Assos
 */
7
8
/**
9
 * @defgroup views_display_plugins Views display plugins
10
 * @{
11
 * Display plugins control how Views interact with the rest of Drupal.
12
 *
13
 * They can handle creating Views from a Drupal page hook; they can
14
 * handle creating Views from a Drupal block hook. They can also
15
 * handle creating Views from an external module source, such as
16
 * a Panels pane, or an insert view, or a CCK field type.
17
 *
18
 * @see hook_views_plugins()
19
 */
20
21
/**
22
 * The default display plugin handler. Display plugins handle options and
23
 * basic mechanisms for different output methods.
24
 */
25
class views_plugin_display extends views_plugin {
26 5d12d676 Assos Assos
27 85ad3d82 Assos Assos
  /**
28
   * The top object of a view.
29
   *
30
   * @var view
31
   */
32 5d12d676 Assos Assos
  public $view = NULL;
33 85ad3d82 Assos Assos
34 5d12d676 Assos Assos
  /**
35 8be7bf84 Assos Assos
   * List of handlers for this display.
36 5d12d676 Assos Assos
   *
37 8be7bf84 Assos Assos
   * @var array
38 5d12d676 Assos Assos
   */
39
  public $handlers = array();
40 85ad3d82 Assos Assos
41
  /**
42
   * Stores all available display extenders.
43 8be7bf84 Assos Assos
   *
44
   * @var array
45 85ad3d82 Assos Assos
   */
46 5d12d676 Assos Assos
  public $extender = array();
47 85ad3d82 Assos Assos
48 5d12d676 Assos Assos
  /**
49
   * {@inheritdoc}
50
   */
51
  public function init(&$view, &$display, $options = NULL) {
52 85ad3d82 Assos Assos
    $this->view = &$view;
53
    $this->display = &$display;
54
55
    // Load extenders as soon as possible.
56
    $this->extender = array();
57
    $extenders = views_get_enabled_display_extenders();
58
    // If you update to the dev version the registry might not be loaded yet.
59
    if (!empty($extenders) && class_exists('views_plugin_display_extender')) {
60
      foreach ($extenders as $extender) {
61
        $plugin = views_get_plugin('display_extender', $extender);
62
        if ($plugin) {
63
          $plugin->init($this->view, $this);
64
          $this->extender[$extender] = $plugin;
65
        }
66
        else {
67 44d2e178 Assos Assos
          vpr('Invalid display extender @extender', array('@extender' => $extender));
68 85ad3d82 Assos Assos
        }
69
      }
70
    }
71
72
    // Track changes that the user should know about.
73
    $changed = FALSE;
74
75 5d12d676 Assos Assos
    // Make some modifications.
76 85ad3d82 Assos Assos
    if (!isset($options) && isset($display->display_options)) {
77
      $options = $display->display_options;
78
    }
79
80
    if ($this->is_default_display() && isset($options['defaults'])) {
81
      unset($options['defaults']);
82
    }
83
84
    // Cache for unpack_options, but not if we are in the ui.
85
    static $unpack_options = array();
86
    if (empty($view->editing)) {
87
      $cid = 'unpack_options:' . md5(serialize(array($this->options, $options)));
88
      if (empty($unpack_options[$cid])) {
89
        $cache = views_cache_get($cid, TRUE);
90
        if (!empty($cache->data)) {
91
          $this->options = $cache->data;
92
        }
93
        else {
94
          $this->unpack_options($this->options, $options);
95
          views_cache_set($cid, $this->options, TRUE);
96
        }
97
        $unpack_options[$cid] = $this->options;
98
      }
99
      else {
100
        $this->options = $unpack_options[$cid];
101
      }
102
    }
103
    else {
104
      $this->unpack_options($this->options, $options);
105
    }
106
107 5d12d676 Assos Assos
    // Translate changed settings.
108 85ad3d82 Assos Assos
    $items_per_page = $this->get_option('items_per_page');
109
    $offset = $this->get_option('offset');
110
    $use_pager = $this->get_option('use_pager');
111
    $pager = $this->get_option('pager');
112
    // Check if the pager options were already converted.
113
    // The pager settings of a Views 2.x view specifying 10 items with an
114
    // offset of 0 and no pager is the same as of a Views 3.x view with
115
    // default settings. In this case, the only way to determine which case we
116
    // are dealing with is checking the API version but that's only available
117
    // for exported Views as it's not stored in the database.
118
    // If you would like to change this code, really take care that you thought
119
    // of every possibility.
120 5d12d676 Assos Assos
    // @todo Provide a way to convert the database views as well.
121 85ad3d82 Assos Assos
    if (((!empty($items_per_page) && $items_per_page != 10) || !empty($offset) || !empty($use_pager))
122
      || (!empty($view->api_version) && $view->api_version == 2)) {
123
      // Find out the right pager type.
124
      // If the view "use pager" it's a normal/full pager.
125
      if ($use_pager) {
126
        $type = 'full';
127
      }
128
      // If it does not use pager, but 0 items per page it should not page
129
      // else it should display just a certain amount of items.
130
      else {
131
        $type = $items_per_page ? 'some' : 'none';
132
      }
133
134
      // Setup the pager options.
135
      $pager = array(
136
        'type' => $type,
137
        'options' => array(
138 8be7bf84 Assos Assos
          'offset' => intval($offset),
139 85ad3d82 Assos Assos
        ),
140
      );
141
142
      if ($items_per_page) {
143
        $pager['options']['items_per_page'] = $items_per_page;
144
      }
145
      // Setup the pager element.
146
      if ($id = $this->get_option('pager_element')) {
147
        $pager['options']['id'] = $id;
148
      }
149
150 8be7bf84 Assos Assos
      // Unset the previous options. After edit and save the view they will be
151
      // erased.
152 85ad3d82 Assos Assos
      $this->set_option('items_per_page', NULL);
153
      $this->set_option('offset', NULL);
154
      $this->set_option('use_pager', NULL);
155
      $this->set_option('pager', $pager);
156
      $changed = TRUE;
157
    }
158
159 8be7bf84 Assos Assos
    // Plugable headers, footer and empty texts are not compatible with
160
    // previous version of views. This code converts old values into a
161
    // configured handler for each area.
162 85ad3d82 Assos Assos
    foreach (array('header', 'footer', 'empty') as $area) {
163
      $converted = FALSE;
164
      if (isset($this->options[$area]) && !is_array($this->options[$area])) {
165
        if (!empty($this->options[$area])) {
166
          $content = $this->get_option($area);
167
          if (!empty($content) && !is_array($content)) {
168
            $format = $this->get_option($area . '_format');
169
            $options = array(
170
              'id' => 'area',
171
              'table' => 'views',
172
              'field' => 'area',
173
              'label' => '',
174
              'relationship' => 'none',
175
              'group_type' => 'group',
176
              'content' => $content,
177
              'format' => !empty($format) ? $format : filter_default_format(),
178
            );
179
180
            if ($area != 'empty' && $empty = $this->get_option($area . '_empty')) {
181
              $options['empty'] = $empty;
182
            }
183
            $this->set_option($area, array('text' => $options));
184
            $converted = TRUE;
185
            $changed = TRUE;
186
          }
187
        }
188 8be7bf84 Assos Assos
        // Ensure that options are at least an empty array.
189 85ad3d82 Assos Assos
        if (!$converted) {
190
          $this->set_option($area, array());
191
        }
192
      }
193
    }
194
195
    // Convert distinct setting from display to query settings.
196
    $distinct = $this->get_option('distinct');
197
    if (!empty($distinct)) {
198
      $query_settings = $this->get_option('query');
199
      $query_settings['options']['distinct'] = $distinct;
200
      $this->set_option('query', $query_settings);
201 8be7bf84 Assos Assos
      // Clear the values.
202 85ad3d82 Assos Assos
      $this->set_option('distinct', NULL);
203
      $changed = TRUE;
204
    }
205
206
    // Convert field language settings.
207
    $query_options = $this->get_option('query');
208
    if (isset($query_options['options']['field_language'])) {
209
      $this->set_option('field_language', $query_options['options']['field_language']);
210
      unset($query_options['options']['field_language']);
211
      $changed = TRUE;
212
    }
213
    if (isset($query_options['options']['field_language_add_to_query'])) {
214
      $this->set_option('field_language_add_to_query', $query_options['options']['field_language_add_to_query']);
215
      unset($query_options['options']['field_language_add_to_query']);
216
      $changed = TRUE;
217
    }
218
    $this->set_option('query', $query_options);
219
220
    // Convert filter groups.
221
    $filter_groups = $this->get_option('filter_groups');
222 5d12d676 Assos Assos
    // Only convert if it wasn't converted yet, which is the case if there is a
223 8be7bf84 Assos Assos
    // '0' group.
224 85ad3d82 Assos Assos
    if (isset($filter_groups['groups'][0])) {
225
      // Update filter groups.
226 8be7bf84 Assos Assos
      $filter_groups['groups'] = views_array_key_plus($filter_groups['groups']);
227 85ad3d82 Assos Assos
      $this->set_option('filter_groups', $filter_groups);
228
      // Update the filter group on each filter.
229
      $filters = $this->get_option('filters');
230
      foreach ($filters as &$filter) {
231
        if (isset($filter['group'])) {
232
          $filter['group']++;
233
        }
234
        else {
235
          $filter['group'] = 1;
236
        }
237
      }
238
      $this->set_option('filters', $filters);
239
      $changed = TRUE;
240
    }
241
242
    // Filter groups were allowed to be rewritten without its filters, so
243
    // before this update the view was using the default values. To be sure that
244
    // the existing view isn't broken, don't use this overridden values but copy
245
    // them from the default display. Only do this if the filters are overridden
246
    // but the filter_groups are not marked as so.
247
    if (!$this->is_default_display() && !$this->options['defaults']['filters'] && $this->options['defaults']['filter_groups']) {
248
      // Set filter_groups to be overridden and save the value in the
249
      // display_options as well.
250
      $this->options['defaults']['filter_groups'] = FALSE;
251
      $this->display->display_options['defaults']['filter_groups'] = $this->options['defaults']['filter_groups'];
252
      // Copy the filter_groups from the default, and add them to the
253
      // display_options as well. $this->default_display is not initialized at
254
      // this point.
255
      $this->options['filter_groups'] = $this->view->display['default']->handler->options['filter_groups'];
256
      $this->display->display_options['filter_groups'] = $this->options['filter_groups'];
257
258
      $changed = TRUE;
259
    }
260
261
    // Mark the view as changed so the user has a chance to save it.
262
    if ($changed) {
263
      $this->view->changed = TRUE;
264
    }
265
  }
266
267 5d12d676 Assos Assos
  /**
268
   * {@inheritdoc}
269
   */
270
  public function destroy() {
271 85ad3d82 Assos Assos
    parent::destroy();
272
273
    foreach ($this->handlers as $type => $handlers) {
274
      foreach ($handlers as $id => $handler) {
275
        if (is_object($handler)) {
276
          $this->handlers[$type][$id]->destroy();
277
        }
278
      }
279
    }
280
281
    if (isset($this->default_display)) {
282
      unset($this->default_display);
283
    }
284
285
    foreach ($this->extender as $extender) {
286
      $extender->destroy();
287
    }
288
  }
289
290
  /**
291 8be7bf84 Assos Assos
   * If this display is the 'default' display which contains fallback settings.
292
   *
293
   * @return bool
294
   *   This is the default display and contains fallback settings.
295 85ad3d82 Assos Assos
   */
296 5d12d676 Assos Assos
  public function is_default_display() {
297
    return FALSE;
298
  }
299 85ad3d82 Assos Assos
300
  /**
301 8be7bf84 Assos Assos
   * Does this display uses exposed filters?
302
   *
303
   * So the view will know whether or not to build them.
304 85ad3d82 Assos Assos
   */
305 5d12d676 Assos Assos
  public function uses_exposed() {
306 85ad3d82 Assos Assos
    if (!isset($this->has_exposed)) {
307
      foreach ($this->handlers as $type => $value) {
308
        foreach ($this->view->$type as $id => $handler) {
309
          if ($handler->can_expose() && $handler->is_exposed()) {
310
            // one is all we need; if we find it, return true.
311
            $this->has_exposed = TRUE;
312
            return TRUE;
313
          }
314
        }
315
      }
316
      $pager = $this->get_plugin('pager');
317 4003efde Assos Assos
      if ($pager && $pager->uses_exposed()) {
318 85ad3d82 Assos Assos
        $this->has_exposed = TRUE;
319
        return TRUE;
320
      }
321
      $this->has_exposed = FALSE;
322
    }
323
324
    return $this->has_exposed;
325
  }
326
327
  /**
328 8be7bf84 Assos Assos
   * Determine if this display should display the exposed filters widgets.
329 85ad3d82 Assos Assos
   *
330 8be7bf84 Assos Assos
   * If so, the view will know whether or not to render them.
331
   *
332
   * Regardless of what this function returns, exposed filters will not be used
333
   * nor displayed unless uses_exposed() returns TRUE.
334 85ad3d82 Assos Assos
   */
335 5d12d676 Assos Assos
  public function displays_exposed() {
336 85ad3d82 Assos Assos
    return TRUE;
337
  }
338
339
  /**
340
   * Does the display use AJAX?
341
   */
342 5d12d676 Assos Assos
  public function use_ajax() {
343 85ad3d82 Assos Assos
    if (!empty($this->definition['use ajax'])) {
344
      return $this->get_option('use_ajax');
345
    }
346
    return FALSE;
347
  }
348
349
  /**
350
   * Does the display have a pager enabled?
351
   */
352 5d12d676 Assos Assos
  public function use_pager() {
353 85ad3d82 Assos Assos
    $pager = $this->get_plugin('pager');
354
    if ($pager) {
355
      return $pager->use_pager();
356
    }
357
  }
358
359
  /**
360
   * Does the display have a more link enabled?
361
   */
362 5d12d676 Assos Assos
  public function use_more() {
363 85ad3d82 Assos Assos
    if (!empty($this->definition['use more'])) {
364
      return $this->get_option('use_more');
365
    }
366
    return FALSE;
367
  }
368
369
  /**
370
   * Does the display have groupby enabled?
371
   */
372 5d12d676 Assos Assos
  public function use_group_by() {
373 85ad3d82 Assos Assos
    return $this->get_option('group_by');
374
  }
375
376
  /**
377
   * Should the enabled display more link be shown when no more items?
378
   */
379 5d12d676 Assos Assos
  public function use_more_always() {
380 85ad3d82 Assos Assos
    if (!empty($this->definition['use more'])) {
381
      return $this->get_option('use_more_always');
382
    }
383
    return FALSE;
384
  }
385
386 ef1afbb9 Assos Assos
  /**
387
   * Should the enabled display more link being opened in an new window?
388
   */
389 5d12d676 Assos Assos
  public function use_more_open_new_window() {
390 ef1afbb9 Assos Assos
    if (!empty($this->definition['use more'])) {
391
      return $this->get_option('open_new_window');
392
    }
393
    return FALSE;
394
  }
395
396 85ad3d82 Assos Assos
  /**
397
   * Does the display have custom link text?
398
   */
399 5d12d676 Assos Assos
  public function use_more_text() {
400 85ad3d82 Assos Assos
    if (!empty($this->definition['use more'])) {
401
      return $this->get_option('use_more_text');
402
    }
403
    return FALSE;
404
  }
405
406
  /**
407
   * Can this display accept attachments?
408
   */
409 5d12d676 Assos Assos
  public function accept_attachments() {
410 85ad3d82 Assos Assos
    if (empty($this->definition['accept attachments'])) {
411
      return FALSE;
412
    }
413
    if (!empty($this->view->argument) && $this->get_option('hide_attachment_summary')) {
414
      foreach ($this->view->argument as $argument_id => $argument) {
415
        if ($argument->needs_style_plugin() && empty($argument->argument_validated)) {
416
          return FALSE;
417
        }
418
      }
419
    }
420
    return TRUE;
421
  }
422
423
  /**
424
   * Allow displays to attach to other views.
425
   */
426 5d12d676 Assos Assos
  public function attach_to($display_id) {
427
  }
428 85ad3d82 Assos Assos
429
  /**
430 8be7bf84 Assos Assos
   * List which sections are defaultable and what items each section contains.
431 85ad3d82 Assos Assos
   */
432 5d12d676 Assos Assos
  public function defaultable_sections($section = NULL) {
433 85ad3d82 Assos Assos
    $sections = array(
434
      'access' => array('access', 'access_options'),
435
      'access_options' => array('access', 'access_options'),
436
      'cache' => array('cache', 'cache_options'),
437
      'cache_options' => array('cache', 'cache_options'),
438
      'title' => array('title'),
439
      'css_class' => array('css_class'),
440
      'use_ajax' => array('use_ajax'),
441
      'hide_attachment_summary' => array('hide_attachment_summary'),
442
      'hide_admin_links' => array('hide_admin_links'),
443
      'group_by' => array('group_by'),
444
      'query' => array('query'),
445 ef1afbb9 Assos Assos
      'use_more' => array('use_more',
446
        'use_more_always',
447
        'open_new_window',
448
        'use_more_text',
449
      ),
450
      'use_more_always' => array(
451
        'use_more',
452
        'use_more_always',
453
        'open_new_window',
454
        'use_more_text',
455
      ),
456
      'use_more_text' => array(
457
        'use_more',
458
        'use_more_always',
459
        'open_new_window',
460
        'use_more_text',
461
      ),
462
      'open_new_window' => array(
463
        'use_more',
464
        'use_more_always',
465
        'open_new_window',
466
        'use_more_text',
467
      ),
468 85ad3d82 Assos Assos
      'link_display' => array('link_display', 'link_url'),
469
470
      // Force these to cascade properly.
471 8be7bf84 Assos Assos
      'style_plugin' => array(
472
        'style_plugin',
473
        'style_options',
474
        'row_plugin',
475
        'row_options',
476
      ),
477
      'style_options' => array(
478
        'style_plugin',
479
        'style_options',
480
        'row_plugin',
481
        'row_options',
482
      ),
483
      'row_plugin' => array(
484
        'style_plugin',
485
        'style_options',
486
        'row_plugin',
487
        'row_options',
488
      ),
489
      'row_options' => array(
490
        'style_plugin',
491
        'style_options',
492
        'row_plugin',
493
        'row_options',
494
      ),
495 85ad3d82 Assos Assos
496
      'pager' => array('pager', 'pager_options'),
497
      'pager_options' => array('pager', 'pager_options'),
498
499
      'exposed_form' => array('exposed_form', 'exposed_form_options'),
500
      'exposed_form_options' => array('exposed_form', 'exposed_form_options'),
501
502 8be7bf84 Assos Assos
      // These guys are special.
503 85ad3d82 Assos Assos
      'header' => array('header'),
504
      'footer' => array('footer'),
505
      'empty' => array('empty'),
506
      'relationships' => array('relationships'),
507
      'fields' => array('fields'),
508
      'sorts' => array('sorts'),
509
      'arguments' => array('arguments'),
510
      'filters' => array('filters', 'filter_groups'),
511
      'filter_groups' => array('filters', 'filter_groups'),
512
    );
513
514
    // If the display cannot use a pager, then we cannot default it.
515
    if (empty($this->definition['use pager'])) {
516
      unset($sections['pager']);
517
      unset($sections['items_per_page']);
518
    }
519
520
    foreach ($this->extender as $extender) {
521
      $extender->defaultable_sections($sections, $section);
522
    }
523
524
    if ($section) {
525
      if (!empty($sections[$section])) {
526
        return $sections[$section];
527
      }
528
    }
529
    else {
530
      return $sections;
531
    }
532
  }
533
534 5d12d676 Assos Assos
  /**
535
   * {@inheritdoc}
536
   */
537
  public function option_definition() {
538 85ad3d82 Assos Assos
    $options = array(
539
      'defaults' => array(
540
        'default' => array(
541
          'access' => TRUE,
542
          'cache' => TRUE,
543
          'query' => TRUE,
544
          'title' => TRUE,
545
          'css_class' => TRUE,
546
547
          'display_description' => FALSE,
548
          'use_ajax' => TRUE,
549
          'hide_attachment_summary' => TRUE,
550
          'hide_admin_links' => TRUE,
551
          'pager' => TRUE,
552
          'pager_options' => TRUE,
553
          'use_more' => TRUE,
554
          'use_more_always' => TRUE,
555 ef1afbb9 Assos Assos
          'open_new_window' => FALSE,
556 85ad3d82 Assos Assos
          'use_more_text' => TRUE,
557
          'exposed_form' => TRUE,
558
          'exposed_form_options' => TRUE,
559
560
          'link_display' => TRUE,
561
          'link_url' => '',
562
          'group_by' => TRUE,
563
564
          'style_plugin' => TRUE,
565
          'style_options' => TRUE,
566
          'row_plugin' => TRUE,
567
          'row_options' => TRUE,
568
569
          'header' => TRUE,
570
          'footer' => TRUE,
571
          'empty' => TRUE,
572
573
          'relationships' => TRUE,
574
          'fields' => TRUE,
575
          'sorts' => TRUE,
576
          'arguments' => TRUE,
577
          'filters' => TRUE,
578
          'filter_groups' => TRUE,
579
        ),
580
        'export' => FALSE,
581
      ),
582
583
      'title' => array(
584
        'default' => '',
585
        'translatable' => TRUE,
586
      ),
587
      'enabled' => array(
588
        'default' => TRUE,
589
        'translatable' => FALSE,
590
        'bool' => TRUE,
591
      ),
592
      'display_comment' => array(
593
        'default' => '',
594
      ),
595
      'css_class' => array(
596
        'default' => '',
597
        'translatable' => FALSE,
598
      ),
599
      'display_description' => array(
600
        'default' => '',
601
        'translatable' => TRUE,
602
      ),
603
      'use_ajax' => array(
604
        'default' => FALSE,
605
        'bool' => TRUE,
606
      ),
607
      'hide_attachment_summary' => array(
608
        'default' => FALSE,
609
        'bool' => TRUE,
610
      ),
611
      'hide_admin_links' => array(
612
        'default' => FALSE,
613
        'bool' => TRUE,
614
      ),
615 5d12d676 Assos Assos
      // This is legacy code.
616
      // Items_per/offset/use_pager is moved to the pager plugin but the
617
      // automatic update path needs this items defined, so don't remove it.
618 85ad3d82 Assos Assos
      // @see views_plugin_display::init()
619
      'items_per_page' => array(
620
        'default' => 10,
621
      ),
622
      'offset' => array(
623
        'default' => 0,
624
      ),
625
      'use_pager' => array(
626
        'default' => FALSE,
627
        'bool' => TRUE,
628
      ),
629
      'use_more' => array(
630
        'default' => FALSE,
631
        'bool' => TRUE,
632
      ),
633
      'use_more_always' => array(
634
        'default' => FALSE,
635
        'bool' => TRUE,
636
        'export' => 'export_option_always',
637
      ),
638
      'use_more_text' => array(
639
        'default' => 'more',
640
        'translatable' => TRUE,
641
      ),
642
      'link_display' => array(
643
        'default' => '',
644
      ),
645
      'link_url' => array(
646
        'default' => '',
647
      ),
648
      'group_by' => array(
649
        'default' => FALSE,
650
        'bool' => TRUE,
651
      ),
652
      'field_language' => array(
653
        'default' => '***CURRENT_LANGUAGE***',
654
      ),
655
      'field_language_add_to_query' => array(
656
        'default' => 1,
657
      ),
658
659 5d12d676 Assos Assos
      // These types are all plugins that can have individual settings and
660
      // therefore need special handling.
661 85ad3d82 Assos Assos
      'access' => array(
662
        'contains' => array(
663 8be7bf84 Assos Assos
          'type' => array(
664
            'default' => 'none',
665
            'export' => 'export_plugin',
666
            'unpack_translatable' => 'unpack_plugin',
667
          ),
668
        ),
669 85ad3d82 Assos Assos
      ),
670
      'cache' => array(
671
        'contains' => array(
672 8be7bf84 Assos Assos
          'type' => array(
673
            'default' => 'none',
674
            'export' => 'export_plugin',
675
            'unpack_translatable' => 'unpack_plugin',
676
          ),
677
        ),
678 85ad3d82 Assos Assos
      ),
679
      'query' => array(
680
        'contains' => array(
681 8be7bf84 Assos Assos
          'type' => array(
682
            'default' => 'views_query',
683
            'export' => 'export_plugin',
684
          ),
685 85ad3d82 Assos Assos
          'options' => array('default' => array(), 'export' => FALSE),
686 8be7bf84 Assos Assos
        ),
687 85ad3d82 Assos Assos
      ),
688 8be7bf84 Assos Assos
      // Note that exposed_form plugin has options in a separate array, while
689
      // access and cache do not. access and cache are legacy and that pattern
690
      // should not be repeated, but it is left as is to reduce the need to
691
      // modify older views. Let's consider the pattern used here to be the
692
      // template from which future plugins should be copied.
693 85ad3d82 Assos Assos
      'exposed_form' => array(
694
        'contains' => array(
695 8be7bf84 Assos Assos
          'type' => array(
696
            'default' => 'basic',
697
            'export' => 'export_plugin',
698
            'unpack_translatable' => 'unpack_plugin',
699
          ),
700 85ad3d82 Assos Assos
          'options' => array('default' => array(), 'export' => FALSE),
701 8be7bf84 Assos Assos
        ),
702 85ad3d82 Assos Assos
      ),
703
      'pager' => array(
704
        'contains' => array(
705 8be7bf84 Assos Assos
          'type' => array(
706
            'default' => 'full',
707
            'export' => 'export_plugin',
708
            'unpack_translatable' => 'unpack_plugin',
709
          ),
710 85ad3d82 Assos Assos
          'options' => array('default' => array(), 'export' => FALSE),
711 8be7bf84 Assos Assos
        ),
712 85ad3d82 Assos Assos
      ),
713
714 8be7bf84 Assos Assos
      // Note that the styles have their options completely independent. Like
715
      // access and cache above, this is a legacy pattern and should not be
716
      // repeated.
717 85ad3d82 Assos Assos
      'style_plugin' => array(
718
        'default' => 'default',
719
        'export' => 'export_style',
720
        'unpack_translatable' => 'unpack_style',
721
      ),
722
      'style_options' => array(
723
        'default' => array(),
724
        'export' => FALSE,
725
      ),
726
      'row_plugin' => array(
727
        'default' => 'fields',
728
        'export' => 'export_style',
729
        'unpack_translatable' => 'unpack_style',
730
      ),
731
      'row_options' => array(
732
        'default' => array(),
733
        'export' => FALSE,
734
      ),
735
736
      'exposed_block' => array(
737
        'default' => FALSE,
738
      ),
739
740
      'header' => array(
741
        'default' => array(),
742
        'export' => 'export_handler',
743
        'unpack_translatable' => 'unpack_handler',
744
      ),
745
      'footer' => array(
746
        'default' => array(),
747
        'export' => 'export_handler',
748
        'unpack_translatable' => 'unpack_handler',
749
      ),
750
      'empty' => array(
751
        'default' => array(),
752
        'export' => 'export_handler',
753
        'unpack_translatable' => 'unpack_handler',
754
      ),
755
756
      // We want these to export last.
757
      // These are the 5 handler types.
758
      'relationships' => array(
759
        'default' => array(),
760
        'export' => 'export_handler',
761
        'unpack_translatable' => 'unpack_handler',
762
763
      ),
764
      'fields' => array(
765
        'default' => array(),
766
        'export' => 'export_handler',
767
        'unpack_translatable' => 'unpack_handler',
768
      ),
769
      'sorts' => array(
770
        'default' => array(),
771
        'export' => 'export_handler',
772
        'unpack_translatable' => 'unpack_handler',
773
      ),
774
      'arguments' => array(
775
        'default' => array(),
776
        'export' => 'export_handler',
777
        'unpack_translatable' => 'unpack_handler',
778
      ),
779
      'filter_groups' => array(
780
        'contains' => array(
781
          'operator' => array('default' => 'AND'),
782
          'groups' => array('default' => array(1 => 'AND')),
783
        ),
784
      ),
785
      'filters' => array(
786
        'default' => array(),
787
        'export' => 'export_handler',
788
        'unpack_translatable' => 'unpack_handler',
789
      ),
790
    );
791
792
    if (empty($this->definition['use pager'])) {
793
      $options['defaults']['default']['use_pager'] = FALSE;
794
      $options['defaults']['default']['items_per_page'] = FALSE;
795
      $options['defaults']['default']['offset'] = FALSE;
796
      $options['defaults']['default']['pager'] = FALSE;
797
      $options['pager']['contains']['type']['default'] = 'some';
798
    }
799
800
    if ($this->is_default_display()) {
801
      unset($options['defaults']);
802
    }
803
804
    foreach ($this->extender as $extender) {
805
      $extender->options_definition_alter($options);
806
    }
807
808
    return $options;
809
  }
810
811
  /**
812
   * Check to see if the display has a 'path' field.
813
   *
814
   * This is a pure function and not just a setting on the definition
815
   * because some displays (such as a panel pane) may have a path based
816
   * upon configuration.
817
   *
818
   * By default, displays do not have a path.
819
   */
820 5d12d676 Assos Assos
  public function has_path() {
821
    return FALSE;
822
  }
823 85ad3d82 Assos Assos
824
  /**
825
   * Check to see if the display has some need to link to another display.
826
   *
827 5d12d676 Assos Assos
   * For the most part, displays without a path will use a link display.
828
   * However, sometimes displays that have a path might also need to link to
829
   * another display. This is true for feeds.
830 85ad3d82 Assos Assos
   */
831 5d12d676 Assos Assos
  public function uses_link_display() {
832
    return !$this->has_path();
833
  }
834 85ad3d82 Assos Assos
835
  /**
836 d719f12f Assos Assos
   * Check to see if the display can put the exposed form in a block.
837 85ad3d82 Assos Assos
   *
838 5d12d676 Assos Assos
   * By default, displays that do not have a path cannot disconnect the exposed
839
   * form and put it in a block, because the form has no place to go and Views
840
   * really wants the forms to go to a specific page.
841 85ad3d82 Assos Assos
   */
842 5d12d676 Assos Assos
  public function uses_exposed_form_in_block() {
843
    return $this->has_path();
844
  }
845 85ad3d82 Assos Assos
846
  /**
847 5d12d676 Assos Assos
   * Check to see which display to use when creating links.
848 85ad3d82 Assos Assos
   */
849 5d12d676 Assos Assos
  public function get_link_display() {
850 85ad3d82 Assos Assos
    $display_id = $this->get_option('link_display');
851
    // If unknown, pick the first one.
852
    if (empty($display_id) || empty($this->view->display[$display_id])) {
853
      foreach ($this->view->display as $display_id => $display) {
854
        if (!empty($display->handler) && $display->handler->has_path()) {
855
          return $display_id;
856
        }
857
      }
858
    }
859
    else {
860
      return $display_id;
861
    }
862 8be7bf84 Assos Assos
    // Fall-through returns NULL.
863 85ad3d82 Assos Assos
  }
864
865
  /**
866
   * Return the base path to use for this display.
867
   *
868 5d12d676 Assos Assos
   * This can be overridden for displays that do strange things with the path.
869 85ad3d82 Assos Assos
   */
870 5d12d676 Assos Assos
  public function get_path() {
871 85ad3d82 Assos Assos
    if ($this->has_path()) {
872
      return $this->get_option('path');
873
    }
874
875
    $display_id = $this->get_link_display();
876
    if ($display_id && !empty($this->view->display[$display_id]) && is_object($this->view->display[$display_id]->handler)) {
877
      return $this->view->display[$display_id]->handler->get_path();
878
    }
879
880
    if ($this->get_option('link_display') == 'custom_url' && $link_url = $this->get_option('link_url')) {
881
      return $link_url;
882
    }
883
  }
884
885 5d12d676 Assos Assos
  /**
886
   *
887
   */
888
  public function get_url() {
889 85ad3d82 Assos Assos
    return $this->view->get_url();
890
  }
891
892
  /**
893 5d12d676 Assos Assos
   * Check to see if the display needs a breadcrumb.
894 85ad3d82 Assos Assos
   *
895 5d12d676 Assos Assos
   * By default, displays do not need breadcrumbs.
896 85ad3d82 Assos Assos
   */
897 5d12d676 Assos Assos
  public function uses_breadcrumb() {
898
    return FALSE;
899
  }
900 85ad3d82 Assos Assos
901
  /**
902 5d12d676 Assos Assos
   * Determine if a given option is set to use the default or current display.
903 85ad3d82 Assos Assos
   *
904
   * @return
905 5d12d676 Assos Assos
   *   TRUE for the default display.
906 85ad3d82 Assos Assos
   */
907 5d12d676 Assos Assos
  public function is_defaulted($option) {
908 85ad3d82 Assos Assos
    return !$this->is_default_display() && !empty($this->default_display) && !empty($this->options['defaults'][$option]);
909
  }
910
911
  /**
912 5d12d676 Assos Assos
   * Intelligently get an option either from this or default display.
913 85ad3d82 Assos Assos
   */
914 5d12d676 Assos Assos
  public function get_option($option) {
915 85ad3d82 Assos Assos
    if ($this->is_defaulted($option)) {
916
      return $this->default_display->get_option($option);
917
    }
918
919 5d12d676 Assos Assos
    if (isset($this->options[$option]) || array_key_exists($option, $this->options)) {
920 85ad3d82 Assos Assos
      return $this->options[$option];
921
    }
922
  }
923
924
  /**
925
   * Determine if the display's style uses fields.
926
   */
927 5d12d676 Assos Assos
  public function uses_fields() {
928 85ad3d82 Assos Assos
    $plugin = $this->get_plugin();
929
    if ($plugin) {
930
      return $plugin->uses_fields();
931
    }
932
  }
933
934
  /**
935
   * Get the instance of a plugin, for example style or row.
936
   *
937
   * @param string $type
938
   *   The type of the plugin.
939
   * @param string $name
940
   *   The name of the plugin defined in hook_views_plugins.
941
   *
942
   * @return views_plugin|FALSE
943 8be7bf84 Assos Assos
   *   FALSE if no plugin, otherwise the requested instance of a plugin.
944 85ad3d82 Assos Assos
   */
945 5d12d676 Assos Assos
  public function get_plugin($type = 'style', $name = NULL) {
946 85ad3d82 Assos Assos
    static $cache = array();
947
    if (!isset($cache[$type][$name])) {
948
      switch ($type) {
949
        case 'style':
950
        case 'row':
951
          $option_name = $type . '_plugin';
952
          $options = $this->get_option($type . '_options');
953
          if (!$name) {
954
            $name = $this->get_option($option_name);
955
          }
956
          break;
957 5d12d676 Assos Assos
958 85ad3d82 Assos Assos
        case 'query':
959
          $views_data = views_fetch_data($this->view->base_table);
960
          $name = !empty($views_data['table']['base']['query class']) ? $views_data['table']['base']['query class'] : 'views_query';
961
        default:
962
          $option_name = $type;
963
          $options = $this->get_option($type);
964
          if (!$name) {
965
            $name = $options['type'];
966
          }
967
968 5d12d676 Assos Assos
          // Access & cache store their options as siblings with the type; all
969
          // others use an 'options' array.
970 85ad3d82 Assos Assos
          if ($type != 'access' && $type != 'cache') {
971
            $options = $options['options'];
972
          }
973
      }
974
      $plugin = views_get_plugin($type, $name);
975
976
      if (!$plugin) {
977 8be7bf84 Assos Assos
        return FALSE;
978 85ad3d82 Assos Assos
      }
979
      if ($type != 'query') {
980
        $plugin->init($this->view, $this->display, $options);
981
      }
982
      else {
983
        $display_id = $this->is_defaulted($option_name) ? $this->display->id : 'default';
984
        $plugin->localization_keys = array($display_id, $type);
985
986
        if (!isset($this->base_field)) {
987
          $views_data = views_fetch_data($this->view->base_table);
988
          $this->view->base_field = !empty($views_data['table']['base']['field']) ? $views_data['table']['base']['field'] : '';
989
        }
990
        $plugin->init($this->view->base_table, $this->view->base_field, $options);
991
      }
992
      $cache[$type][$name] = $plugin;
993
    }
994
995
    return $cache[$type][$name];
996
  }
997
998
  /**
999
   * Get the handler object for a single handler.
1000
   */
1001 5d12d676 Assos Assos
  public function &get_handler($type, $id) {
1002 85ad3d82 Assos Assos
    if (!isset($this->handlers[$type])) {
1003
      $this->get_handlers($type);
1004
    }
1005
1006
    if (isset($this->handlers[$type][$id])) {
1007
      return $this->handlers[$type][$id];
1008
    }
1009
1010
    // So we can return a reference.
1011
    $null = NULL;
1012
    return $null;
1013
  }
1014
1015
  /**
1016
   * Get a full array of handlers for $type. This caches them.
1017
   */
1018 5d12d676 Assos Assos
  public function &get_handlers($type) {
1019 85ad3d82 Assos Assos
    if (!isset($this->handlers[$type])) {
1020
      $this->handlers[$type] = array();
1021
      $types = views_object_types();
1022
      $plural = $types[$type]['plural'];
1023
1024
      foreach ($this->get_option($plural) as $id => $info) {
1025
        // If this is during form submission and there are temporary options
1026
        // which can only appear if the view is in the edit cache, use those
1027
        // options instead. This is used for AJAX multi-step stuff.
1028
        if (isset($_POST['form_id']) && isset($this->view->temporary_options[$type][$id])) {
1029
          $info = $this->view->temporary_options[$type][$id];
1030
        }
1031
1032
        if ($info['id'] != $id) {
1033
          $info['id'] = $id;
1034
        }
1035
1036
        // If aggregation is on, the group type might override the actual
1037
        // handler that is in use. This piece of code checks that and,
1038
        // if necessary, sets the override handler.
1039
        $override = NULL;
1040
        if ($this->use_group_by() && !empty($info['group_type'])) {
1041
          if (empty($this->view->query)) {
1042
            $this->view->init_query();
1043
          }
1044
          $aggregate = $this->view->query->get_aggregation_info();
1045
          if (!empty($aggregate[$info['group_type']]['handler'][$type])) {
1046
            $override = $aggregate[$info['group_type']]['handler'][$type];
1047
          }
1048
        }
1049
1050
        if (!empty($types[$type]['type'])) {
1051
          $handler_type = $types[$type]['type'];
1052
        }
1053
        else {
1054
          $handler_type = $type;
1055
        }
1056
1057
        $handler = views_get_handler($info['table'], $info['field'], $handler_type, $override);
1058
        if ($handler) {
1059
          // Special override for area types so they know where they come from.
1060
          if ($handler_type == 'area') {
1061
            $handler->handler_type = $type;
1062
          }
1063
1064
          $handler->init($this->view, $info);
1065
          $this->handlers[$type][$id] = &$handler;
1066
        }
1067
1068
        // Prevent reference problems.
1069
        unset($handler);
1070
      }
1071
    }
1072
1073
    return $this->handlers[$type];
1074
  }
1075
1076
  /**
1077 5d12d676 Assos Assos
   * List of fields for the current display with the associated relationship.
1078 85ad3d82 Assos Assos
   *
1079 8be7bf84 Assos Assos
   * @param bool $groupable_only
1080
   *   Return only an array of field labels from handler that return TRUE from
1081
   *   use_string_group_by method.
1082 85ad3d82 Assos Assos
   */
1083 5d12d676 Assos Assos
  public function get_field_labels() {
1084 8be7bf84 Assos Assos
    // Use func_get_arg so the function signature isn't amended but we can still
1085
    // pass TRUE into the function to filter by groupable handlers.
1086 85ad3d82 Assos Assos
    $args = func_get_args();
1087
    $groupable_only = isset($args[0]) ? $args[0] : FALSE;
1088
1089
    $options = array();
1090
    foreach ($this->get_handlers('relationship') as $relationship => $handler) {
1091
      if ($label = $handler->label()) {
1092
        $relationships[$relationship] = $label;
1093
      }
1094
      else {
1095
        $relationships[$relationship] = $handler->ui_name();
1096
      }
1097
    }
1098
1099
    foreach ($this->get_handlers('field') as $id => $handler) {
1100
      if ($groupable_only && !$handler->use_string_group_by()) {
1101
        // Continue to next handler if it's not groupable.
1102
        continue;
1103
      }
1104
      if ($label = $handler->label()) {
1105
        $options[$id] = $label;
1106
      }
1107
      else {
1108
        $options[$id] = $handler->ui_name();
1109
      }
1110
      if (!empty($handler->options['relationship']) && !empty($relationships[$handler->options['relationship']])) {
1111
        $options[$id] = '(' . $relationships[$handler->options['relationship']] . ') ' . $options[$id];
1112
      }
1113
    }
1114
    return $options;
1115
  }
1116
1117
  /**
1118
   * Intelligently set an option either from this display or from the
1119
   * default display, if directed to do so.
1120
   */
1121 5d12d676 Assos Assos
  public function set_option($option, $value) {
1122 85ad3d82 Assos Assos
    if ($this->is_defaulted($option)) {
1123
      return $this->default_display->set_option($option, $value);
1124
    }
1125
1126 8be7bf84 Assos Assos
    // Set this in two places: On the handler where we'll notice it but also on
1127
    // the display object so it gets saved. This should only be a temporary fix.
1128 85ad3d82 Assos Assos
    $this->display->display_options[$option] = $value;
1129
    return $this->options[$option] = $value;
1130
  }
1131
1132
  /**
1133
   * Set an option and force it to be an override.
1134
   */
1135 5d12d676 Assos Assos
  public function override_option($option, $value) {
1136 85ad3d82 Assos Assos
    $this->set_override($option, FALSE);
1137
    $this->set_option($option, $value);
1138
  }
1139
1140
  /**
1141
   * Because forms may be split up into sections, this provides
1142
   * an easy URL to exactly the right section. Don't override this.
1143
   */
1144 5d12d676 Assos Assos
  public function option_link($text, $section, $class = '', $title = '') {
1145 85ad3d82 Assos Assos
    views_add_js('ajax');
1146
    if (!empty($class)) {
1147
      $text = '<span>' . $text . '</span>';
1148
    }
1149
1150
    if (!trim($text)) {
1151
      $text = t('Broken field');
1152
    }
1153
1154
    if (empty($title)) {
1155
      $title = $text;
1156
    }
1157
1158 b08fce64 Assos Assos
    // Truncate the path as it is displayed as a link.
1159
    if ($section == 'path') {
1160
      $text = views_ui_truncate($text, 24);
1161
    }
1162
1163 8be7bf84 Assos Assos
    return l($text,
1164
        'admin/structure/views/nojs/display/' . $this->view->name . '/' . $this->display->id . '/' . $section,
1165
        array(
1166
          'attributes' => array(
1167
            'class' => 'views-ajax-link ' . $class,
1168
            'title' => $title,
1169
            'id' => drupal_html_id('views-' . $this->display->id . '-' . $section),
1170
          ),
1171
          'html' => TRUE,
1172
        )
1173
      );
1174 85ad3d82 Assos Assos
  }
1175
1176
  /**
1177
   * Returns to tokens for arguments.
1178
   *
1179 8be7bf84 Assos Assos
   * This function is similar to views_handler_field::get_render_tokens() but
1180
   * without fields tokens.
1181 85ad3d82 Assos Assos
   */
1182 5d12d676 Assos Assos
  public function get_arguments_tokens() {
1183 85ad3d82 Assos Assos
    $tokens = array();
1184
    if (!empty($this->view->build_info['substitutions'])) {
1185
      $tokens = $this->view->build_info['substitutions'];
1186
    }
1187
    $count = 0;
1188
    foreach ($this->view->display_handler->get_handlers('argument') as $arg => $handler) {
1189
      $token = '%' . ++$count;
1190
      if (!isset($tokens[$token])) {
1191
        $tokens[$token] = '';
1192
      }
1193
1194
      // Use strip tags as there should never be HTML in the path.
1195
      // However, we need to preserve special characters like " that
1196
      // were removed by check_plain().
1197
      $tokens['!' . $count] = isset($this->view->args[$count - 1]) ? strip_tags(decode_entities($this->view->args[$count - 1])) : '';
1198
    }
1199
1200
    return $tokens;
1201
  }
1202
1203
  /**
1204
   * Provide the default summary for options in the views UI.
1205
   *
1206
   * This output is returned as an array.
1207
   */
1208 5d12d676 Assos Assos
  public function options_summary(&$categories, &$options) {
1209 85ad3d82 Assos Assos
    $categories = array(
1210
      'title' => array(
1211
        'title' => t('Title'),
1212
        'column' => 'first',
1213
      ),
1214
      'format' => array(
1215
        'title' => t('Format'),
1216
        'column' => 'first',
1217
      ),
1218
      'filters' => array(
1219
        'title' => t('Filters'),
1220
        'column' => 'first',
1221
      ),
1222
      'fields' => array(
1223
        'title' => t('Fields'),
1224
        'column' => 'first',
1225
      ),
1226
      'pager' => array(
1227
        'title' => t('Pager'),
1228
        'column' => 'second',
1229
      ),
1230
      'exposed' => array(
1231
        'title' => t('Exposed form'),
1232
        'column' => 'third',
1233
        'build' => array(
1234
          '#weight' => 1,
1235
        ),
1236
      ),
1237
      'access' => array(
1238
        'title' => '',
1239
        'column' => 'second',
1240
        'build' => array(
1241
          '#weight' => -5,
1242
        ),
1243
      ),
1244
      'other' => array(
1245
        'title' => t('Other'),
1246
        'column' => 'third',
1247
        'build' => array(
1248
          '#weight' => 2,
1249
        ),
1250
      ),
1251
    );
1252
1253
    if ($this->display->id != 'default') {
1254
      $options['display_id'] = array(
1255
        'category' => 'other',
1256
        'title' => t('Machine Name'),
1257
        'value' => !empty($this->display->new_id) ? check_plain($this->display->new_id) : check_plain($this->display->id),
1258
        'desc' => t('Change the machine name of this display.'),
1259
      );
1260
    }
1261
1262 d719f12f Assos Assos
    $display_comment = check_plain(views_ui_truncate($this->get_option('display_comment'), 80));
1263 85ad3d82 Assos Assos
    $options['display_comment'] = array(
1264
      'category' => 'other',
1265
      'title' => t('Comment'),
1266
      'value' => !empty($display_comment) ? $display_comment : t('No comment'),
1267
      'desc' => t('Comment or document this display.'),
1268
    );
1269
1270
    $title = strip_tags($this->get_option('title'));
1271
    if (!$title) {
1272
      $title = t('None');
1273
    }
1274
1275
    $options['title'] = array(
1276
      'category' => 'title',
1277
      'title' => t('Title'),
1278
      'value' => $title,
1279
      'desc' => t('Change the title that this display will use.'),
1280
    );
1281
1282
    $style_plugin = views_fetch_plugin_data('style', $this->get_option('style_plugin'));
1283
    $style_plugin_instance = $this->get_plugin('style');
1284
    $style_summary = empty($style_plugin['title']) ? t('Missing style plugin') : $style_plugin_instance->summary_title();
1285
    $style_title = empty($style_plugin['title']) ? t('Missing style plugin') : $style_plugin_instance->plugin_title();
1286
1287
    $style = '';
1288
1289
    $options['style_plugin'] = array(
1290
      'category' => 'format',
1291
      'title' => t('Format'),
1292
      'value' => $style_title,
1293
      'setting' => $style_summary,
1294
      'desc' => t('Change the way content is formatted.'),
1295
    );
1296
1297 5d12d676 Assos Assos
    // This adds a 'Settings' link to the style_options setting if the style
1298
    // has options.
1299 85ad3d82 Assos Assos
    if (!empty($style_plugin['uses options'])) {
1300
      $options['style_plugin']['links']['style_options'] = t('Change settings for this format');
1301
    }
1302
1303
    if (!empty($style_plugin['uses row plugin'])) {
1304
      $row_plugin = views_fetch_plugin_data('row', $this->get_option('row_plugin'));
1305
      $row_plugin_instance = $this->get_plugin('row');
1306
      $row_summary = empty($row_plugin['title']) ? t('Missing style plugin') : $row_plugin_instance->summary_title();
1307
      $row_title = empty($row_plugin['title']) ? t('Missing style plugin') : $row_plugin_instance->plugin_title();
1308
1309
      $options['row_plugin'] = array(
1310
        'category' => 'format',
1311
        'title' => t('Show'),
1312
        'value' => $row_title,
1313
        'setting' => $row_summary,
1314
        'desc' => t('Change the way each row in the view is styled.'),
1315
      );
1316 5d12d676 Assos Assos
      // This adds a 'Settings' link to the row_options setting if the row
1317
      // style has options.
1318 85ad3d82 Assos Assos
      if (!empty($row_plugin['uses options'])) {
1319
        $options['row_plugin']['links']['row_options'] = t('Change settings for this style');
1320
      }
1321
    }
1322
    if (!empty($this->definition['use ajax'])) {
1323
      $options['use_ajax'] = array(
1324
        'category' => 'other',
1325
        'title' => t('Use AJAX'),
1326
        'value' => $this->get_option('use_ajax') ? t('Yes') : t('No'),
1327
        'desc' => t('Change whether or not this display will use AJAX.'),
1328
      );
1329
    }
1330
    if (!empty($this->definition['accept attachments'])) {
1331
      $options['hide_attachment_summary'] = array(
1332
        'category' => 'other',
1333
        'title' => t('Hide attachments in summary'),
1334
        'value' => $this->get_option('hide_attachment_summary') ? t('Yes') : t('No'),
1335
        'desc' => t('Change whether or not to display attachments when displaying a contextual filter summary.'),
1336
      );
1337
    }
1338
    if (!isset($this->definition['contextual links locations']) || !empty($this->definition['contextual links locations'])) {
1339
      $options['hide_admin_links'] = array(
1340
        'category' => 'other',
1341
        'title' => t('Hide contextual links'),
1342
        'value' => $this->get_option('hide_admin_links') ? t('Yes') : t('No'),
1343
        'desc' => t('Change whether or not to display contextual links for this view.'),
1344
      );
1345
    }
1346
1347
    $pager_plugin = $this->get_plugin('pager');
1348
    if (!$pager_plugin) {
1349 5d12d676 Assos Assos
      // Default to the no pager plugin.
1350 85ad3d82 Assos Assos
      $pager_plugin = views_get_plugin('pager', 'none');
1351
    }
1352
1353
    $pager_str = $pager_plugin->summary_title();
1354
1355
    $options['pager'] = array(
1356
      'category' => 'pager',
1357
      'title' => t('Use pager'),
1358
      'value' => $pager_plugin->plugin_title(),
1359
      'setting' => $pager_str,
1360
      'desc' => t("Change this display's pager setting."),
1361
    );
1362
1363 5d12d676 Assos Assos
    // If pagers aren't allowed, change the text of the item.
1364 85ad3d82 Assos Assos
    if (empty($this->definition['use pager'])) {
1365
      $options['pager']['title'] = t('Items to display');
1366
    }
1367
1368
    if (!empty($pager_plugin->definition['uses options'])) {
1369
      $options['pager']['links']['pager_options'] = t('Change settings for this pager type.');
1370
    }
1371
1372
    if (!empty($this->definition['use more'])) {
1373
      $options['use_more'] = array(
1374
        'category' => 'pager',
1375
        'title' => t('More link'),
1376
        'value' => $this->get_option('use_more') ? t('Yes') : t('No'),
1377
        'desc' => t('Specify whether this display will provide a "more" link.'),
1378
      );
1379
    }
1380
1381
    $this->view->init_query();
1382
    if ($this->view->query->get_aggregation_info()) {
1383
      $options['group_by'] = array(
1384
        'category' => 'other',
1385
        'title' => t('Use aggregation'),
1386
        'value' => $this->get_option('group_by') ? t('Yes') : t('No'),
1387
        'desc' => t('Allow grouping and aggregation (calculation) of fields.'),
1388
      );
1389
    }
1390
1391
    $options['query'] = array(
1392
      'category' => 'other',
1393
      'title' => t('Query settings'),
1394
      'value' => t('Settings'),
1395
      'desc' => t('Allow to set some advanced settings for the query plugin'),
1396
    );
1397
1398
    $languages = array(
1399 8be7bf84 Assos Assos
      '***CURRENT_LANGUAGE***' => t("Current user's language"),
1400
      '***DEFAULT_LANGUAGE***' => t("Default site language"),
1401
      LANGUAGE_NONE => t('Language neutral'),
1402 85ad3d82 Assos Assos
    );
1403 4003efde Assos Assos
    $languages = array_merge($languages, views_language_list());
1404
1405 85ad3d82 Assos Assos
    $field_language = array();
1406
    $options['field_language'] = array(
1407
      'category' => 'other',
1408
      'title' => t('Field Language'),
1409
      'value' => $languages[$this->get_option('field_language')],
1410
      'desc' => t('All fields which support translations will be displayed in the selected language.'),
1411
    );
1412
1413
    $access_plugin = $this->get_plugin('access');
1414
    if (!$access_plugin) {
1415 8be7bf84 Assos Assos
      // Default to the no access control plugin.
1416 85ad3d82 Assos Assos
      $access_plugin = views_get_plugin('access', 'none');
1417
    }
1418
1419
    $access_str = $access_plugin->summary_title();
1420
1421
    $options['access'] = array(
1422
      'category' => 'access',
1423
      'title' => t('Access'),
1424
      'value' => $access_plugin->plugin_title(),
1425
      'setting' => $access_str,
1426
      'desc' => t('Specify access control type for this display.'),
1427
    );
1428
1429
    if (!empty($access_plugin->definition['uses options'])) {
1430
      $options['access']['links']['access_options'] = t('Change settings for this access type.');
1431
    }
1432
1433
    $cache_plugin = $this->get_plugin('cache');
1434
    if (!$cache_plugin) {
1435 8be7bf84 Assos Assos
      // Default to the no cache control plugin.
1436 85ad3d82 Assos Assos
      $cache_plugin = views_get_plugin('cache', 'none');
1437
    }
1438
1439
    $cache_str = $cache_plugin->summary_title();
1440
1441
    $options['cache'] = array(
1442
      'category' => 'other',
1443
      'title' => t('Caching'),
1444
      'value' => $cache_plugin->plugin_title(),
1445
      'setting' => $cache_str,
1446
      'desc' => t('Specify caching type for this display.'),
1447
    );
1448
1449
    if (!empty($cache_plugin->definition['uses options'])) {
1450
      $options['cache']['links']['cache_options'] = t('Change settings for this caching type.');
1451
    }
1452
1453
    if (!empty($access_plugin->definition['uses options'])) {
1454
      $options['access']['links']['access_options'] = t('Change settings for this access type.');
1455
    }
1456
1457
    if ($this->uses_link_display()) {
1458
      $display_id = $this->get_link_display();
1459
      $link_display = empty($this->view->display[$display_id]) ? t('None') : check_plain($this->view->display[$display_id]->display_title);
1460 8be7bf84 Assos Assos
      $link_display = $this->get_option('link_display') == 'custom_url' ? t('Custom URL') : $link_display;
1461 85ad3d82 Assos Assos
      $options['link_display'] = array(
1462
        'category' => 'other',
1463
        'title' => t('Link display'),
1464
        'value' => $link_display,
1465
        'desc' => t('Specify which display or custom url this display will link to.'),
1466
      );
1467
    }
1468
1469
    if ($this->uses_exposed_form_in_block()) {
1470
      $options['exposed_block'] = array(
1471
        'category' => 'exposed',
1472
        'title' => t('Exposed form in block'),
1473
        'value' => $this->get_option('exposed_block') ? t('Yes') : t('No'),
1474
        'desc' => t('Allow the exposed form to appear in a block instead of the view.'),
1475
      );
1476
    }
1477
1478
    $exposed_form_plugin = $this->get_plugin('exposed_form');
1479
    if (!$exposed_form_plugin) {
1480 5d12d676 Assos Assos
      // Default to the no cache control plugin.
1481 85ad3d82 Assos Assos
      $exposed_form_plugin = views_get_plugin('exposed_form', 'basic');
1482
    }
1483
1484
    $exposed_form_str = $exposed_form_plugin->summary_title();
1485
1486
    $options['exposed_form'] = array(
1487
      'category' => 'exposed',
1488
      'title' => t('Exposed form style'),
1489
      'value' => $exposed_form_plugin->plugin_title(),
1490
      'setting' => $exposed_form_str,
1491
      'desc' => t('Select the kind of exposed filter to use.'),
1492
    );
1493
1494
    if (!empty($exposed_form_plugin->definition['uses options'])) {
1495
      $options['exposed_form']['links']['exposed_form_options'] = t('Exposed form settings for this exposed form style.');
1496
    }
1497
1498
    $css_class = check_plain(trim($this->get_option('css_class')));
1499
    if (!$css_class) {
1500
      $css_class = t('None');
1501
    }
1502
1503
    $options['css_class'] = array(
1504
      'category' => 'other',
1505
      'title' => t('CSS class'),
1506
      'value' => $css_class,
1507
      'desc' => t('Change the CSS class name(s) that will be added to this display.'),
1508
    );
1509
1510
    $options['analyze-theme'] = array(
1511
      'category' => 'other',
1512
      'title' => t('Theme'),
1513
      'value' => t('Information'),
1514
      'desc' => t('Get information on how to theme this display'),
1515
    );
1516
1517
    foreach ($this->extender as $extender) {
1518
      $extender->options_summary($categories, $options);
1519
    }
1520
  }
1521
1522
  /**
1523
   * Provide the default form for setting options.
1524
   */
1525 5d12d676 Assos Assos
  public function options_form(&$form, &$form_state) {
1526 85ad3d82 Assos Assos
    parent::options_form($form, $form_state);
1527
    if ($this->defaultable_sections($form_state['section'])) {
1528
      views_ui_standard_display_dropdown($form, $form_state, $form_state['section']);
1529
    }
1530
    $form['#title'] = check_plain($this->display->display_title) . ': ';
1531
1532 8be7bf84 Assos Assos
    // Set the 'section' to highlight on the form. If it's the item we're
1533
    // looking at is pulling from the default display, reflect that. Don't use
1534
    // is_defaulted since we want it to show up even on the default display.
1535 85ad3d82 Assos Assos
    if (!empty($this->options['defaults'][$form_state['section']])) {
1536
      $form['#section'] = 'default-' . $form_state['section'];
1537
    }
1538
    else {
1539
      $form['#section'] = $this->display->id . '-' . $form_state['section'];
1540
    }
1541
1542
    switch ($form_state['section']) {
1543
      case 'display_id':
1544
        $form['#title'] .= t('The machine name of this display');
1545
        $form['display_id'] = array(
1546
          '#type' => 'textfield',
1547
          '#description' => t('This is machine name of the display.'),
1548
          '#default_value' => !empty($this->display->new_id) ? $this->display->new_id : $this->display->id,
1549
          '#required' => TRUE,
1550
          '#size' => 64,
1551
        );
1552
        break;
1553 5d12d676 Assos Assos
1554 85ad3d82 Assos Assos
      case 'display_title':
1555
        $form['#title'] .= t('The name and the description of this display');
1556
        $form['display_title'] = array(
1557
          '#title' => t('Name'),
1558
          '#type' => 'textfield',
1559
          '#description' => t('This name will appear only in the administrative interface for the View.'),
1560
          '#default_value' => $this->display->display_title,
1561
        );
1562
        $form['display_description'] = array(
1563
          '#title' => t('Description'),
1564
          '#type' => 'textfield',
1565
          '#description' => t('This description will appear only in the administrative interface for the View.'),
1566
          '#default_value' => $this->get_option('display_description'),
1567
        );
1568
        break;
1569 5d12d676 Assos Assos
1570 85ad3d82 Assos Assos
      case 'display_comment':
1571
        $form['#title'] .= t("This display's comments");
1572
        $form['display_comment'] = array(
1573
          '#type' => 'textarea',
1574
          '#description' => t('This value will be seen and used only within the Views UI and can be used to document this display. You can use this to provide notes for other or future maintainers of your site about how or why this display is configured.'),
1575
          '#default_value' => $this->get_option('display_comment'),
1576
        );
1577
        break;
1578 5d12d676 Assos Assos
1579 85ad3d82 Assos Assos
      case 'title':
1580
        $form['#title'] .= t('The title of this view');
1581
        $form['title'] = array(
1582
          '#type' => 'textfield',
1583 b08fce64 Assos Assos
          '#description' => t('This title will be displayed with the view, wherever titles are normally displayed; i.e, as the page title, block title, etc. Use &lt;none&gt; to not assign a title; this can allow other modules to control the page title.'),
1584 85ad3d82 Assos Assos
          '#default_value' => $this->get_option('title'),
1585
        );
1586
        break;
1587 5d12d676 Assos Assos
1588 85ad3d82 Assos Assos
      case 'css_class':
1589
        $form['#title'] .= t('CSS class');
1590
        $form['css_class'] = array(
1591
          '#type' => 'textfield',
1592
          '#description' => t('The CSS class names will be added to the view. This enables you to use specific CSS code for each view. You may define multiples classes separated by spaces.'),
1593
          '#default_value' => $this->get_option('css_class'),
1594
        );
1595
        break;
1596 5d12d676 Assos Assos
1597 85ad3d82 Assos Assos
      case 'use_ajax':
1598
        $form['#title'] .= t('Use AJAX when available to load this view');
1599
        $form['description'] = array(
1600
          '#markup' => '<div class="description form-item">' . t('If set, this view will use an AJAX mechanism for paging, table sorting and exposed filters. This means the entire page will not refresh. It is not recommended that you use this if this view is the main content of the page as it will prevent deep linking to specific pages, but it is very useful for side content.') . '</div>',
1601
        );
1602
        $form['use_ajax'] = array(
1603
          '#type' => 'radios',
1604
          '#options' => array(1 => t('Yes'), 0 => t('No')),
1605
          '#default_value' => $this->get_option('use_ajax') ? 1 : 0,
1606
        );
1607
        break;
1608 5d12d676 Assos Assos
1609 85ad3d82 Assos Assos
      case 'hide_attachment_summary':
1610
        $form['#title'] .= t('Hide attachments when displaying a contextual filter summary');
1611
        $form['hide_attachment_summary'] = array(
1612
          '#type' => 'radios',
1613
          '#options' => array(1 => t('Yes'), 0 => t('No')),
1614
          '#default_value' => $this->get_option('hide_attachment_summary') ? 1 : 0,
1615
        );
1616
        break;
1617 5d12d676 Assos Assos
1618 85ad3d82 Assos Assos
      case 'hide_admin_links':
1619
        $form['#title'] .= t('Hide contextual links on this view.');
1620
        $form['hide_admin_links'] = array(
1621
          '#type' => 'radios',
1622
          '#options' => array(1 => t('Yes'), 0 => t('No')),
1623
          '#default_value' => $this->get_option('hide_admin_links') ? 1 : 0,
1624
        );
1625 5d12d676 Assos Assos
        break;
1626
1627 85ad3d82 Assos Assos
      case 'use_more':
1628
        $form['#title'] .= t('Add a more link to the bottom of the display.');
1629
        $form['use_more'] = array(
1630
          '#type' => 'checkbox',
1631
          '#title' => t('Create more link'),
1632
          '#description' => t("This will add a more link to the bottom of this view, which will link to the page view. If you have more than one page view, the link will point to the display specified in 'Link display' section under advanced. You can override the url at the link display setting."),
1633
          '#default_value' => $this->get_option('use_more'),
1634
        );
1635
        $form['use_more_always'] = array(
1636
          '#type' => 'checkbox',
1637
          '#title' => t("Display 'more' link only if there is more content"),
1638
          '#description' => t("Leave this unchecked to display the 'more' link even if there are no more items to display."),
1639
          '#default_value' => !$this->get_option('use_more_always'),
1640 8be7bf84 Assos Assos
          '#dependency' => array(
1641
            'edit-use-more' => array(TRUE),
1642
          ),
1643 85ad3d82 Assos Assos
        );
1644 ef1afbb9 Assos Assos
        $form['open_new_window'] = array(
1645
          '#type' => 'checkbox',
1646
          '#title' => t("Open 'more' link in new window (target='blank')"),
1647
          '#description' => t("Leave this unchecked to open the more link in the same window."),
1648
          '#default_value' => $this->get_option('open_new_window'),
1649
          '#dependency' => array(
1650
            'edit-use-more' => array(TRUE),
1651
          ),
1652
        );
1653 85ad3d82 Assos Assos
        $form['use_more_text'] = array(
1654
          '#type' => 'textfield',
1655
          '#title' => t('More link text'),
1656
          '#description' => t("The text to display for the more link."),
1657
          '#default_value' => $this->get_option('use_more_text'),
1658
          '#dependency' => array(
1659
            'edit-use-more' => array(TRUE),
1660
          ),
1661
        );
1662
        break;
1663 5d12d676 Assos Assos
1664 85ad3d82 Assos Assos
      case 'group_by':
1665
        $form['#title'] .= t('Allow grouping and aggregation (calculation) of fields.');
1666
        $form['group_by'] = array(
1667
          '#type' => 'checkbox',
1668
          '#title' => t('Aggregate'),
1669
          '#description' => t('If enabled, some fields may become unavailable. All fields that are selected for grouping will be collapsed to one record per distinct value. Other fields which are selected for aggregation will have the function run on them. For example, you can group nodes on title and count the number of nids in order to get a list of duplicate titles.'),
1670
          '#default_value' => $this->get_option('group_by'),
1671
        );
1672
        break;
1673 5d12d676 Assos Assos
1674 85ad3d82 Assos Assos
      case 'access':
1675
        $form['#title'] .= t('Access restrictions');
1676
        $form['access'] = array(
1677
          '#prefix' => '<div class="clearfix">',
1678
          '#suffix' => '</div>',
1679
          '#tree' => TRUE,
1680
        );
1681
        $access = $this->get_option('access');
1682 8be7bf84 Assos Assos
        $form['access']['type'] = array(
1683 85ad3d82 Assos Assos
          '#type' => 'radios',
1684
          '#options' => views_fetch_plugin_names('access', NULL, array($this->view->base_table)),
1685
          '#default_value' => $access['type'],
1686
        );
1687
        $access_plugin = views_fetch_plugin_data('access', $access['type']);
1688
        if (!empty($access_plugin['uses options'])) {
1689
          $form['markup'] = array(
1690
            '#prefix' => '<div class="form-item description">',
1691
            '#markup' => t('You may also adjust the !settings for the currently selected access restriction.', array('!settings' => $this->option_link(t('settings'), 'access_options'))),
1692
            '#suffix' => '</div>',
1693
          );
1694
        }
1695
        break;
1696 5d12d676 Assos Assos
1697 85ad3d82 Assos Assos
      case 'access_options':
1698
        $access = $this->get_option('access');
1699
        $plugin = $this->get_plugin('access');
1700
        $form['#title'] .= t('Access options');
1701
        if ($plugin) {
1702 d719f12f Assos Assos
          if (!empty($plugin->definition['help topic'])) {
1703
            $form['#help_topic'] = $plugin->definition['help topic'];
1704
          }
1705
          if (!empty($plugin->definition['module'])) {
1706
            $form['#help_module'] = $plugin->definition['module'];
1707
          }
1708 85ad3d82 Assos Assos
          $form['access_options'] = array(
1709
            '#tree' => TRUE,
1710
          );
1711
          $form['access_options']['type'] = array(
1712
            '#type' => 'value',
1713
            '#value' => $access['type'],
1714
          );
1715
          $plugin->options_form($form['access_options'], $form_state);
1716
        }
1717
        break;
1718 5d12d676 Assos Assos
1719 85ad3d82 Assos Assos
      case 'cache':
1720
        $form['#title'] .= t('Caching');
1721
        $form['cache'] = array(
1722
          '#prefix' => '<div class="clearfix">',
1723
          '#suffix' => '</div>',
1724
          '#tree' => TRUE,
1725
        );
1726
        $cache = $this->get_option('cache');
1727 8be7bf84 Assos Assos
        $form['cache']['type'] = array(
1728 85ad3d82 Assos Assos
          '#type' => 'radios',
1729
          '#options' => views_fetch_plugin_names('cache', NULL, array($this->view->base_table)),
1730
          '#default_value' => $cache['type'],
1731
        );
1732
        $cache_plugin = views_fetch_plugin_data('cache', $cache['type']);
1733
        if (!empty($cache_plugin['uses options'])) {
1734
          $form['markup'] = array(
1735
            '#prefix' => '<div class="form-item description">',
1736
            '#suffix' => '</div>',
1737
            '#markup' => t('You may also adjust the !settings for the currently selected cache mechanism.', array('!settings' => $this->option_link(t('settings'), 'cache_options'))),
1738
          );
1739
        }
1740
        break;
1741 5d12d676 Assos Assos
1742 85ad3d82 Assos Assos
      case 'cache_options':
1743
        $cache = $this->get_option('cache');
1744
        $plugin = $this->get_plugin('cache');
1745
        $form['#title'] .= t('Caching options');
1746
        if ($plugin) {
1747 d719f12f Assos Assos
          if (!empty($plugin->definition['help topic'])) {
1748
            $form['#help_topic'] = $plugin->definition['help topic'];
1749
          }
1750
          if (!empty($plugin->definition['module'])) {
1751
            $form['#help_module'] = $plugin->definition['module'];
1752
          }
1753 85ad3d82 Assos Assos
          $form['cache_options'] = array(
1754
            '#tree' => TRUE,
1755
          );
1756
          $form['cache_options']['type'] = array(
1757
            '#type' => 'value',
1758
            '#value' => $cache['type'],
1759
          );
1760
          $plugin->options_form($form['cache_options'], $form_state);
1761
        }
1762
        break;
1763 5d12d676 Assos Assos
1764 85ad3d82 Assos Assos
      case 'query':
1765
        $query_options = $this->get_option('query');
1766
        $plugin_name = $query_options['type'];
1767
1768
        $form['#title'] .= t('Query options');
1769
        $this->view->init_query();
1770
        if ($this->view->query) {
1771 d719f12f Assos Assos
          if (!empty($this->view->query->definition['help topic'])) {
1772 85ad3d82 Assos Assos
            $form['#help_topic'] = $this->view->query->definition['help topic'];
1773
          }
1774 d719f12f Assos Assos
          if (!empty($this->view->query->definition['module'])) {
1775 85ad3d82 Assos Assos
            $form['#help_module'] = $this->view->query->definition['module'];
1776
          }
1777
          $form['query'] = array(
1778
            '#tree' => TRUE,
1779
            'type' => array(
1780
              '#type' => 'value',
1781
              '#value' => $plugin_name,
1782
            ),
1783
            'options' => array(
1784
              '#tree' => TRUE,
1785
            ),
1786
          );
1787
          $this->view->query->options_form($form['query']['options'], $form_state);
1788
        }
1789
        break;
1790 5d12d676 Assos Assos
1791 85ad3d82 Assos Assos
      case 'field_language':
1792
        $form['#title'] .= t('Field Language');
1793
1794
        $entities = entity_get_info();
1795
        $entity_tables = array();
1796
        $has_translation_handlers = FALSE;
1797
        foreach ($entities as $type => $entity_info) {
1798
          $entity_tables[] = $entity_info['base table'];
1799
1800
          if (!empty($entity_info['translation'])) {
1801
            $has_translation_handlers = TRUE;
1802
          }
1803
        }
1804
1805
        // Doesn't make sense to show a field setting here if we aren't querying
1806
        // an entity base table. Also, we make sure that there's at least one
1807
        // entity type with a translation handler attached.
1808
        if (in_array($this->view->base_table, $entity_tables) && $has_translation_handlers) {
1809
          $languages = array(
1810
            '***CURRENT_LANGUAGE***' => t("Current user's language"),
1811
            '***DEFAULT_LANGUAGE***' => t("Default site language"),
1812
            LANGUAGE_NONE => t('Language neutral'),
1813
          );
1814
          $languages = array_merge($languages, views_language_list());
1815
1816
          $form['field_language'] = array(
1817
            '#type' => 'select',
1818
            '#title' => t('Field Language'),
1819
            '#description' => t('All fields which support translations will be displayed in the selected language.'),
1820
            '#options' => $languages,
1821
            '#default_value' => $this->get_option('field_language'),
1822
          );
1823
          $form['field_language_add_to_query'] = array(
1824
            '#type' => 'checkbox',
1825
            '#title' => t('When needed, add the field language condition to the query'),
1826
            '#default_value' => $this->get_option('field_language_add_to_query'),
1827
          );
1828
        }
1829
        else {
1830
          $form['field_language']['#markup'] = t("You don't have translatable entity types.");
1831
        }
1832
        break;
1833 5d12d676 Assos Assos
1834 85ad3d82 Assos Assos
      case 'style_plugin':
1835
        $form['#title'] .= t('How should this view be styled');
1836
        $form['#help_topic'] = 'style';
1837 8be7bf84 Assos Assos
        $form['style_plugin'] = array(
1838 85ad3d82 Assos Assos
          '#type' => 'radios',
1839
          '#options' => views_fetch_plugin_names('style', $this->get_style_type(), array($this->view->base_table)),
1840
          '#default_value' => $this->get_option('style_plugin'),
1841
          '#description' => t('If the style you choose has settings, be sure to click the settings button that will appear next to it in the View summary.'),
1842
        );
1843
1844
        $style_plugin = views_fetch_plugin_data('style', $this->get_option('style_plugin'));
1845
        if (!empty($style_plugin['uses options'])) {
1846
          $form['markup'] = array(
1847
            '#markup' => '<div class="form-item description">' . t('You may also adjust the !settings for the currently selected style.', array('!settings' => $this->option_link(t('settings'), 'style_options'))) . '</div>',
1848
          );
1849
        }
1850
        break;
1851 5d12d676 Assos Assos
1852 85ad3d82 Assos Assos
      case 'style_options':
1853
        $form['#title'] .= t('Style options');
1854
        $style = TRUE;
1855
        $type = 'style_plugin';
1856
        $name = $this->get_option('style_plugin');
1857
1858
      case 'row_options':
1859
        if (!isset($name)) {
1860
          $name = $this->get_option('row_plugin');
1861
        }
1862 5d12d676 Assos Assos
        // If row, $style will be empty.
1863 85ad3d82 Assos Assos
        if (empty($style)) {
1864
          $form['#title'] .= t('Row style options');
1865
          $type = 'row_plugin';
1866
        }
1867
        $plugin = $this->get_plugin(empty($style) ? 'row' : 'style');
1868
        if ($plugin) {
1869 d719f12f Assos Assos
          if (!empty($plugin->definition['help topic'])) {
1870 85ad3d82 Assos Assos
            $form['#help_topic'] = $plugin->definition['help topic'];
1871 d719f12f Assos Assos
          }
1872
          if (!empty($plugin->definition['module'])) {
1873 85ad3d82 Assos Assos
            $form['#help_module'] = $plugin->definition['module'];
1874
          }
1875
          $form[$form_state['section']] = array(
1876
            '#tree' => TRUE,
1877
          );
1878
          $plugin->options_form($form[$form_state['section']], $form_state);
1879
        }
1880
        break;
1881 5d12d676 Assos Assos
1882 85ad3d82 Assos Assos
      case 'row_plugin':
1883
        $form['#title'] .= t('How should each row in this view be styled');
1884
        $form['#help_topic'] = 'style-row';
1885 8be7bf84 Assos Assos
        $form['row_plugin'] = array(
1886 85ad3d82 Assos Assos
          '#type' => 'radios',
1887
          '#options' => views_fetch_plugin_names('row', $this->get_style_type(), array($this->view->base_table)),
1888
          '#default_value' => $this->get_option('row_plugin'),
1889
        );
1890
1891
        $row_plugin = views_fetch_plugin_data('row', $this->get_option('row_plugin'));
1892
        if (!empty($row_plugin['uses options'])) {
1893
          $form['markup'] = array(
1894
            '#markup' => '<div class="form-item description">' . t('You may also adjust the !settings for the currently selected row style.', array('!settings' => $this->option_link(t('settings'), 'row_options'))) . '</div>',
1895
          );
1896
        }
1897
        break;
1898 5d12d676 Assos Assos
1899 85ad3d82 Assos Assos
      case 'link_display':
1900
        $form['#title'] .= t('Which display to use for path');
1901
        foreach ($this->view->display as $display_id => $display) {
1902
          if ($display->handler->has_path()) {
1903
            $options[$display_id] = $display->display_title;
1904
          }
1905
        }
1906
        $options['custom_url'] = t('Custom URL');
1907
        if (count($options)) {
1908
          $form['link_display'] = array(
1909
            '#type' => 'radios',
1910
            '#options' => $options,
1911
            '#description' => t("Which display to use to get this display's path for things like summary links, rss feed links, more links, etc."),
1912
            '#default_value' => $this->get_option('link_display'),
1913
          );
1914
        }
1915
1916
        $options = array();
1917 5d12d676 Assos Assos
        // This lets us prepare the key as we want it printed.
1918
        $count = 0;
1919 85ad3d82 Assos Assos
        foreach ($this->view->display_handler->get_handlers('argument') as $arg => $handler) {
1920
          $options[t('Arguments')]['%' . ++$count] = t('@argument title', array('@argument' => $handler->ui_name()));
1921
          $options[t('Arguments')]['!' . $count] = t('@argument input', array('@argument' => $handler->ui_name()));
1922
        }
1923
1924 5d12d676 Assos Assos
        // Default text. We have some options, so make a list.
1925 85ad3d82 Assos Assos
        $output = '';
1926
        if (!empty($options)) {
1927
          $output = t('<p>The following tokens are available for this link.</p>');
1928
          foreach (array_keys($options) as $type) {
1929
            if (!empty($options[$type])) {
1930
              $items = array();
1931
              foreach ($options[$type] as $key => $value) {
1932
                $items[] = $key . ' == ' . $value;
1933
              }
1934
              $output .= theme('item_list',
1935
                array(
1936
                  'items' => $items,
1937 8be7bf84 Assos Assos
                  'type' => $type,
1938 85ad3d82 Assos Assos
                ));
1939
            }
1940
          }
1941
        }
1942
1943
        $form['link_url'] = array(
1944
          '#type' => 'textfield',
1945
          '#title' => t('Custom URL'),
1946
          '#default_value' => $this->get_option('link_url'),
1947
          '#description' => t('A Drupal path or external URL the more link will point to. Note that this will override the link display setting above.') . $output,
1948
          '#dependency' => array('radio:link_display' => array('custom_url')),
1949
        );
1950
        break;
1951 5d12d676 Assos Assos
1952 85ad3d82 Assos Assos
      case 'analyze-theme':
1953
        $form['#title'] .= t('Theming information');
1954
        $form['#help_topic'] = 'analyze-theme';
1955
1956
        if (isset($_POST['theme'])) {
1957
          $this->theme = $_POST['theme'];
1958
        }
1959
        elseif (empty($this->theme)) {
1960
          $this->theme = variable_get('theme_default', 'bartik');
1961
        }
1962
1963
        if (isset($GLOBALS['theme']) && $GLOBALS['theme'] == $this->theme) {
1964
          $this->theme_registry = theme_get_registry();
1965
          $theme_engine = $GLOBALS['theme_engine'];
1966
        }
1967
        else {
1968
          $themes = list_themes();
1969
          $theme = $themes[$this->theme];
1970
1971
          // Find all our ancestor themes and put them in an array.
1972
          $base_theme = array();
1973
          $ancestor = $this->theme;
1974
          while ($ancestor && isset($themes[$ancestor]->base_theme)) {
1975
            $ancestor = $themes[$ancestor]->base_theme;
1976
            $base_theme[] = $themes[$ancestor];
1977
          }
1978
1979
          // The base themes should be initialized in the right order.
1980
          $base_theme = array_reverse($base_theme);
1981
1982 5d12d676 Assos Assos
          // This code is copied directly from _drupal_theme_initialize().
1983 85ad3d82 Assos Assos
          $theme_engine = NULL;
1984
1985
          // Initialize the theme.
1986
          if (isset($theme->engine)) {
1987
            // Include the engine.
1988
            include_once DRUPAL_ROOT . '/' . $theme->owner;
1989
1990
            $theme_engine = $theme->engine;
1991
            if (function_exists($theme_engine . '_init')) {
1992
              foreach ($base_theme as $base) {
1993
                call_user_func($theme_engine . '_init', $base);
1994
              }
1995
              call_user_func($theme_engine . '_init', $theme);
1996
            }
1997
          }
1998
          else {
1999 8be7bf84 Assos Assos
            // Include non-engine theme files.
2000 85ad3d82 Assos Assos
            foreach ($base_theme as $base) {
2001
              // Include the theme file or the engine.
2002
              if (!empty($base->owner)) {
2003
                include_once DRUPAL_ROOT . '/' . $base->owner;
2004
              }
2005
            }
2006 8be7bf84 Assos Assos
            // And our theme gets one too.
2007 85ad3d82 Assos Assos
            if (!empty($theme->owner)) {
2008
              include_once DRUPAL_ROOT . '/' . $theme->owner;
2009
            }
2010
          }
2011
          $this->theme_registry = _theme_load_registry($theme, $base_theme, $theme_engine);
2012
        }
2013
2014 5d12d676 Assos Assos
        // If there's a theme engine involved, we also need to know its
2015
        // extension so we can give the proper filename.
2016 85ad3d82 Assos Assos
        $this->theme_extension = '.tpl.php';
2017
        if (isset($theme_engine)) {
2018
          $extension_function = $theme_engine . '_extension';
2019
          if (function_exists($extension_function)) {
2020
            $this->theme_extension = $extension_function();
2021
          }
2022
        }
2023
2024
        $funcs = array();
2025 8be7bf84 Assos Assos
        // Get theme functions for the display. Note that some displays may not
2026
        // have themes. The 'feed' display, for example, completely delegates to
2027
        // the style.
2028 85ad3d82 Assos Assos
        if (!empty($this->definition['theme'])) {
2029 8be7bf84 Assos Assos
          $funcs[] = $this->option_link(t('Display output'), 'analyze-theme-display') . ': ' . $this->format_themes($this->theme_functions());
2030 85ad3d82 Assos Assos
          $themes = $this->additional_theme_functions();
2031
          if ($themes) {
2032
            foreach ($themes as $theme) {
2033 8be7bf84 Assos Assos
              $funcs[] = $this->option_link(t('Alternative display output'), 'analyze-theme-display') . ': ' . $this->format_themes($theme);
2034 85ad3d82 Assos Assos
            }
2035
          }
2036
        }
2037
2038
        $plugin = $this->get_plugin();
2039
        if ($plugin) {
2040
          $funcs[] = $this->option_link(t('Style output'), 'analyze-theme-style') . ': ' . $this->format_themes($plugin->theme_functions(), $plugin->additional_theme_functions());
2041
          $themes = $plugin->additional_theme_functions();
2042
          if ($themes) {
2043
            foreach ($themes as $theme) {
2044 8be7bf84 Assos Assos
              $funcs[] = $this->option_link(t('Alternative style'), 'analyze-theme-style') . ': ' . $this->format_themes($theme);
2045 85ad3d82 Assos Assos
            }
2046
          }
2047
2048
          if ($plugin->uses_row_plugin()) {
2049
            $row_plugin = $this->get_plugin('row');
2050
            if ($row_plugin) {
2051
              $funcs[] = $this->option_link(t('Row style output'), 'analyze-theme-row') . ': ' . $this->format_themes($row_plugin->theme_functions());
2052
              $themes = $row_plugin->additional_theme_functions();
2053
              if ($themes) {
2054
                foreach ($themes as $theme) {
2055 8be7bf84 Assos Assos
                  $funcs[] = $this->option_link(t('Alternative row style'), 'analyze-theme-row') . ': ' . $this->format_themes($theme);
2056 85ad3d82 Assos Assos
                }
2057
              }
2058
            }
2059
          }
2060
2061
          if ($plugin->uses_fields()) {
2062
            foreach ($this->get_handlers('field') as $id => $handler) {
2063
              $funcs[] = $this->option_link(t('Field @field (ID: @id)', array('@field' => $handler->ui_name(), '@id' => $id)), 'analyze-theme-field') . ': ' . $this->format_themes($handler->theme_functions());
2064
            }
2065
          }
2066
        }
2067
2068
        $form['important'] = array(
2069
          '#markup' => '<div class="form-item description"><p>' . t('This section lists all possible templates for the display plugin and for the style plugins, ordered roughly from the least specific to the most specific. The active template for each plugin -- which is the most specific template found on the system -- is highlighted in bold.') . '</p></div>',
2070
        );
2071
2072
        if (isset($this->view->display[$this->view->current_display]->new_id)) {
2073
          $form['important']['new_id'] = array(
2074
            '#prefix' => '<div class="description">',
2075
            '#suffix' => '</div>',
2076
            '#value' => t("<strong>Important!</strong> You have changed the display's machine name. Anything that attached to this display specifically, such as theming, may stop working until it is updated. To see theme suggestions for it, you need to save the view."),
2077
          );
2078
        }
2079
2080
        foreach (list_themes() as $key => $theme) {
2081
          if (!empty($theme->info['hidden'])) {
2082
            continue;
2083
          }
2084
          $options[$key] = $theme->info['name'];
2085
        }
2086
2087
        $form['box'] = array(
2088
          '#prefix' => '<div class="container-inline">',
2089
          '#suffix' => '</div>',
2090
        );
2091
        $form['box']['theme'] = array(
2092
          '#type' => 'select',
2093
          '#options' => $options,
2094
          '#default_value' => $this->theme,
2095
        );
2096
2097
        $form['box']['change'] = array(
2098
          '#type' => 'submit',
2099
          '#value' => t('Change theme'),
2100
          '#submit' => array('views_ui_edit_display_form_change_theme'),
2101
        );
2102
2103
        $form['analysis'] = array(
2104
          '#markup' => '<div class="form-item">' . theme('item_list', array('items' => $funcs)) . '</div>',
2105
        );
2106
2107
        $form['rescan_button'] = array(
2108
          '#prefix' => '<div class="form-item">',
2109
          '#suffix' => '</div>',
2110
        );
2111
        $form['rescan_button']['button'] = array(
2112
          '#type' => 'submit',
2113
          '#value' => t('Rescan template files'),
2114
          '#submit' => array('views_ui_config_item_form_rescan'),
2115
        );
2116
        $form['rescan_button']['markup'] = array(
2117
          '#markup' => '<div class="description">' . t("<strong>Important!</strong> When adding, removing, or renaming template files, it is necessary to make Drupal aware of the changes by making it rescan the files on your system. By clicking this button you clear Drupal's theme registry and thereby trigger this rescanning process. The highlighted templates above will then reflect the new state of your system.") . '</div>',
2118
        );
2119
2120
        $form_state['ok_button'] = TRUE;
2121
        break;
2122 5d12d676 Assos Assos
2123 85ad3d82 Assos Assos
      case 'analyze-theme-display':
2124
        $form['#title'] .= t('Theming information (display)');
2125
        $output = '<p>' . t('Back to !info.', array('!info' => $this->option_link(t('theming information'), 'analyze-theme'))) . '</p>';
2126
2127
        if (empty($this->definition['theme'])) {
2128
          $output .= t('This display has no theming information');
2129
        }
2130
        else {
2131
          $output .= '<p>' . t('This is the default theme template used for this display.') . '</p>';
2132
          $output .= '<pre>' . check_plain(file_get_contents('./' . $this->definition['theme path'] . '/' . strtr($this->definition['theme'], '_', '-') . '.tpl.php')) . '</pre>';
2133
        }
2134
2135
        if (!empty($this->definition['additional themes'])) {
2136
          foreach ($this->definition['additional themes'] as $theme => $type) {
2137
            $output .= '<p>' . t('This is an alternative template for this display.') . '</p>';
2138
            $output .= '<pre>' . check_plain(file_get_contents('./' . $this->definition['theme path'] . '/' . strtr($theme, '_', '-') . '.tpl.php')) . '</pre>';
2139
          }
2140
        }
2141
2142
        $form['analysis'] = array(
2143
          '#markup' => '<div class="form-item">' . $output . '</div>',
2144
        );
2145
2146
        $form_state['ok_button'] = TRUE;
2147
        break;
2148 5d12d676 Assos Assos
2149 85ad3d82 Assos Assos
      case 'analyze-theme-style':
2150
        $form['#title'] .= t('Theming information (style)');
2151
        $output = '<p>' . t('Back to !info.', array('!info' => $this->option_link(t('theming information'), 'analyze-theme'))) . '</p>';
2152
2153
        $plugin = $this->get_plugin();
2154
2155
        if (empty($plugin->definition['theme'])) {
2156
          $output .= t('This display has no style theming information');
2157
        }
2158
        else {
2159
          $output .= '<p>' . t('This is the default theme template used for this style.') . '</p>';
2160
          $output .= '<pre>' . check_plain(file_get_contents('./' . $plugin->definition['theme path'] . '/' . strtr($plugin->definition['theme'], '_', '-') . '.tpl.php')) . '</pre>';
2161
        }
2162
2163
        if (!empty($plugin->definition['additional themes'])) {
2164
          foreach ($plugin->definition['additional themes'] as $theme => $type) {
2165
            $output .= '<p>' . t('This is an alternative template for this style.') . '</p>';
2166
            $output .= '<pre>' . check_plain(file_get_contents('./' . $plugin->definition['theme path'] . '/' . strtr($theme, '_', '-') . '.tpl.php')) . '</pre>';
2167
          }
2168
        }
2169
2170
        $form['analysis'] = array(
2171
          '#markup' => '<div class="form-item">' . $output . '</div>',
2172
        );
2173
2174
        $form_state['ok_button'] = TRUE;
2175
        break;
2176 5d12d676 Assos Assos
2177 85ad3d82 Assos Assos
      case 'analyze-theme-row':
2178
        $form['#title'] .= t('Theming information (row style)');
2179
        $output = '<p>' . t('Back to !info.', array('!info' => $this->option_link(t('theming information'), 'analyze-theme'))) . '</p>';
2180
2181
        $plugin = $this->get_plugin('row');
2182
2183
        if (empty($plugin->definition['theme'])) {
2184
          $output .= t('This display has no row style theming information');
2185
        }
2186
        else {
2187
          $output .= '<p>' . t('This is the default theme template used for this row style.') . '</p>';
2188
          $output .= '<pre>' . check_plain(file_get_contents('./' . $plugin->definition['theme path'] . '/' . strtr($plugin->definition['theme'], '_', '-') . '.tpl.php')) . '</pre>';
2189
        }
2190
2191
        if (!empty($plugin->definition['additional themes'])) {
2192
          foreach ($plugin->definition['additional themes'] as $theme => $type) {
2193
            $output .= '<p>' . t('This is an alternative template for this row style.') . '</p>';
2194
            $output .= '<pre>' . check_plain(file_get_contents('./' . $plugin->definition['theme path'] . '/' . strtr($theme, '_', '-') . '.tpl.php')) . '</pre>';
2195
          }
2196
        }
2197
2198
        $form['analysis'] = array(
2199
          '#markup' => '<div class="form-item">' . $output . '</div>',
2200
        );
2201
2202
        $form_state['ok_button'] = TRUE;
2203
        break;
2204 5d12d676 Assos Assos
2205 85ad3d82 Assos Assos
      case 'analyze-theme-field':
2206
        $form['#title'] .= t('Theming information (row style)');
2207
        $output = '<p>' . t('Back to !info.', array('!info' => $this->option_link(t('theming information'), 'analyze-theme'))) . '</p>';
2208
2209
        $output .= '<p>' . t('This is the default theme template used for this row style.') . '</p>';
2210
2211 8be7bf84 Assos Assos
        // Field templates aren't registered the normal way... and they're
2212
        // always this one, anyhow.
2213 85ad3d82 Assos Assos
        $output .= '<pre>' . check_plain(file_get_contents(drupal_get_path('module', 'views') . '/theme/views-view-field.tpl.php')) . '</pre>';
2214
2215
        $form['analysis'] = array(
2216
          '#markup' => '<div class="form-item">' . $output . '</div>',
2217
        );
2218
        $form_state['ok_button'] = TRUE;
2219
        break;
2220
2221
      case 'exposed_block':
2222
        $form['#title'] .= t('Put the exposed form in a block');
2223
        $form['description'] = array(
2224
          '#markup' => '<div class="description form-item">' . t('If set, any exposed widgets will not appear with this view. Instead, a block will be made available to the Drupal block administration system, and the exposed form will appear there. Note that this block must be enabled manually, Views will not enable it for you.') . '</div>',
2225
        );
2226
        $form['exposed_block'] = array(
2227
          '#type' => 'radios',
2228
          '#options' => array(1 => t('Yes'), 0 => t('No')),
2229
          '#default_value' => $this->get_option('exposed_block') ? 1 : 0,
2230
        );
2231
        break;
2232 5d12d676 Assos Assos
2233 85ad3d82 Assos Assos
      case 'exposed_form':
2234
        $form['#title'] .= t('Exposed Form');
2235
        $form['exposed_form'] = array(
2236
          '#prefix' => '<div class="clearfix">',
2237
          '#suffix' => '</div>',
2238
          '#tree' => TRUE,
2239
        );
2240
2241
        $exposed_form = $this->get_option('exposed_form');
2242 8be7bf84 Assos Assos
        $form['exposed_form']['type'] = array(
2243 85ad3d82 Assos Assos
          '#type' => 'radios',
2244
          '#options' => views_fetch_plugin_names('exposed_form', NULL, array($this->view->base_table)),
2245
          '#default_value' => $exposed_form['type'],
2246
        );
2247
2248
        $exposed_form_plugin = views_fetch_plugin_data('exposed_form', $exposed_form['type']);
2249
        if (!empty($exposed_form_plugin['uses options'])) {
2250
          $form['markup'] = array(
2251
            '#prefix' => '<div class="form-item description">',
2252
            '#suffix' => '</div>',
2253
            '#markup' => t('You may also adjust the !settings for the currently selected style.', array('!settings' => $this->option_link(t('settings'), 'exposed_form_options'))),
2254
          );
2255
        }
2256
        break;
2257 5d12d676 Assos Assos
2258 85ad3d82 Assos Assos
      case 'exposed_form_options':
2259
        $plugin = $this->get_plugin('exposed_form');
2260
        $form['#title'] .= t('Exposed form options');
2261
        if ($plugin) {
2262 d719f12f Assos Assos
          if (!empty($plugin->definition['help topic'])) {
2263
            $form['#help_topic'] = $plugin->definition['help topic'];
2264
          }
2265
          if (!empty($plugin->definition['module'])) {
2266
            $form['#help_module'] = $plugin->definition['module'];
2267
          }
2268 85ad3d82 Assos Assos
2269
          $form['exposed_form_options'] = array(
2270
            '#tree' => TRUE,
2271
          );
2272
          $plugin->options_form($form['exposed_form_options'], $form_state);
2273
        }
2274
        break;
2275 5d12d676 Assos Assos
2276 85ad3d82 Assos Assos
      case 'pager':
2277
        $form['#title'] .= t('Select which pager, if any, to use for this view');
2278
        $form['pager'] = array(
2279
          '#prefix' => '<div class="clearfix">',
2280
          '#suffix' => '</div>',
2281
          '#tree' => TRUE,
2282
        );
2283
2284
        $pager = $this->get_option('pager');
2285 8be7bf84 Assos Assos
        $form['pager']['type'] = array(
2286 85ad3d82 Assos Assos
          '#type' => 'radios',
2287
          '#options' => views_fetch_plugin_names('pager', empty($this->definition['use pager']) ? 'basic' : NULL, array($this->view->base_table)),
2288
          '#default_value' => $pager['type'],
2289
        );
2290
2291 6f57d8c7 Assos Assos
        $pager_plugin = views_fetch_plugin_data('pager', $pager['type']);
2292 85ad3d82 Assos Assos
        if (!empty($pager_plugin['uses options'])) {
2293
          $form['markup'] = array(
2294
            '#prefix' => '<div class="form-item description">',
2295
            '#suffix' => '</div>',
2296
            '#markup' => t('You may also adjust the !settings for the currently selected pager.', array('!settings' => $this->option_link(t('settings'), 'pager_options'))),
2297
          );
2298
        }
2299
        break;
2300 5d12d676 Assos Assos
2301 85ad3d82 Assos Assos
      case 'pager_options':
2302
        $plugin = $this->get_plugin('pager');
2303
        $form['#title'] .= t('Pager options');
2304
        if ($plugin) {
2305 d719f12f Assos Assos
          if (!empty($plugin->definition['help topic'])) {
2306
            $form['#help_topic'] = $plugin->definition['help topic'];
2307
          }
2308
          if (!empty($plugin->definition['module'])) {
2309
            $form['#help_module'] = $plugin->definition['module'];
2310
          }
2311 85ad3d82 Assos Assos
2312
          $form['pager_options'] = array(
2313
            '#tree' => TRUE,
2314
          );
2315
          $plugin->options_form($form['pager_options'], $form_state);
2316
        }
2317
        break;
2318
    }
2319
2320
    foreach ($this->extender as $extender) {
2321
      $extender->options_form($form, $form_state);
2322
    }
2323
  }
2324
2325
  /**
2326
   * Format a list of theme templates for output by the theme info helper.
2327
   */
2328 5d12d676 Assos Assos
  public function format_themes($themes) {
2329 85ad3d82 Assos Assos
    $registry = $this->theme_registry;
2330
    $extension = $this->theme_extension;
2331
2332
    $output = '';
2333
    $picked = FALSE;
2334
    foreach ($themes as $theme) {
2335
      $template = strtr($theme, '_', '-') . $extension;
2336
      if (!$picked && !empty($registry[$theme])) {
2337
        $template_path = isset($registry[$theme]['path']) ? $registry[$theme]['path'] . '/' : './';
2338
        if (file_exists($template_path . $template)) {
2339
          $hint = t('File found in folder @template-path', array('@template-path' => $template_path));
2340 8be7bf84 Assos Assos
          $template = '<strong title="' . $hint . '">' . $template . '</strong>';
2341 85ad3d82 Assos Assos
        }
2342
        else {
2343
          $template = '<strong class="error">' . $template . ' ' . t('(File not found, in folder @template-path)', array('@template-path' => $template_path)) . '</strong>';
2344
        }
2345
        $picked = TRUE;
2346
      }
2347
      $fixed[] = $template;
2348
    }
2349
2350 8be7bf84 Assos Assos
    return theme('item_list', array('items' => array_reverse($fixed)));
2351 85ad3d82 Assos Assos
  }
2352
2353
  /**
2354
   * Validate the options form.
2355
   */
2356 5d12d676 Assos Assos
  public function options_validate(&$form, &$form_state) {
2357 85ad3d82 Assos Assos
    switch ($form_state['section']) {
2358
      case 'display_title':
2359
        if (empty($form_state['values']['display_title'])) {
2360
          form_error($form['display_title'], t('Display title may not be empty.'));
2361
        }
2362
        break;
2363 5d12d676 Assos Assos
2364 85ad3d82 Assos Assos
      case 'css_class':
2365
        $css_class = $form_state['values']['css_class'];
2366
        if (preg_match('/[^a-zA-Z0-9-_ ]/', $css_class)) {
2367
          form_error($form['css_class'], t('CSS classes must be alphanumeric or dashes only.'));
2368
        }
2369 5d12d676 Assos Assos
        break;
2370
2371 85ad3d82 Assos Assos
      case 'display_id':
2372
        if ($form_state['values']['display_id']) {
2373
          if (preg_match('/[^a-z0-9_]/', $form_state['values']['display_id'])) {
2374
            form_error($form['display_id'], t('Display name must be letters, numbers, or underscores only.'));
2375
          }
2376
2377
          foreach ($this->view->display as $id => $display) {
2378
            if ($id != $this->view->current_display && ($form_state['values']['display_id'] == $id || (isset($display->new_id) && $form_state['values']['display_id'] == $display->new_id))) {
2379
              form_error($form['display_id'], t('Display id should be unique.'));
2380
            }
2381
          }
2382
        }
2383
        break;
2384 5d12d676 Assos Assos
2385 85ad3d82 Assos Assos
      case 'style_options':
2386
        $style = TRUE;
2387
      case 'row_options':
2388 8be7bf84 Assos Assos
        // If row, $style will be empty.
2389 85ad3d82 Assos Assos
        $plugin = $this->get_plugin(empty($style) ? 'row' : 'style');
2390
        if ($plugin) {
2391
          $plugin->options_validate($form[$form_state['section']], $form_state);
2392
        }
2393
        break;
2394 5d12d676 Assos Assos
2395 85ad3d82 Assos Assos
      case 'access_options':
2396
        $plugin = $this->get_plugin('access');
2397
        if ($plugin) {
2398
          $plugin->options_validate($form['access_options'], $form_state);
2399
        }
2400
        break;
2401 5d12d676 Assos Assos
2402 85ad3d82 Assos Assos
      case 'query':
2403
        if ($this->view->query) {
2404
          $this->view->query->options_validate($form['query'], $form_state);
2405
        }
2406
        break;
2407 5d12d676 Assos Assos
2408 85ad3d82 Assos Assos
      case 'cache_options':
2409
        $plugin = $this->get_plugin('cache');
2410
        if ($plugin) {
2411
          $plugin->options_validate($form['cache_options'], $form_state);
2412
        }
2413
        break;
2414 5d12d676 Assos Assos
2415 85ad3d82 Assos Assos
      case 'exposed_form_options':
2416
        $plugin = $this->get_plugin('exposed_form');
2417
        if ($plugin) {
2418
          $plugin->options_validate($form['exposed_form_options'], $form_state);
2419
        }
2420
        break;
2421 5d12d676 Assos Assos
2422 85ad3d82 Assos Assos
      case 'pager_options':
2423
        $plugin = $this->get_plugin('pager');
2424
        if ($plugin) {
2425
          $plugin->options_validate($form['pager_options'], $form_state);
2426
        }
2427
        break;
2428
    }
2429
2430
    foreach ($this->extender as $extender) {
2431
      $extender->options_validate($form, $form_state);
2432
    }
2433
  }
2434
2435
  /**
2436
   * Perform any necessary changes to the form values prior to storage.
2437 8be7bf84 Assos Assos
   *
2438 85ad3d82 Assos Assos
   * There is no need for this function to actually store the data.
2439
   */
2440 5d12d676 Assos Assos
  public function options_submit(&$form, &$form_state) {
2441 85ad3d82 Assos Assos
    // Not sure I like this being here, but it seems (?) like a logical place.
2442
    $cache_plugin = $this->get_plugin('cache');
2443
    if ($cache_plugin) {
2444
      $cache_plugin->cache_flush();
2445
    }
2446
2447
    $section = $form_state['section'];
2448
    switch ($section) {
2449
      case 'display_id':
2450
        if (isset($form_state['values']['display_id'])) {
2451
          $this->display->new_id = $form_state['values']['display_id'];
2452
        }
2453
        break;
2454 5d12d676 Assos Assos
2455 85ad3d82 Assos Assos
      case 'display_title':
2456
        $this->display->display_title = $form_state['values']['display_title'];
2457
        $this->set_option('display_description', $form_state['values']['display_description']);
2458
        break;
2459 5d12d676 Assos Assos
2460 85ad3d82 Assos Assos
      case 'access':
2461
        $access = $this->get_option('access');
2462
        if ($access['type'] != $form_state['values']['access']['type']) {
2463
          $plugin = views_get_plugin('access', $form_state['values']['access']['type']);
2464
          if ($plugin) {
2465
            $access = array('type' => $form_state['values']['access']['type']);
2466
            $this->set_option('access', $access);
2467
            if (!empty($plugin->definition['uses options'])) {
2468
              views_ui_add_form_to_stack('display', $this->view, $this->display->id, array('access_options'));
2469
            }
2470
          }
2471
        }
2472
        break;
2473 5d12d676 Assos Assos
2474 85ad3d82 Assos Assos
      case 'access_options':
2475
        $plugin = views_get_plugin('access', $form_state['values'][$section]['type']);
2476
        if ($plugin) {
2477
          $plugin->options_submit($form['access_options'], $form_state);
2478
          $this->set_option('access', $form_state['values'][$section]);
2479
        }
2480
        break;
2481 5d12d676 Assos Assos
2482 85ad3d82 Assos Assos
      case 'cache':
2483
        $cache = $this->get_option('cache');
2484
        if ($cache['type'] != $form_state['values']['cache']['type']) {
2485
          $plugin = views_get_plugin('cache', $form_state['values']['cache']['type']);
2486
          if ($plugin) {
2487
            $cache = array('type' => $form_state['values']['cache']['type']);
2488
            $this->set_option('cache', $cache);
2489
            if (!empty($plugin->definition['uses options'])) {
2490
              views_ui_add_form_to_stack('display', $this->view, $this->display->id, array('cache_options'));
2491
            }
2492
          }
2493
        }
2494
        break;
2495 5d12d676 Assos Assos
2496 85ad3d82 Assos Assos
      case 'cache_options':
2497
        $plugin = views_get_plugin('cache', $form_state['values'][$section]['type']);
2498
        if ($plugin) {
2499
          $plugin->options_submit($form['cache_options'], $form_state);
2500
          $this->set_option('cache', $form_state['values'][$section]);
2501
        }
2502
        break;
2503 5d12d676 Assos Assos
2504 85ad3d82 Assos Assos
      case 'query':
2505
        $plugin = $this->get_plugin('query');
2506
        if ($plugin) {
2507
          $plugin->options_submit($form['query']['options'], $form_state);
2508
          $this->set_option('query', $form_state['values'][$section]);
2509
        }
2510
        break;
2511
2512
      case 'link_display':
2513
        $this->set_option('link_url', $form_state['values']['link_url']);
2514
      case 'title':
2515
      case 'css_class':
2516
      case 'display_comment':
2517
        $this->set_option($section, $form_state['values'][$section]);
2518
        break;
2519 5d12d676 Assos Assos
2520 85ad3d82 Assos Assos
      case 'field_language':
2521
        $this->set_option('field_language', $form_state['values']['field_language']);
2522
        $this->set_option('field_language_add_to_query', $form_state['values']['field_language_add_to_query']);
2523
        break;
2524 5d12d676 Assos Assos
2525 85ad3d82 Assos Assos
      case 'use_ajax':
2526
      case 'hide_attachment_summary':
2527
      case 'hide_admin_links':
2528 8be7bf84 Assos Assos
        $this->set_option($section, (bool) $form_state['values'][$section]);
2529 85ad3d82 Assos Assos
        break;
2530 5d12d676 Assos Assos
2531 85ad3d82 Assos Assos
      case 'use_more':
2532
        $this->set_option($section, intval($form_state['values'][$section]));
2533
        $this->set_option('use_more_always', !intval($form_state['values']['use_more_always']));
2534 ef1afbb9 Assos Assos
        $this->set_option('open_new_window', $form_state['values']['open_new_window']) == '1';
2535 85ad3d82 Assos Assos
        $this->set_option('use_more_text', $form_state['values']['use_more_text']);
2536
      case 'distinct':
2537
        $this->set_option($section, $form_state['values'][$section]);
2538
        break;
2539 5d12d676 Assos Assos
2540 85ad3d82 Assos Assos
      case 'group_by':
2541
        $this->set_option($section, $form_state['values'][$section]);
2542
        break;
2543 5d12d676 Assos Assos
2544 85ad3d82 Assos Assos
      case 'row_plugin':
2545
        // This if prevents resetting options to default if they don't change
2546
        // the plugin.
2547
        if ($this->get_option($section) != $form_state['values'][$section]) {
2548
          $plugin = views_get_plugin('row', $form_state['values'][$section]);
2549
          if ($plugin) {
2550
            $this->set_option($section, $form_state['values'][$section]);
2551
            $this->set_option('row_options', array());
2552
2553 8be7bf84 Assos Assos
            // Send ajax form to options page if we use it.
2554 85ad3d82 Assos Assos
            if (!empty($plugin->definition['uses options'])) {
2555
              views_ui_add_form_to_stack('display', $this->view, $this->display->id, array('row_options'));
2556
            }
2557
          }
2558
        }
2559
        break;
2560 5d12d676 Assos Assos
2561 85ad3d82 Assos Assos
      case 'style_plugin':
2562
        // This if prevents resetting options to default if they don't change
2563
        // the plugin.
2564
        if ($this->get_option($section) != $form_state['values'][$section]) {
2565
          $plugin = views_get_plugin('style', $form_state['values'][$section]);
2566
          if ($plugin) {
2567
            $this->set_option($section, $form_state['values'][$section]);
2568
            $this->set_option('style_options', array());
2569 8be7bf84 Assos Assos
            // Send ajax form to options page if we use it.
2570 85ad3d82 Assos Assos
            if (!empty($plugin->definition['uses options'])) {
2571
              views_ui_add_form_to_stack('display', $this->view, $this->display->id, array('style_options'));
2572
            }
2573
          }
2574
        }
2575
        break;
2576 5d12d676 Assos Assos
2577 85ad3d82 Assos Assos
      case 'style_options':
2578
        $style = TRUE;
2579
      case 'row_options':
2580 8be7bf84 Assos Assos
        // If row, $style will be empty.
2581 85ad3d82 Assos Assos
        $plugin = $this->get_plugin(empty($style) ? 'row' : 'style');
2582
        if ($plugin) {
2583
          $plugin->options_submit($form['options'][$section], $form_state);
2584
        }
2585
        $this->set_option($section, $form_state['values'][$section]);
2586
        break;
2587 5d12d676 Assos Assos
2588 85ad3d82 Assos Assos
      case 'exposed_block':
2589
        $this->set_option($section, (bool) $form_state['values'][$section]);
2590
        break;
2591 5d12d676 Assos Assos
2592 85ad3d82 Assos Assos
      case 'exposed_form':
2593
        $exposed_form = $this->get_option('exposed_form');
2594
        if ($exposed_form['type'] != $form_state['values']['exposed_form']['type']) {
2595
          $plugin = views_get_plugin('exposed_form', $form_state['values']['exposed_form']['type']);
2596
          if ($plugin) {
2597
            $exposed_form = array('type' => $form_state['values']['exposed_form']['type'], 'options' => array());
2598
            $this->set_option('exposed_form', $exposed_form);
2599
            if (!empty($plugin->definition['uses options'])) {
2600
              views_ui_add_form_to_stack('display', $this->view, $this->display->id, array('exposed_form_options'));
2601
            }
2602
          }
2603
        }
2604
        break;
2605 5d12d676 Assos Assos
2606 85ad3d82 Assos Assos
      case 'exposed_form_options':
2607
        $plugin = $this->get_plugin('exposed_form');
2608
        if ($plugin) {
2609
          $exposed_form = $this->get_option('exposed_form');
2610
          $plugin->options_submit($form['exposed_form_options'], $form_state);
2611
          $exposed_form['options'] = $form_state['values'][$section];
2612
          $this->set_option('exposed_form', $exposed_form);
2613
        }
2614
        break;
2615 5d12d676 Assos Assos
2616 85ad3d82 Assos Assos
      case 'pager':
2617
        $pager = $this->get_option('pager');
2618
        if ($pager['type'] != $form_state['values']['pager']['type']) {
2619
          $plugin = views_get_plugin('pager', $form_state['values']['pager']['type']);
2620
          if ($plugin) {
2621
            // Because pagers have very similar options, let's allow pagers to
2622
            // try to carry the options over.
2623
            $plugin->init($this->view, $this->display, $pager['options']);
2624
2625
            $pager = array('type' => $form_state['values']['pager']['type'], 'options' => $plugin->options);
2626
            $this->set_option('pager', $pager);
2627
            if (!empty($plugin->definition['uses options'])) {
2628
              views_ui_add_form_to_stack('display', $this->view, $this->display->id, array('pager_options'));
2629
            }
2630
          }
2631
        }
2632
        break;
2633 5d12d676 Assos Assos
2634 85ad3d82 Assos Assos
      case 'pager_options':
2635
        $plugin = $this->get_plugin('pager');
2636
        if ($plugin) {
2637
          $pager = $this->get_option('pager');
2638
          $plugin->options_submit($form['pager_options'], $form_state);
2639
          $pager['options'] = $form_state['values'][$section];
2640
          $this->set_option('pager', $pager);
2641
        }
2642
        break;
2643
    }
2644
2645
    foreach ($this->extender as $extender) {
2646
      $extender->options_submit($form, $form_state);
2647
    }
2648
  }
2649
2650
  /**
2651
   * If override/revert was clicked, perform the proper toggle.
2652
   */
2653 5d12d676 Assos Assos
  public function options_override($form, &$form_state) {
2654 85ad3d82 Assos Assos
    $this->set_override($form_state['section']);
2655
  }
2656
2657
  /**
2658
   * Flip the override setting for the given section.
2659
   *
2660
   * @param string $section
2661
   *   Which option should be marked as overridden, for example "filters".
2662
   * @param bool $new_state
2663
   *   Select the new state of the option.
2664 8be7bf84 Assos Assos
   *   - TRUE: Revert to default.
2665
   *   - FALSE: Mark it as overridden.
2666 85ad3d82 Assos Assos
   */
2667 5d12d676 Assos Assos
  public function set_override($section, $new_state = NULL) {
2668 85ad3d82 Assos Assos
    $options = $this->defaultable_sections($section);
2669
    if (!$options) {
2670
      return;
2671
    }
2672
2673
    if (!isset($new_state)) {
2674
      $new_state = empty($this->options['defaults'][$section]);
2675
    }
2676
2677
    // For each option that is part of this group, fix our settings.
2678
    foreach ($options as $option) {
2679
      if ($new_state) {
2680
        // Revert to defaults.
2681
        unset($this->options[$option]);
2682
        unset($this->display->display_options[$option]);
2683
      }
2684
      else {
2685 8be7bf84 Assos Assos
        // Copy existing values into our display.
2686 85ad3d82 Assos Assos
        $this->options[$option] = $this->get_option($option);
2687
        $this->display->display_options[$option] = $this->options[$option];
2688
      }
2689
      $this->options['defaults'][$option] = $new_state;
2690
      $this->display->display_options['defaults'][$option] = $new_state;
2691
    }
2692
  }
2693
2694
  /**
2695
   * Inject anything into the query that the display handler needs.
2696
   */
2697 5d12d676 Assos Assos
  public function query() {
2698 85ad3d82 Assos Assos
    foreach ($this->extender as $extender) {
2699
      $extender->query();
2700
    }
2701
  }
2702
2703
  /**
2704 5d12d676 Assos Assos
   * Not all display plugins will support filtering.
2705 85ad3d82 Assos Assos
   */
2706 5d12d676 Assos Assos
  public function render_filters() {
2707
  }
2708 85ad3d82 Assos Assos
2709
  /**
2710
   * Not all display plugins will suppert pager rendering.
2711
   */
2712 5d12d676 Assos Assos
  public function render_pager() {
2713 85ad3d82 Assos Assos
    return TRUE;
2714
  }
2715
2716
  /**
2717 5d12d676 Assos Assos
   * Render the 'more' link.
2718 85ad3d82 Assos Assos
   */
2719 5d12d676 Assos Assos
  public function render_more_link() {
2720 85ad3d82 Assos Assos
    if ($this->use_more() && ($this->use_more_always() || (!empty($this->view->query->pager) && $this->view->query->pager->has_more_records()))) {
2721
      $path = $this->get_path();
2722
2723
      if ($this->get_option('link_display') == 'custom_url' && $override_path = $this->get_option('link_url')) {
2724
        $tokens = $this->get_arguments_tokens();
2725
        $path = strtr($override_path, $tokens);
2726
      }
2727
2728
      if ($path) {
2729
        if (empty($override_path)) {
2730
          $path = $this->view->get_url(NULL, $path);
2731
        }
2732
        $url_options = array();
2733
        if (!empty($this->view->exposed_raw_input)) {
2734
          $url_options['query'] = $this->view->exposed_raw_input;
2735
        }
2736
        $theme = views_theme_functions('views_more', $this->view, $this->display);
2737 44d2e178 Assos Assos
2738
        $parsed_url = drupal_parse_url($path);
2739
        // Preserve the query string from url.
2740
        if (!empty($parsed_url['query'])) {
2741
          if (!empty($url_options['query'])) {
2742
            $url_options['query'] = array_merge($parsed_url['query'], $url_options['query']);
2743
          }
2744
          else {
2745
            $url_options['query'] = $parsed_url['query'];
2746
          }
2747
          $path = $parsed_url['path'];
2748
        }
2749
        // Add fragment if applicable.
2750
        if (!empty($parsed_url['fragment'])) {
2751
          $url_options['fragment'] = $parsed_url['fragment'];
2752
        }
2753
2754 85ad3d82 Assos Assos
        $path = check_url(url($path, $url_options));
2755
2756 8be7bf84 Assos Assos
        return theme($theme, array(
2757
          'more_url' => $path,
2758
          'new_window' => $this->use_more_open_new_window(),
2759
          'link_text' => check_plain($this->use_more_text()),
2760
          'view' => $this->view,
2761
        ));
2762 85ad3d82 Assos Assos
      }
2763
    }
2764
  }
2765
2766
  /**
2767
   * Legacy functions.
2768
   */
2769
2770
  /**
2771
   * Render the header of the view.
2772
   */
2773 5d12d676 Assos Assos
  public function render_header() {
2774 85ad3d82 Assos Assos
    $empty = !empty($this->view->result);
2775
    return $this->render_area('header', $empty);
2776
  }
2777
2778
  /**
2779
   * Render the footer of the view.
2780
   */
2781 5d12d676 Assos Assos
  public function render_footer() {
2782 85ad3d82 Assos Assos
    $empty = !empty($this->view->result);
2783
    return $this->render_area('footer', $empty);
2784
  }
2785
2786 5d12d676 Assos Assos
  /**
2787
   *
2788
   */
2789
  public function render_empty() {
2790 85ad3d82 Assos Assos
    return $this->render_area('empty');
2791
  }
2792
2793
  /**
2794
   * If this display creates a block, implement one of these.
2795
   */
2796 5d12d676 Assos Assos
  public function hook_block_list($delta = 0, $edit = array()) {
2797
    return array();
2798
  }
2799 85ad3d82 Assos Assos
2800
  /**
2801
   * If this display creates a page with a menu item, implement it here.
2802
   */
2803 5d12d676 Assos Assos
  public function hook_menu() {
2804
    return array();
2805
  }
2806 85ad3d82 Assos Assos
2807
  /**
2808
   * Render this display.
2809
   */
2810 5d12d676 Assos Assos
  public function render() {
2811 85ad3d82 Assos Assos
    return theme($this->theme_functions(), array('view' => $this->view));
2812
  }
2813
2814 5d12d676 Assos Assos
  /**
2815
   *
2816
   */
2817
  public function render_area($area, $empty = FALSE) {
2818 85ad3d82 Assos Assos
    $return = '';
2819
    foreach ($this->get_handlers($area) as $area) {
2820
      $return .= $area->render($empty);
2821
    }
2822
    return $return;
2823
  }
2824
2825
  /**
2826
   * Determine if the user has access to this display of the view.
2827
   */
2828 5d12d676 Assos Assos
  public function access($account = NULL) {
2829 85ad3d82 Assos Assos
    if (!isset($account)) {
2830
      global $user;
2831
      $account = $user;
2832
    }
2833
2834
    // Full override.
2835
    if (user_access('access all views', $account)) {
2836
      return TRUE;
2837
    }
2838
2839
    $plugin = $this->get_plugin('access');
2840
    if ($plugin) {
2841
      return $plugin->access($account);
2842
    }
2843
2844 5d12d676 Assos Assos
    // Fallback to all access if no plugin.
2845 85ad3d82 Assos Assos
    return TRUE;
2846
  }
2847
2848
  /**
2849 8be7bf84 Assos Assos
   * Set up any variables on the view prior to execution.
2850
   *
2851
   * These are separated from execute because they are extremely common and
2852
   * unlikely to be overridden on an individual display.
2853 85ad3d82 Assos Assos
   */
2854 5d12d676 Assos Assos
  public function pre_execute() {
2855 85ad3d82 Assos Assos
    $this->view->set_use_ajax($this->use_ajax());
2856
    if ($this->use_more() && !$this->use_more_always()) {
2857
      $this->view->get_total_rows = TRUE;
2858
    }
2859
    $this->view->init_handlers();
2860
    if ($this->uses_exposed()) {
2861
      $exposed_form = $this->get_plugin('exposed_form');
2862
      $exposed_form->pre_execute();
2863
    }
2864
2865
    foreach ($this->extender as $extender) {
2866
      $extender->pre_execute();
2867
    }
2868
2869
    if ($this->get_option('hide_admin_links')) {
2870
      $this->view->hide_admin_links = TRUE;
2871
    }
2872
  }
2873
2874
  /**
2875
   * When used externally, this is how a view gets run and returns
2876
   * data in the format required.
2877
   *
2878
   * The base class cannot be executed.
2879
   */
2880 5d12d676 Assos Assos
  public function execute() {
2881
  }
2882 85ad3d82 Assos Assos
2883
  /**
2884 5d12d676 Assos Assos
   * Fully render the display.
2885
   *
2886
   * Used for the purposes of a live preview or some other AJAXy reason.
2887 85ad3d82 Assos Assos
   */
2888 5d12d676 Assos Assos
  public function preview() {
2889
    return $this->view->render();
2890
  }
2891 85ad3d82 Assos Assos
2892
  /**
2893 5d12d676 Assos Assos
   * Displays can require a certain type of style plugin.
2894
   *
2895
   * By default, they will be 'normal'.
2896 85ad3d82 Assos Assos
   */
2897 5d12d676 Assos Assos
  public function get_style_type() {
2898
    return 'normal';
2899
  }
2900 85ad3d82 Assos Assos
2901
  /**
2902
   * Make sure the display and all associated handlers are valid.
2903
   *
2904
   * @return
2905 5d12d676 Assos Assos
   *   Empty array if the display is valid; an array of error strings if it is
2906
   *   not.
2907 85ad3d82 Assos Assos
   */
2908 5d12d676 Assos Assos
  public function validate() {
2909 85ad3d82 Assos Assos
    $errors = array();
2910
    // Make sure displays that use fields HAVE fields.
2911
    if ($this->uses_fields()) {
2912
      $fields = FALSE;
2913
      foreach ($this->get_handlers('field') as $field) {
2914
        if (empty($field->options['exclude'])) {
2915
          $fields = TRUE;
2916
        }
2917
      }
2918
2919
      if (!$fields) {
2920
        $errors[] = t('Display "@display" uses fields but there are none defined for it or all are excluded.', array('@display' => $this->display->display_title));
2921
      }
2922
    }
2923
2924
    if ($this->has_path() && !$this->get_option('path')) {
2925
      $errors[] = t('Display "@display" uses a path but the path is undefined.', array('@display' => $this->display->display_title));
2926
    }
2927
2928 5d12d676 Assos Assos
    // Validate style plugin.
2929 85ad3d82 Assos Assos
    $style = $this->get_plugin();
2930
    if (empty($style)) {
2931
      $errors[] = t('Display "@display" has an invalid style plugin.', array('@display' => $this->display->display_title));
2932
    }
2933
    else {
2934
      $result = $style->validate();
2935
      if (!empty($result) && is_array($result)) {
2936
        $errors = array_merge($errors, $result);
2937
      }
2938
    }
2939
2940
    // Validate query plugin.
2941
    $query = $this->get_plugin('query');
2942
    $result = $query->validate();
2943
    if (!empty($result) && is_array($result)) {
2944
      $errors = array_merge($errors, $result);
2945
    }
2946
2947 5d12d676 Assos Assos
    // Validate handlers.
2948 85ad3d82 Assos Assos
    foreach (views_object_types() as $type => $info) {
2949
      foreach ($this->get_handlers($type) as $handler) {
2950
        $result = $handler->validate();
2951
        if (!empty($result) && is_array($result)) {
2952
          $errors = array_merge($errors, $result);
2953
        }
2954
      }
2955
    }
2956
2957
    return $errors;
2958
  }
2959
2960
  /**
2961
   * Check if the provided identifier is unique.
2962
   *
2963
   * @param string $id
2964
   *   The id of the handler which is checked.
2965
   * @param string $identifier
2966
   *   The actual get identifier configured in the exposed settings.
2967
   *
2968
   * @return bool
2969
   *   Returns whether the identifier is unique on all handlers.
2970
   */
2971 5d12d676 Assos Assos
  public function is_identifier_unique($id, $identifier) {
2972 85ad3d82 Assos Assos
    foreach (views_object_types() as $type => $info) {
2973
      foreach ($this->get_handlers($type) as $key => $handler) {
2974
        if ($handler->can_expose() && $handler->is_exposed()) {
2975
          if ($handler->is_a_group()) {
2976
            if ($id != $key && $identifier == $handler->options['group_info']['identifier']) {
2977
              return FALSE;
2978
            }
2979
          }
2980
          else {
2981 b08fce64 Assos Assos
            if ($id != $key && isset($handler->options['expose']['identifier']) && $identifier == $handler->options['expose']['identifier']) {
2982 85ad3d82 Assos Assos
              return FALSE;
2983
            }
2984
          }
2985
        }
2986
      }
2987
    }
2988
    return TRUE;
2989
  }
2990
2991
  /**
2992
   * Provide the block system with any exposed widget blocks for this display.
2993
   */
2994 5d12d676 Assos Assos
  public function get_special_blocks() {
2995 85ad3d82 Assos Assos
    $blocks = array();
2996
2997
    if ($this->uses_exposed_form_in_block()) {
2998
      $delta = '-exp-' . $this->view->name . '-' . $this->display->id;
2999
      $desc = t('Exposed form: @view-@display_id', array('@view' => $this->view->name, '@display_id' => $this->display->id));
3000
3001
      $blocks[$delta] = array(
3002
        'info' => $desc,
3003
        'cache' => DRUPAL_NO_CACHE,
3004
      );
3005
    }
3006
3007
    return $blocks;
3008
  }
3009
3010
  /**
3011
   * Render any special blocks provided for this display.
3012
   */
3013 5d12d676 Assos Assos
  public function view_special_blocks($type) {
3014 85ad3d82 Assos Assos
    if ($type == '-exp') {
3015 8be7bf84 Assos Assos
      // Avoid interfering with the admin forms.
3016 85ad3d82 Assos Assos
      if (arg(0) == 'admin' && arg(1) == 'structure' && arg(2) == 'views') {
3017
        return;
3018
      }
3019
      $this->view->init_handlers();
3020
3021
      if ($this->uses_exposed() && $this->get_option('exposed_block')) {
3022
        $exposed_form = $this->get_plugin('exposed_form');
3023
        return array(
3024
          'content' => $exposed_form->render_exposed_form(TRUE),
3025
        );
3026
      }
3027
    }
3028
  }
3029
3030
  /**
3031
   * Override of export_option()
3032
   *
3033 5d12d676 Assos Assos
   * Because displays do not want to export options that are NOT overridden from
3034
   * the default display, we need some special handling during the export
3035
   * process.
3036 85ad3d82 Assos Assos
   */
3037 5d12d676 Assos Assos
  public function export_option($indent, $prefix, $storage, $option, $definition, $parents) {
3038
    // The $prefix is wrong because we store our actual options a little
3039
    // differently.
3040 85ad3d82 Assos Assos
    $prefix = '$handler->display->display_options';
3041
    $output = '';
3042
    if (!$parents && !$this->is_default_display()) {
3043
      // Do not export items that are not overridden.
3044
      if ($this->is_defaulted($option)) {
3045
        return;
3046
      }
3047
3048 5d12d676 Assos Assos
      // If this is not defaulted and is overrideable, flip the switch to say
3049
      // this is overridden.
3050 85ad3d82 Assos Assos
      if ($this->defaultable_sections($option)) {
3051
        $output .= $indent . $prefix . "['defaults']['$option'] = FALSE;\n";
3052
      }
3053
    }
3054
3055
    $output .= parent::export_option($indent, $prefix, $storage, $option, $definition, $parents);
3056
    return $output;
3057
  }
3058
3059
  /**
3060
   * Special method to export items that have handlers.
3061
   *
3062 5d12d676 Assos Assos
   * This method was specified in the option_definition() as the method to
3063
   * utilize to export fields, filters, sort criteria, relationships and
3064
   * arguments. This passes the export off to the individual handlers so that
3065
   * they can export themselves properly.
3066 85ad3d82 Assos Assos
   */
3067 5d12d676 Assos Assos
  public function export_handler($indent, $prefix, $storage, $option, $definition, $parents) {
3068 85ad3d82 Assos Assos
    $output = '';
3069
3070 5d12d676 Assos Assos
    // Cut the 's' off because the data is stored as the plural form but we need
3071 8be7bf84 Assos Assos
    // the singular form.
3072 85ad3d82 Assos Assos
    if ($option != 'header' && $option != 'footer' && $option != 'empty') {
3073
      $type = substr($option, 0, -1);
3074
    }
3075
    else {
3076
      $type = $option;
3077
    }
3078
    $types = views_object_types();
3079
    foreach ($storage[$option] as $id => $info) {
3080
      if (!empty($types[$type]['type'])) {
3081
        $handler_type = $types[$type]['type'];
3082
      }
3083
      else {
3084
        $handler_type = $type;
3085
      }
3086 8be7bf84 Assos Assos
      // If aggregation is on, the group type might override the actual handler
3087
      // that is in use. This piece of code checks that and, if necessary, sets
3088
      // the override handler.
3089 85ad3d82 Assos Assos
      $override = NULL;
3090
      if ($this->use_group_by() && !empty($info['group_type'])) {
3091
        if (empty($this->view->query)) {
3092
          $this->view->init_query();
3093
        }
3094
        $aggregate = $this->view->query->get_aggregation_info();
3095
        if (!empty($aggregate[$info['group_type']]['handler'][$type])) {
3096
          $override = $aggregate[$info['group_type']]['handler'][$type];
3097
        }
3098
      }
3099
      $handler = views_get_handler($info['table'], $info['field'], $handler_type, $override);
3100
      if ($handler) {
3101
        $handler->init($this->view, $info);
3102
        $output .= $indent . '/* ' . $types[$type]['stitle'] . ': ' . $handler->ui_name() . " */\n";
3103
        $output .= $handler->export_options($indent, $prefix . "['$option']['$id']");
3104
      }
3105
3106
      // Prevent reference problems.
3107
      unset($handler);
3108
    }
3109
3110
    return $output;
3111
  }
3112
3113
  /**
3114
   * Special handling for the style export.
3115
   *
3116
   * Styles are stored as style_plugin and style_options or row_plugin and
3117 8be7bf84 Assos Assos
   * row_options accordingly. The options are told not to export, and the export
3118
   * for the plugin should export both.
3119 85ad3d82 Assos Assos
   */
3120 5d12d676 Assos Assos
  public function export_style($indent, $prefix, $storage, $option, $definition, $parents) {
3121 85ad3d82 Assos Assos
    $output = '';
3122
    $style_plugin = $this->get_plugin();
3123
    if ($option == 'style_plugin') {
3124
      $type = 'style';
3125
      $options_field = 'style_options';
3126
      $plugin = $style_plugin;
3127
    }
3128
    else {
3129
      if (!$style_plugin || !$style_plugin->uses_row_plugin()) {
3130
        return;
3131
      }
3132
3133
      $type = 'row';
3134
      $options_field = 'row_options';
3135
      $plugin = $this->get_plugin('row');
3136
      // If the style plugin doesn't use row plugins, don't even bother.
3137
    }
3138
3139
    if ($plugin) {
3140
      // Write which plugin to use.
3141
      $value = $this->get_option($option);
3142
      $output .= $indent . $prefix . "['$option'] = '$value';\n";
3143
3144
      // Pass off to the plugin to export itself.
3145
      $output .= $plugin->export_options($indent, $prefix . "['$options_field']");
3146
    }
3147
3148
    return $output;
3149
  }
3150
3151
  /**
3152 8be7bf84 Assos Assos
   * Special handling for plugin export.
3153 85ad3d82 Assos Assos
   *
3154
   * Plugins other than styles are stored in array with 'type' being the key
3155
   * to the plugin. For modern plugins, the options are stored in the 'options'
3156
   * array, but for legacy plugins (access and cache) options are stored as
3157
   * siblings to the type.
3158
   */
3159 5d12d676 Assos Assos
  public function export_plugin($indent, $prefix, $storage, $option, $definition, $parents) {
3160 85ad3d82 Assos Assos
    $output = '';
3161
    $plugin_type = end($parents);
3162
    $plugin = $this->get_plugin($plugin_type);
3163
    if ($plugin) {
3164
      // Write which plugin to use.
3165
      $value = $storage[$option];
3166
      $new_prefix = $prefix . "['$plugin_type']";
3167
3168
      $output .= $indent . $new_prefix . "['$option'] = '$value';\n";
3169
3170 8be7bf84 Assos Assos
      if ($plugin_type != 'access' && $plugin_type != 'cache') {
3171 85ad3d82 Assos Assos
        $new_prefix .= "['options']";
3172
      }
3173
3174
      // Pass off to the plugin to export itself.
3175
      $output .= $plugin->export_options($indent, $new_prefix);
3176
    }
3177
3178
    return $output;
3179
  }
3180
3181 5d12d676 Assos Assos
  /**
3182
   *
3183
   */
3184
  public function unpack_style($indent, $prefix, $storage, $option, $definition, $parents) {
3185 85ad3d82 Assos Assos
    $output = '';
3186
    $style_plugin = $this->get_plugin();
3187
    if ($option == 'style_plugin') {
3188
      $type = 'style';
3189
      $options_field = 'style_options';
3190
      $plugin = $style_plugin;
3191
    }
3192
    else {
3193
      if (!$style_plugin || !$style_plugin->uses_row_plugin()) {
3194
        return;
3195
      }
3196
3197
      $type = 'row';
3198
      $options_field = 'row_options';
3199
      $plugin = $this->get_plugin('row');
3200
      // If the style plugin doesn't use row plugins, don't even bother.
3201
    }
3202
3203
    if ($plugin) {
3204
      return $plugin->unpack_translatables($translatable, $parents);
3205
    }
3206
  }
3207
3208
  /**
3209
   * Special handling for plugin unpacking.
3210
   */
3211 5d12d676 Assos Assos
  public function unpack_plugin(&$translatable, $storage, $option, $definition, $parents) {
3212 85ad3d82 Assos Assos
    $plugin_type = end($parents);
3213
    $plugin = $this->get_plugin($plugin_type);
3214
    if ($plugin) {
3215
      // Write which plugin to use.
3216
      return $plugin->unpack_translatables($translatable, $parents);
3217
    }
3218
  }
3219
3220 5d12d676 Assos Assos
  /**
3221 85ad3d82 Assos Assos
   * Special method to unpack items that have handlers.
3222
   *
3223 5d12d676 Assos Assos
   * This method was specified in the option_definition() as the method to
3224
   * utilize to export fields, filters, sort criteria, relationships and
3225
   * arguments. This passes the export off to the individual handlers so that
3226
   * they can export themselves properly.
3227 85ad3d82 Assos Assos
   */
3228 5d12d676 Assos Assos
  public function unpack_handler(&$translatable, $storage, $option, $definition, $parents) {
3229 85ad3d82 Assos Assos
    $output = '';
3230
3231 5d12d676 Assos Assos
    // Cut the 's' off because the data is stored as the plural form but we need
3232 8be7bf84 Assos Assos
    // the singular form.
3233 85ad3d82 Assos Assos
    if ($option != 'header' && $option != 'footer' && $option != 'empty') {
3234
      $type = substr($option, 0, -1);
3235
    }
3236
    else {
3237
      $type = $option;
3238
    }
3239
    $types = views_object_types();
3240
    foreach ($storage[$option] as $id => $info) {
3241
      if (!empty($types[$type]['type'])) {
3242
        $handler_type = $types[$type]['type'];
3243
      }
3244
      else {
3245
        $handler_type = $type;
3246
      }
3247
      $handler = views_get_handler($info['table'], $info['field'], $handler_type);
3248
      if ($handler) {
3249
        $handler->init($this->view, $info);
3250 8be7bf84 Assos Assos
        $items = array_merge($parents, array($type, $info['table'], $info['id']));
3251
        $handler->unpack_translatables($translatable, $items);
3252 85ad3d82 Assos Assos
      }
3253
3254
      // Prevent reference problems.
3255
      unset($handler);
3256
    }
3257
3258
    return $output;
3259
  }
3260
3261
  /**
3262
   * Provide some helpful text for the arguments.
3263 5d12d676 Assos Assos
   *
3264 8be7bf84 Assos Assos
   * The result should contain of an array with:
3265
   * - filter value present: The title of the fieldset in the argument where
3266
   *   you can configure what should be done with a given argument.
3267
   * - filter value not present: The tiel of the fieldset in the argument where
3268
   *   you can configure what should be done if the argument does not exist.
3269
   * - description: A description about how arguments comes to the display. For
3270
   *   example blocks don't get it from url.
3271 85ad3d82 Assos Assos
   */
3272 5d12d676 Assos Assos
  public function get_argument_text() {
3273 85ad3d82 Assos Assos
    return array(
3274
      'filter value not present' => t('When the filter value is <em>NOT</em> available'),
3275
      'filter value present' => t('When the filter value <em>IS</em> available or a default is provided'),
3276
      'description' => t("This display does not have a source for contextual filters, so no contextual filter value will be available unless you select 'Provide default'."),
3277
    );
3278
  }
3279
3280
  /**
3281
   * Provide some helpful text for pagers.
3282
   *
3283 8be7bf84 Assos Assos
   * The result should contain of an array with:
3284
   * - items per page title.
3285
   * - items per page description.
3286 85ad3d82 Assos Assos
   */
3287 5d12d676 Assos Assos
  public function get_pager_text() {
3288 85ad3d82 Assos Assos
    return array(
3289
      'items per page title' => t('Items to display'),
3290 8be7bf84 Assos Assos
      'items per page description' => t('The number of items to display. Enter 0 for no limit.'),
3291 85ad3d82 Assos Assos
    );
3292
  }
3293
3294 5d12d676 Assos Assos
}
3295 85ad3d82 Assos Assos
3296
/**
3297
 * @}
3298
 */