3 namespace Drupal\views\Plugin\views\display;
5 use Drupal\Core\Form\FormStateInterface;
6 use Drupal\views\ViewExecutable;
9 * The plugin that handles an attachment display.
11 * Attachment displays are secondary displays that are 'attached' to a primary
12 * display. Effectively they are a simple way to get multiple views within
13 * the same view. They can share some information.
15 * @ingroup views_display_plugins
19 * title = @Translation("Attachment"),
20 * help = @Translation("Attachments added to other displays to achieve multiple views in the same view."),
21 * theme = "views_view",
22 * contextual_links_locations = {""}
25 class Attachment extends DisplayPluginBase {
28 * Whether the display allows the use of a pager or not.
32 protected $usesPager = FALSE;
34 protected function defineOptions() {
35 $options = parent::defineOptions();
37 $options['displays'] = ['default' => []];
38 $options['attachment_position'] = ['default' => 'before'];
39 $options['inherit_arguments'] = ['default' => TRUE];
40 $options['inherit_exposed_filters'] = ['default' => FALSE];
41 $options['inherit_pager'] = ['default' => FALSE];
42 $options['render_pager'] = ['default' => FALSE];
47 public function execute() {
48 return $this->view->render($this->display['id']);
51 public function attachmentPositions($position = NULL) {
53 'before' => $this->t('Before'),
54 'after' => $this->t('After'),
55 'both' => $this->t('Both'),
59 return $positions[$position];
66 * Provide the summary for attachment options in the views UI.
68 * This output is returned as an array.
70 public function optionsSummary(&$categories, &$options) {
71 // It is very important to call the parent function here:
72 parent::optionsSummary($categories, $options);
74 $categories['attachment'] = [
75 'title' => $this->t('Attachment settings'),
82 $displays = array_filter($this->getOption('displays'));
83 if (count($displays) > 1) {
84 $attach_to = $this->t('Multiple displays');
86 elseif (count($displays) == 1) {
87 $display = array_shift($displays);
88 if ($display = $this->view->storage->getDisplay($display)) {
89 $attach_to = $display['display_title'];
93 if (!isset($attach_to)) {
94 $attach_to = $this->t('Not defined');
97 $options['displays'] = [
98 'category' => 'attachment',
99 'title' => $this->t('Attach to'),
100 'value' => $attach_to,
103 $options['attachment_position'] = [
104 'category' => 'attachment',
105 'title' => $this->t('Attachment position'),
106 'value' => $this->attachmentPositions($this->getOption('attachment_position')),
109 $options['inherit_arguments'] = [
110 'category' => 'attachment',
111 'title' => $this->t('Inherit contextual filters'),
112 'value' => $this->getOption('inherit_arguments') ? $this->t('Yes') : $this->t('No'),
115 $options['inherit_exposed_filters'] = [
116 'category' => 'attachment',
117 'title' => $this->t('Inherit exposed filters'),
118 'value' => $this->getOption('inherit_exposed_filters') ? $this->t('Yes') : $this->t('No'),
121 $options['inherit_pager'] = [
122 'category' => 'pager',
123 'title' => $this->t('Inherit pager'),
124 'value' => $this->getOption('inherit_pager') ? $this->t('Yes') : $this->t('No'),
127 $options['render_pager'] = [
128 'category' => 'pager',
129 'title' => $this->t('Render pager'),
130 'value' => $this->getOption('render_pager') ? $this->t('Yes') : $this->t('No'),
136 * Provide the default form for setting options.
138 public function buildOptionsForm(&$form, FormStateInterface $form_state) {
139 // It is very important to call the parent function here:
140 parent::buildOptionsForm($form, $form_state);
142 switch ($form_state->get('section')) {
143 case 'inherit_arguments':
144 $form['#title'] .= $this->t('Inherit contextual filters');
145 $form['inherit_arguments'] = [
146 '#type' => 'checkbox',
147 '#title' => $this->t('Inherit'),
148 '#description' => $this->t('Should this display inherit its contextual filter values from the parent display to which it is attached?'),
149 '#default_value' => $this->getOption('inherit_arguments'),
152 case 'inherit_exposed_filters':
153 $form['#title'] .= $this->t('Inherit exposed filters');
154 $form['inherit_exposed_filters'] = [
155 '#type' => 'checkbox',
156 '#title' => $this->t('Inherit'),
157 '#description' => $this->t('Should this display inherit its exposed filter values from the parent display to which it is attached?'),
158 '#default_value' => $this->getOption('inherit_exposed_filters'),
161 case 'inherit_pager':
162 $form['#title'] .= $this->t('Inherit pager');
163 $form['inherit_pager'] = [
164 '#type' => 'checkbox',
165 '#title' => $this->t('Inherit'),
166 '#description' => $this->t('Should this display inherit its paging values from the parent display to which it is attached?'),
167 '#default_value' => $this->getOption('inherit_pager'),
171 $form['#title'] .= $this->t('Render pager');
172 $form['render_pager'] = [
173 '#type' => 'checkbox',
174 '#title' => $this->t('Render'),
175 '#description' => $this->t('Should this display render the pager values? This is only meaningful if inheriting a pager.'),
176 '#default_value' => $this->getOption('render_pager'),
179 case 'attachment_position':
180 $form['#title'] .= $this->t('Position');
181 $form['attachment_position'] = [
182 '#title' => $this->t('Position'),
184 '#description' => $this->t('Attach before or after the parent display?'),
185 '#options' => $this->attachmentPositions(),
186 '#default_value' => $this->getOption('attachment_position'),
190 $form['#title'] .= $this->t('Attach to');
192 foreach ($this->view->storage->get('display') as $display_id => $display) {
193 if ($this->view->displayHandlers->has($display_id) && $this->view->displayHandlers->get($display_id)->acceptAttachments()) {
194 $displays[$display_id] = $display['display_title'];
197 $form['displays'] = [
198 '#title' => $this->t('Displays'),
199 '#type' => 'checkboxes',
200 '#description' => $this->t('Select which display or displays this should attach to.'),
201 '#options' => array_map('\Drupal\Component\Utility\Html::escape', $displays),
202 '#default_value' => $this->getOption('displays'),
209 * Perform any necessary changes to the form values prior to storage.
210 * There is no need for this function to actually store the data.
212 public function submitOptionsForm(&$form, FormStateInterface $form_state) {
213 // It is very important to call the parent function here:
214 parent::submitOptionsForm($form, $form_state);
215 $section = $form_state->get('section');
218 $form_state->setValue($section, array_filter($form_state->getValue($section)));
219 case 'inherit_arguments':
220 case 'inherit_pager':
222 case 'inherit_exposed_filters':
223 case 'attachment_position':
224 $this->setOption($section, $form_state->getValue($section));
232 public function attachTo(ViewExecutable $view, $display_id, array &$build) {
233 $displays = $this->getOption('displays');
235 if (empty($displays[$display_id])) {
239 if (!$this->access()) {
243 $args = $this->getOption('inherit_arguments') ? $this->view->args : [];
244 $view->setArguments($args);
245 $view->setDisplay($this->display['id']);
246 if ($this->getOption('inherit_pager')) {
247 $view->display_handler->usesPager = $this->view->displayHandlers->get($display_id)->usesPager();
248 $view->display_handler->setOption('pager', $this->view->displayHandlers->get($display_id)->getOption('pager'));
251 $attachment = $view->buildRenderable($this->display['id'], $args);
253 switch ($this->getOption('attachment_position')) {
255 $this->view->attachment_before[] = $attachment;
258 $this->view->attachment_after[] = $attachment;
261 $this->view->attachment_before[] = $attachment;
262 $this->view->attachment_after[] = $attachment;
269 * Attachment displays only use exposed widgets if
270 * they are set to inherit the exposed filter settings
271 * of their parent display.
273 public function usesExposed() {
274 if (!empty($this->options['inherit_exposed_filters']) && parent::usesExposed()) {
281 * If an attachment is set to inherit the exposed filter
282 * settings from its parent display, then don't render and
283 * display a second set of exposed filter widgets.
285 public function displaysExposed() {
286 return $this->options['inherit_exposed_filters'] ? FALSE : TRUE;
289 public function renderPager() {
290 return $this->usesPager() && $this->getOption('render_pager');