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

/**
 * @file
5
 * Contains \Drupal\views\Plugin\views\display\Page.
merlinofchaos's avatar
merlinofchaos committed
6
7
 */

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

10
use Drupal\Component\Utility\Xss;
11
use Drupal\Core\Form\FormStateInterface;
12
13
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
14

merlinofchaos's avatar
merlinofchaos committed
15
16
17
18
/**
 * The plugin that handles a full page.
 *
 * @ingroup views_display_plugins
19
 *
20
 * @ViewsDisplay(
aspilicious's avatar
aspilicious committed
21
 *   id = "page",
22
23
 *   title = @Translation("Page"),
 *   help = @Translation("Display the view as a page, with a URL and menu links."),
24
 *   uses_menu_links = TRUE,
25
 *   uses_route = TRUE,
26
27
 *   contextual_links_locations = {"page"},
 *   theme = "views_view",
28
 *   admin = @Translation("Page")
29
30
 * )
 */
31
class Page extends PathPluginBase {
32

33
34
35
36
37
38
39
  /**
   * Whether the display allows attachments.
   *
   * @var bool
   */
  protected $usesAttachments = TRUE;

40
41
42
  /**
   * Overrides \Drupal\views\Plugin\views\display\PathPluginBase::defineOptions().
   */
43
44
  protected function defineOptions() {
    $options = parent::defineOptions();
merlinofchaos's avatar
merlinofchaos committed
45
46
47
48
49
50
51
52

    $options['menu'] = array(
      'contains' => array(
        'type' => array('default' => 'none'),
        // Do not translate menu and title as menu system will.
        'title' => array('default' => '', 'translatable' => FALSE),
        'description' => array('default' => '', 'translatable' => FALSE),
        'weight' => array('default' => 0),
53
        'name' => array('default' => 'navigation'),
merlinofchaos's avatar
merlinofchaos committed
54
        'context' => array('default' => ''),
55
      ),
merlinofchaos's avatar
merlinofchaos committed
56
57
58
59
60
61
62
63
64
    );
    $options['tab_options'] = array(
      'contains' => array(
        'type' => array('default' => 'none'),
        // Do not translate menu and title as menu system will.
        'title' => array('default' => '', 'translatable' => FALSE),
        'description' => array('default' => '', 'translatable' => FALSE),
        'weight' => array('default' => 0),
        'name' => array('default' => 'navigation'),
65
      ),
merlinofchaos's avatar
merlinofchaos committed
66
67
68
69
70
    );

    return $options;
  }

71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
  /**
   * {@inheritdoc}
   */
  protected function getRoute($view_id, $display_id) {
    $route = parent::getRoute($view_id, $display_id);

    // Move _controller to _content for page displays, which will return a
    // normal Drupal HTML page.
    $defaults = $route->getDefaults();
    $defaults['_content'] = $defaults['_controller'];
    unset($defaults['_controller']);
    $route->setDefaults($defaults);

    return $route;
  }

merlinofchaos's avatar
merlinofchaos committed
87
  /**
88
   * Overrides \Drupal\views\Plugin\views\display\PathPluginBase::execute().
merlinofchaos's avatar
merlinofchaos committed
89
   */
90
  public function execute() {
91
92
    parent::execute();

merlinofchaos's avatar
merlinofchaos committed
93
94
95
96
97
98
99
100
    // Let the world know that this is the page view we're using.
    views_set_page_view($this->view);

    // And now render the view.
    $render = $this->view->render();

    // First execute the view so it's possible to get tokens for the title.
    // And the title, which is much easier.
101
102
103
104
105
106
107
108
    // @todo Figure out how to support custom response objects. Maybe for pages
    //   it should be dropped.
    if (is_array($render)) {
      $render += array(
        '#title' => Xss::filterAdmin($this->view->getTitle()),
      );
    }
    return $render;
merlinofchaos's avatar
merlinofchaos committed
109
110
111
  }

  /**
112
   * Overrides \Drupal\views\Plugin\views\display\DisplayPluginBase::optionsSummary().
merlinofchaos's avatar
merlinofchaos committed
113
   */
114
115
  public function optionsSummary(&$categories, &$options) {
    parent::optionsSummary($categories, $options);
merlinofchaos's avatar
merlinofchaos committed
116

117
    $menu = $this->getOption('menu');
merlinofchaos's avatar
merlinofchaos committed
118
119
120
    if (!is_array($menu)) {
      $menu = array('type' => 'none');
    }
121
    switch ($menu['type']) {
merlinofchaos's avatar
merlinofchaos committed
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
      case 'none':
      default:
        $menu_str = t('No menu');
        break;
      case 'normal':
        $menu_str = t('Normal: @title', array('@title' => $menu['title']));
        break;
      case 'tab':
      case 'default tab':
        $menu_str = t('Tab: @title', array('@title' => $menu['title']));
        break;
    }

    $options['menu'] = array(
      'category' => 'page',
      'title' => t('Menu'),
      'value' => views_ui_truncate($menu_str, 24),
    );

141
142
    // This adds a 'Settings' link to the style_options setting if the style
    // has options.
merlinofchaos's avatar
merlinofchaos committed
143
144
145
146
147
148
149
    if ($menu['type'] == 'default tab') {
      $options['menu']['setting'] = t('Parent menu item');
      $options['menu']['links']['tab_options'] = t('Change settings for the parent menu');
    }
  }

  /**
150
   * Overrides \Drupal\views\Plugin\views\display\callbackPluginBase::buildOptionsForm().
merlinofchaos's avatar
merlinofchaos committed
151
   */
152
  public function buildOptionsForm(&$form, FormStateInterface $form_state) {
153
    parent::buildOptionsForm($form, $form_state);
merlinofchaos's avatar
merlinofchaos committed
154
155
156
157
158
159
160
161
162

    switch ($form_state['section']) {
      case 'menu':
        $form['#title'] .= t('Menu item entry');
        $form['menu'] = array(
          '#prefix' => '<div class="clearfix">',
          '#suffix' => '</div>',
          '#tree' => TRUE,
        );
163
        $menu = $this->getOption('menu');
merlinofchaos's avatar
merlinofchaos committed
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
        if (empty($menu)) {
          $menu = array('type' => 'none', 'title' => '', 'weight' => 0);
        }
        $form['menu']['type'] = array(
          '#prefix' => '<div class="views-left-30">',
          '#suffix' => '</div>',
          '#title' => t('Type'),
          '#type' => 'radios',
          '#options' => array(
            'none' => t('No menu entry'),
            'normal' => t('Normal menu entry'),
            'tab' => t('Menu tab'),
            'default tab' => t('Default menu tab')
          ),
          '#default_value' => $menu['type'],
        );
180

merlinofchaos's avatar
merlinofchaos committed
181
182
        $form['menu']['title'] = array(
          '#prefix' => '<div class="views-left-50">',
183
          '#title' => t('Menu link title'),
merlinofchaos's avatar
merlinofchaos committed
184
185
          '#type' => 'textfield',
          '#default_value' => $menu['title'],
186
187
188
189
190
191
192
193
194
195
196
197
198
          '#states' => array(
            'visible' => array(
              array(
                ':input[name="menu[type]"]' => array('value' => 'normal'),
              ),
              array(
                ':input[name="menu[type]"]' => array('value' => 'tab'),
              ),
              array(
                ':input[name="menu[type]"]' => array('value' => 'default tab'),
              ),
            ),
          ),
merlinofchaos's avatar
merlinofchaos committed
199
200
201
202
203
        );
        $form['menu']['description'] = array(
          '#title' => t('Description'),
          '#type' => 'textfield',
          '#default_value' => $menu['description'],
204
          '#description' => t("Shown when hovering over the menu link."),
205
206
207
208
209
210
211
212
213
214
215
216
217
          '#states' => array(
            'visible' => array(
              array(
                ':input[name="menu[type]"]' => array('value' => 'normal'),
              ),
              array(
                ':input[name="menu[type]"]' => array('value' => 'tab'),
              ),
              array(
                ':input[name="menu[type]"]' => array('value' => 'default tab'),
              ),
            ),
          ),
merlinofchaos's avatar
merlinofchaos committed
218
219
        );

220
        // Only display the menu selector if Menu UI module is enabled.
221
        if (\Drupal::moduleHandler()->moduleExists('menu_ui')) {
merlinofchaos's avatar
merlinofchaos committed
222
223
224
          $form['menu']['name'] = array(
            '#title' => t('Menu'),
            '#type' => 'select',
225
            '#options' => menu_ui_get_menus(),
merlinofchaos's avatar
merlinofchaos committed
226
            '#default_value' => $menu['name'],
227
228
229
230
231
232
233
234
235
236
            '#states' => array(
              'visible' => array(
                array(
                  ':input[name="menu[type]"]' => array('value' => 'normal'),
                ),
                array(
                  ':input[name="menu[type]"]' => array('value' => 'tab'),
                ),
              ),
            ),
merlinofchaos's avatar
merlinofchaos committed
237
238
239
240
241
242
243
244
          );
        }
        else {
          $form['menu']['name'] = array(
            '#type' => 'value',
            '#value' => $menu['name'],
          );
          $form['menu']['markup'] = array(
245
            '#markup' => t('Menu selection requires the activation of Menu UI module.'),
merlinofchaos's avatar
merlinofchaos committed
246
247
248
249
250
251
          );
        }
        $form['menu']['weight'] = array(
          '#title' => t('Weight'),
          '#type' => 'textfield',
          '#default_value' => isset($menu['weight']) ? $menu['weight'] : 0,
252
          '#description' => t('In the menu, the heavier links will sink and the lighter links will be positioned nearer the top.'),
253
254
255
256
257
258
259
260
261
262
263
264
265
          '#states' => array(
            'visible' => array(
              array(
                ':input[name="menu[type]"]' => array('value' => 'normal'),
              ),
              array(
                ':input[name="menu[type]"]' => array('value' => 'tab'),
              ),
              array(
                ':input[name="menu[type]"]' => array('value' => 'default tab'),
              ),
            ),
          ),
merlinofchaos's avatar
merlinofchaos committed
266
267
268
        );
        $form['menu']['context'] = array(
          '#title' => t('Context'),
269
          '#suffix' => '</div>',
merlinofchaos's avatar
merlinofchaos committed
270
271
272
          '#type' => 'checkbox',
          '#default_value' => !empty($menu['context']),
          '#description' => t('Displays the link in contextual links'),
273
274
275
276
277
          '#states' => array(
            'visible' => array(
              ':input[name="menu[type]"]' => array('value' => 'tab'),
            ),
          ),
merlinofchaos's avatar
merlinofchaos committed
278
279
280
281
        );
        break;
      case 'tab_options':
        $form['#title'] .= t('Default tab options');
282
        $tab_options = $this->getOption('tab_options');
merlinofchaos's avatar
merlinofchaos committed
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
        if (empty($tab_options)) {
          $tab_options = array('type' => 'none', 'title' => '', 'weight' => 0);
        }

        $form['tab_markup'] = array(
          '#markup' => '<div class="form-item description">' . t('When providing a menu item as a tab, Drupal needs to know what the parent menu item of that tab will be. Sometimes the parent will already exist, but other times you will need to have one created. The path of a parent item will always be the same path with the last part left off. i.e, if the path to this view is <em>foo/bar/baz</em>, the parent path would be <em>foo/bar</em>.') . '</div>',
        );

        $form['tab_options'] = array(
          '#prefix' => '<div class="clearfix">',
          '#suffix' => '</div>',
          '#tree' => TRUE,
        );
        $form['tab_options']['type'] = array(
          '#prefix' => '<div class="views-left-25">',
          '#suffix' => '</div>',
          '#title' => t('Parent menu item'),
          '#type' => 'radios',
          '#options' => array('none' => t('Already exists'), 'normal' => t('Normal menu item'), 'tab' => t('Menu tab')),
          '#default_value' => $tab_options['type'],
        );
        $form['tab_options']['title'] = array(
          '#prefix' => '<div class="views-left-75">',
          '#title' => t('Title'),
          '#type' => 'textfield',
          '#default_value' => $tab_options['title'],
          '#description' => t('If creating a parent menu item, enter the title of the item.'),
310
311
312
313
314
315
316
317
318
319
          '#states' => array(
            'visible' => array(
              array(
                ':input[name="tab_options[type]"]' => array('value' => 'normal'),
              ),
              array(
                ':input[name="tab_options[type]"]' => array('value' => 'tab'),
              ),
            ),
          ),
merlinofchaos's avatar
merlinofchaos committed
320
321
322
323
324
325
        );
        $form['tab_options']['description'] = array(
          '#title' => t('Description'),
          '#type' => 'textfield',
          '#default_value' => $tab_options['description'],
          '#description' => t('If creating a parent menu item, enter the description of the item.'),
326
327
328
329
330
331
332
333
334
335
          '#states' => array(
            'visible' => array(
              array(
                ':input[name="tab_options[type]"]' => array('value' => 'normal'),
              ),
              array(
                ':input[name="tab_options[type]"]' => array('value' => 'tab'),
              ),
            ),
          ),
merlinofchaos's avatar
merlinofchaos committed
336
        );
337
        // Only display the menu selector if Menu UI module is enabled.
338
        if (\Drupal::moduleHandler()->moduleExists('menu_ui')) {
merlinofchaos's avatar
merlinofchaos committed
339
340
341
          $form['tab_options']['name'] = array(
            '#title' => t('Menu'),
            '#type' => 'select',
342
            '#options' => menu_ui_get_menus(),
merlinofchaos's avatar
merlinofchaos committed
343
344
            '#default_value' => $tab_options['name'],
            '#description' => t('Insert item into an available menu.'),
345
346
347
348
349
            '#states' => array(
              'visible' => array(
                ':input[name="tab_options[type]"]' => array('value' => 'normal'),
              ),
            ),
merlinofchaos's avatar
merlinofchaos committed
350
351
352
353
354
355
356
357
          );
        }
        else {
          $form['tab_options']['name'] = array(
            '#type' => 'value',
            '#value' => $tab_options['name'],
          );
          $form['tab_options']['markup'] = array(
358
            '#markup' => t('Menu selection requires the activation of Menu UI module.'),
merlinofchaos's avatar
merlinofchaos committed
359
360
361
362
363
364
365
366
          );
        }
        $form['tab_options']['weight'] = array(
          '#suffix' => '</div>',
          '#title' => t('Tab weight'),
          '#type' => 'textfield',
          '#default_value' => $tab_options['weight'],
          '#size' => 5,
367
          '#description' => t('If the parent menu item is a tab, enter the weight of the tab. Heavier tabs will sink and the lighter tabs will be positioned nearer to the first menu item.'),
368
369
370
371
372
          '#states' => array(
            'visible' => array(
              ':input[name="tab_options[type]"]' => array('value' => 'tab'),
            ),
          ),
merlinofchaos's avatar
merlinofchaos committed
373
374
375
376
377
        );
        break;
    }
  }

378
379
380
  /**
   * Overrides \Drupal\views\Plugin\views\display\callbackPluginBase::validateOptionsForm().
   */
381
  public function validateOptionsForm(&$form, FormStateInterface $form_state) {
382
    parent::validateOptionsForm($form, $form_state);
merlinofchaos's avatar
merlinofchaos committed
383

384
385
386
    if ($form_state['section'] == 'menu') {
      $path = $this->getOption('path');
      if ($form_state['values']['menu']['type'] == 'normal' && strpos($path, '%') !== FALSE) {
387
        form_error($form['menu']['type'], $form_state, t('Views cannot create normal menu items for paths with a % in them.'));
388
      }
merlinofchaos's avatar
merlinofchaos committed
389

390
391
392
393
      if ($form_state['values']['menu']['type'] == 'default tab' || $form_state['values']['menu']['type'] == 'tab') {
        $bits = explode('/', $path);
        $last = array_pop($bits);
        if ($last == '%') {
394
          form_error($form['menu']['type'], $form_state, t('A display whose path ends with a % cannot be a tab.'));
merlinofchaos's avatar
merlinofchaos committed
395
        }
396
      }
merlinofchaos's avatar
merlinofchaos committed
397

398
      if ($form_state['values']['menu']['type'] != 'none' && empty($form_state['values']['menu']['title'])) {
399
        form_error($form['menu']['title'], $form_state, t('Title is required for this menu type.'));
400
      }
merlinofchaos's avatar
merlinofchaos committed
401
402
403
    }
  }

404
405
406
  /**
   * Overrides \Drupal\views\Plugin\views\display\callbackPluginBase::submitOptionsForm().
   */
407
  public function submitOptionsForm(&$form, FormStateInterface $form_state) {
408
    parent::submitOptionsForm($form, $form_state);
409

merlinofchaos's avatar
merlinofchaos committed
410
411
    switch ($form_state['section']) {
      case 'menu':
412
        $this->setOption('menu', $form_state['values']['menu']);
merlinofchaos's avatar
merlinofchaos committed
413
414
        // send ajax form to options page if we use it.
        if ($form_state['values']['menu']['type'] == 'default tab') {
415
          $form_state['view']->addFormToStack('display', $this->display['id'], 'tab_options');
merlinofchaos's avatar
merlinofchaos committed
416
417
418
        }
        break;
      case 'tab_options':
419
        $this->setOption('tab_options', $form_state['values']['tab_options']);
merlinofchaos's avatar
merlinofchaos committed
420
421
422
423
        break;
    }
  }

424
425
426
  /**
   * Overrides \Drupal\views\Plugin\views\display\DisplayPluginBase::validate().
   */
427
  public function validate() {
merlinofchaos's avatar
merlinofchaos committed
428
429
    $errors = parent::validate();

430
    $menu = $this->getOption('menu');
merlinofchaos's avatar
merlinofchaos committed
431
    if (!empty($menu['type']) && $menu['type'] != 'none' && empty($menu['title'])) {
432
      $errors[] = t('Display @display is set to use a menu but the menu link text is not set.', array('@display' => $this->display['display_title']));
merlinofchaos's avatar
merlinofchaos committed
433
434
435
    }

    if ($menu['type'] == 'default tab') {
436
      $tab_options = $this->getOption('tab_options');
merlinofchaos's avatar
merlinofchaos committed
437
      if (!empty($tab_options['type']) && $tab_options['type'] != 'none' && empty($tab_options['title'])) {
438
        $errors[] = t('Display @display is set to use a parent menu but the parent menu link text is not set.', array('@display' => $this->display['display_title']));
merlinofchaos's avatar
merlinofchaos committed
439
440
441
442
443
444
      }
    }

    return $errors;
  }

445
446
447
  /**
   * Overrides \Drupal\views\Plugin\views\display\DisplayPluginBase::getArgumentText().
   */
448
  public function getArgumentText() {
merlinofchaos's avatar
merlinofchaos committed
449
450
451
452
453
454
455
    return array(
      'filter value not present' => t('When the filter value is <em>NOT</em> in the URL'),
      'filter value present' => t('When the filter value <em>IS</em> in the URL or a default is provided'),
      'description' => t('The contextual filter values is provided by the URL.'),
    );
  }

456
457
458
  /**
   * Overrides \Drupal\views\Plugin\views\display\DisplayPluginBase::getPagerText().
   */
459
  public function getPagerText() {
merlinofchaos's avatar
merlinofchaos committed
460
461
462
463
464
    return array(
      'items per page title' => t('Items per page'),
      'items per page description' => t('The number of items to display per page. Enter 0 for no limit.')
    );
  }
465

merlinofchaos's avatar
merlinofchaos committed
466
}