views_ui.theme.inc 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549
  1. <?php
  2. /**
  3. * @file
  4. * Preprocessors and theme functions for the Views UI.
  5. */
  6. use Drupal\Component\Render\FormattableMarkup;
  7. use Drupal\Core\Form\FormState;
  8. use Drupal\Core\Render\Element;
  9. use Drupal\Core\Render\Element\Checkboxes;
  10. use Drupal\Core\Render\Element\Radios;
  11. use Drupal\Core\Url;
  12. use Drupal\Core\Template\Attribute;
  13. /**
  14. * Prepares variables for Views UI display tab setting templates.
  15. *
  16. * Default template: views-ui-display-tab-setting.html.twig.
  17. *
  18. * @param array $variables
  19. * An associative array containing:
  20. * - link: The setting's primary link.
  21. * - settings_links: An array of links for this setting.
  22. * - defaulted: A boolean indicating the setting is in its default state.
  23. * - overridden: A boolean indicating the setting has been overridden from
  24. * the default.
  25. * - description: The setting's description.
  26. * - description_separator: A boolean indicating a separator colon should be
  27. * appended to the setting's description.
  28. */
  29. function template_preprocess_views_ui_display_tab_setting(&$variables) {
  30. // Put the primary link to the left side.
  31. array_unshift($variables['settings_links'], $variables['link']);
  32. if (!empty($variables['overridden'])) {
  33. $variables['attributes']['title'][] = t('Overridden');
  34. }
  35. // Append a colon to the description, if requested.
  36. if ($variables['description'] && $variables['description_separator']) {
  37. $variables['description'] .= t(':');
  38. }
  39. }
  40. /**
  41. * Prepares variables for Views UI view listing templates.
  42. *
  43. * Default template: views-ui-view-listing-table.html.twig.
  44. *
  45. * @param array $variables
  46. * An associative array containing:
  47. * - headers: An associative array containing the headers for the view
  48. * listing table.
  49. * - rows: An associative array containing the rows data for the view
  50. * listing table.
  51. */
  52. function template_preprocess_views_ui_views_listing_table(&$variables) {
  53. // Convert the attributes to valid attribute objects.
  54. foreach ($variables['headers'] as $key => $header) {
  55. $variables['headers'][$key]['attributes'] = new Attribute($header['#attributes']);
  56. }
  57. if (!empty($variables['rows'])) {
  58. foreach ($variables['rows'] as $key => $row) {
  59. $variables['rows'][$key]['attributes'] = new Attribute($row['#attributes']);
  60. }
  61. }
  62. }
  63. /**
  64. * Prepares variables for Views UI display tab bucket templates.
  65. *
  66. * Default template: views-ui-display-tab-bucket.html.twig.
  67. *
  68. * @param array $variables
  69. * An associative array containing:
  70. * - element: An associative array containing the properties of the element.
  71. * Properties used: #name, #overridden, #children, #title, #actions.
  72. */
  73. function template_preprocess_views_ui_display_tab_bucket(&$variables) {
  74. $element = $variables['element'];
  75. if (!empty($element['#overridden'])) {
  76. $variables['attributes']['title'][] = t('Overridden');
  77. }
  78. $variables['name'] = isset($element['#name']) ? $element['#name'] : NULL;
  79. $variables['overridden'] = isset($element['#overridden']) ? $element['#overridden'] : NULL;
  80. $variables['content'] = $element['#children'];
  81. $variables['title'] = $element['#title'];
  82. $variables['actions'] = !empty($element['#actions']) ? $element['#actions'] : [];
  83. }
  84. /**
  85. * Prepares variables for Views UI build group filter form templates.
  86. *
  87. * Default template: views-ui-build-group-filter-form.html.twig.
  88. *
  89. * @param array $variables
  90. * An associative array containing:
  91. * - form: A render element representing the form.
  92. */
  93. function template_preprocess_views_ui_build_group_filter_form(&$variables) {
  94. $form = $variables['form'];
  95. // Prepare table of options.
  96. $header = [
  97. t('Default'),
  98. t('Weight'),
  99. t('Label'),
  100. t('Operator'),
  101. t('Value'),
  102. t('Operations'),
  103. ];
  104. // Prepare default selectors.
  105. $form_state = new FormState();
  106. $form['default_group'] = Radios::processRadios($form['default_group'], $form_state, $form);
  107. $form['default_group_multiple'] = Checkboxes::processCheckboxes($form['default_group_multiple'], $form_state, $form);
  108. $form['default_group']['All']['#title'] = '';
  109. $rows[] = [
  110. ['data' => $form['default_group']['All']],
  111. '',
  112. [
  113. 'data' => \Drupal::config('views.settings')->get('ui.exposed_filter_any_label') == 'old_any' ? t('&lt;Any&gt;') : t('- Any -'),
  114. 'colspan' => 4,
  115. 'class' => ['class' => 'any-default-radios-row'],
  116. ],
  117. ];
  118. // Remove the 'All' default_group form element because it's added to the
  119. // table row.
  120. unset($variables['form']['default_group']['All']);
  121. foreach (Element::children($form['group_items']) as $group_id) {
  122. $form['group_items'][$group_id]['value']['#title'] = '';
  123. $default = [
  124. $form['default_group'][$group_id],
  125. $form['default_group_multiple'][$group_id],
  126. ];
  127. // Remove these fields from the form since they are moved into the table.
  128. unset($variables['form']['default_group'][$group_id]);
  129. unset($variables['form']['default_group_multiple'][$group_id]);
  130. $link = [
  131. '#type' => 'link',
  132. '#url' => Url::fromRoute('<none>', [], [
  133. 'attributes' => [
  134. 'id' => 'views-remove-link-' . $group_id,
  135. 'class' => [
  136. 'views-hidden',
  137. 'views-button-remove',
  138. 'views-groups-remove-link',
  139. 'views-remove-link',
  140. ],
  141. 'alt' => t('Remove this item'),
  142. 'title' => t('Remove this item'),
  143. ],
  144. ]),
  145. '#title' => new FormattableMarkup('<span>@text</span>', ['@text' => t('Remove')]),
  146. ];
  147. $remove = [$form['group_items'][$group_id]['remove'], $link];
  148. $data = [
  149. 'default' => ['data' => $default],
  150. 'weight' => ['data' => $form['group_items'][$group_id]['weight']],
  151. 'title' => ['data' => $form['group_items'][$group_id]['title']],
  152. 'operator' => ['data' => $form['group_items'][$group_id]['operator']],
  153. 'value' => ['data' => $form['group_items'][$group_id]['value']],
  154. 'remove' => ['data' => $remove],
  155. ];
  156. $rows[] = ['data' => $data, 'id' => 'views-row-' . $group_id, 'class' => ['draggable']];
  157. }
  158. $variables['table'] = [
  159. '#type' => 'table',
  160. '#header' => $header,
  161. '#rows' => $rows,
  162. '#attributes' => [
  163. 'class' => ['views-filter-groups'],
  164. 'id' => 'views-filter-groups',
  165. ],
  166. '#tabledrag' => [
  167. [
  168. 'action' => 'order',
  169. 'relationship' => 'sibling',
  170. 'group' => 'weight',
  171. ],
  172. ],
  173. ];
  174. // Hide fields used in table.
  175. unset($variables['form']['group_items']);
  176. }
  177. /**
  178. * Prepares variables for Views UI rearrange filter form templates.
  179. *
  180. * Default template: views-ui-rearrange-filter-form.html.twig.
  181. *
  182. * @param array $variables
  183. * An associative array containing:
  184. * - form: A render element representing the form.
  185. */
  186. function template_preprocess_views_ui_rearrange_filter_form(&$variables) {
  187. $form = &$variables['form'];
  188. $rows = $ungroupable_rows = [];
  189. // Enable grouping only if > 1 group.
  190. $variables['grouping'] = count(array_keys($form['#group_options'])) > 1;
  191. foreach ($form['#group_renders'] as $group_id => $contents) {
  192. // Header row for the group.
  193. if ($group_id !== 'ungroupable') {
  194. // Set up tabledrag so that it changes the group dropdown when rows are
  195. // dragged between groups.
  196. $options = [
  197. 'table_id' => 'views-rearrange-filters',
  198. 'action' => 'match',
  199. 'relationship' => 'sibling',
  200. 'group' => 'views-group-select',
  201. 'subgroup' => 'views-group-select-' . $group_id,
  202. ];
  203. drupal_attach_tabledrag($form['override'], $options);
  204. // Title row, spanning all columns.
  205. $row = [];
  206. // Add a cell to the first row, containing the group operator.
  207. $row[] = [
  208. 'class' => ['group', 'group-operator', 'container-inline'],
  209. 'data' => $form['filter_groups']['groups'][$group_id],
  210. 'rowspan' => max([2, count($contents) + 1]),
  211. ];
  212. // Title.
  213. $row[] = [
  214. 'class' => ['group', 'group-title'],
  215. 'data' => [
  216. '#prefix' => '<span>',
  217. '#markup' => $form['#group_options'][$group_id],
  218. '#suffix' => '</span>',
  219. ],
  220. 'colspan' => 4,
  221. ];
  222. $rows[] = [
  223. 'class' => ['views-group-title'],
  224. 'data' => $row,
  225. 'id' => 'views-group-title-' . $group_id,
  226. ];
  227. // Row which will only appear if the group has nothing in it.
  228. $row = [];
  229. $class = 'group-' . (count($contents) ? 'populated' : 'empty');
  230. $instructions = '<span>' . t('No filters have been added.') . '</span> <span class="js-only">' . t('Drag to add filters.') . '</span>';
  231. // When JavaScript is enabled, the button for removing the group (if it's
  232. // present) should be hidden, since it will be replaced by a link on the
  233. // client side.
  234. if (!empty($form['remove_groups'][$group_id]['#type']) && $form['remove_groups'][$group_id]['#type'] == 'submit') {
  235. $form['remove_groups'][$group_id]['#attributes']['class'][] = 'js-hide';
  236. }
  237. $row[] = [
  238. 'colspan' => 5,
  239. 'data' => [
  240. ['#markup' => $instructions],
  241. $form['remove_groups'][$group_id],
  242. ],
  243. ];
  244. $rows[] = [
  245. 'class' => [
  246. 'group-message',
  247. 'group-' . $group_id . '-message',
  248. $class,
  249. ],
  250. 'data' => $row,
  251. 'id' => 'views-group-' . $group_id,
  252. ];
  253. }
  254. foreach ($contents as $id) {
  255. if (isset($form['filters'][$id]['name'])) {
  256. $row = [];
  257. $row[]['data'] = $form['filters'][$id]['name'];
  258. $form['filters'][$id]['weight']['#attributes']['class'] = ['weight'];
  259. $row[]['data'] = $form['filters'][$id]['weight'];
  260. $form['filters'][$id]['group']['#attributes']['class'] = ['views-group-select views-group-select-' . $group_id];
  261. $row[]['data'] = $form['filters'][$id]['group'];
  262. $form['filters'][$id]['removed']['#attributes']['class'][] = 'js-hide';
  263. $remove_link = [
  264. '#type' => 'link',
  265. '#url' => Url::fromRoute('<none>'),
  266. '#title' => new FormattableMarkup('<span>@text</span>', ['@text' => t('Remove')]),
  267. '#weight' => '1',
  268. '#options' => [
  269. 'attributes' => [
  270. 'id' => 'views-remove-link-' . $id,
  271. 'class' => [
  272. 'views-hidden',
  273. 'views-button-remove',
  274. 'views-groups-remove-link',
  275. 'views-remove-link',
  276. ],
  277. 'alt' => t('Remove this item'),
  278. 'title' => t('Remove this item'),
  279. ],
  280. ],
  281. ];
  282. $row[]['data'] = [
  283. $form['filters'][$id]['removed'],
  284. $remove_link,
  285. ];
  286. $row = [
  287. 'data' => $row,
  288. 'class' => ['draggable'],
  289. 'id' => 'views-row-' . $id,
  290. ];
  291. if ($group_id !== 'ungroupable') {
  292. $rows[] = $row;
  293. }
  294. else {
  295. $ungroupable_rows[] = $row;
  296. }
  297. }
  298. }
  299. }
  300. if (!$variables['grouping']) {
  301. $form['filter_groups']['groups'][0]['#title'] = t('Operator');
  302. }
  303. if (!empty($ungroupable_rows)) {
  304. $header = [
  305. t('Ungroupable filters'),
  306. t('Weight'),
  307. [
  308. 'data' => t('Group'),
  309. 'class' => ['views-hide-label'],
  310. ],
  311. [
  312. 'data' => t('Remove'),
  313. 'class' => ['views-hide-label'],
  314. ],
  315. ];
  316. $variables['ungroupable_table'] = [
  317. '#type' => 'table',
  318. '#header' => $header,
  319. '#rows' => $ungroupable_rows,
  320. '#attributes' => [
  321. 'id' => 'views-rearrange-filters-ungroupable',
  322. 'class' => ['arrange'],
  323. ],
  324. '#tabledrag' => [
  325. [
  326. 'action' => 'order',
  327. 'relationship' => 'sibling',
  328. 'group' => 'weight',
  329. ],
  330. ],
  331. ];
  332. }
  333. if (empty($rows)) {
  334. $rows[] = [['data' => t('No fields available.'), 'colspan' => '2']];
  335. }
  336. // Set up tabledrag so that the weights are changed when rows are dragged.
  337. $variables['table'] = [
  338. '#type' => 'table',
  339. '#rows' => $rows,
  340. '#attributes' => [
  341. 'id' => 'views-rearrange-filters',
  342. 'class' => ['arrange'],
  343. ],
  344. '#tabledrag' => [
  345. [
  346. 'action' => 'order',
  347. 'relationship' => 'sibling',
  348. 'group' => 'weight',
  349. ],
  350. ],
  351. ];
  352. // When JavaScript is enabled, the button for adding a new group should be
  353. // hidden, since it will be replaced by a link on the client side.
  354. $form['actions']['add_group']['#attributes']['class'][] = 'js-hide';
  355. }
  356. /**
  357. * Prepares variables for style plugin table templates.
  358. *
  359. * Default template: views-ui-style-plugin-table.html.twig.
  360. *
  361. * @param array $variables
  362. * An associative array containing:
  363. * - form: A render element representing the form.
  364. */
  365. function template_preprocess_views_ui_style_plugin_table(&$variables) {
  366. $form = $variables['form'];
  367. $header = [
  368. t('Field'),
  369. t('Column'),
  370. t('Align'),
  371. t('Separator'),
  372. [
  373. 'data' => t('Sortable'),
  374. 'align' => 'center',
  375. ],
  376. [
  377. 'data' => t('Default order'),
  378. 'align' => 'center',
  379. ],
  380. [
  381. 'data' => t('Default sort'),
  382. 'align' => 'center',
  383. ],
  384. [
  385. 'data' => t('Hide empty column'),
  386. 'align' => 'center',
  387. ],
  388. [
  389. 'data' => t('Responsive'),
  390. 'align' => 'center',
  391. ],
  392. ];
  393. $rows = [];
  394. foreach (Element::children($form['columns']) as $id) {
  395. $row = [];
  396. $row[]['data'] = $form['info'][$id]['name'];
  397. $row[]['data'] = $form['columns'][$id];
  398. $row[]['data'] = $form['info'][$id]['align'];
  399. $row[]['data'] = $form['info'][$id]['separator'];
  400. if (!empty($form['info'][$id]['sortable'])) {
  401. $row[] = [
  402. 'data' => $form['info'][$id]['sortable'],
  403. 'align' => 'center',
  404. ];
  405. $row[] = [
  406. 'data' => $form['info'][$id]['default_sort_order'],
  407. 'align' => 'center',
  408. ];
  409. $row[] = [
  410. 'data' => $form['default'][$id],
  411. 'align' => 'center',
  412. ];
  413. }
  414. else {
  415. $row[] = '';
  416. $row[] = '';
  417. $row[] = '';
  418. }
  419. $row[] = [
  420. 'data' => $form['info'][$id]['empty_column'],
  421. 'align' => 'center',
  422. ];
  423. $row[] = [
  424. 'data' => $form['info'][$id]['responsive'],
  425. 'align' => 'center',
  426. ];
  427. $rows[] = $row;
  428. }
  429. // Add the special 'None' row.
  430. $rows[] = [['data' => t('None'), 'colspan' => 6], ['align' => 'center', 'data' => $form['default'][-1]], ['colspan' => 2]];
  431. // Unset elements from the form array that are used to build the table so that
  432. // they are not rendered twice.
  433. unset($form['default']);
  434. unset($form['info']);
  435. unset($form['columns']);
  436. $variables['table'] = [
  437. '#type' => 'table',
  438. '#theme' => 'table__views_ui_style_plugin_table',
  439. '#header' => $header,
  440. '#rows' => $rows,
  441. ];
  442. $variables['form'] = $form;
  443. }
  444. /**
  445. * Prepares variables for views UI view preview section templates.
  446. *
  447. * Default template: views-ui-view-preview-section.html.twig.
  448. *
  449. * @param array $variables
  450. * An associative array containing:
  451. * - view: The view object.
  452. * - section: The section name of a View (e.g. title, rows or pager).
  453. */
  454. function template_preprocess_views_ui_view_preview_section(&$variables) {
  455. switch ($variables['section']) {
  456. case 'title':
  457. $variables['title'] = t('Title');
  458. $links = views_ui_view_preview_section_display_category_links($variables['view'], 'title', $variables['title']);
  459. break;
  460. case 'header':
  461. $variables['title'] = t('Header');
  462. $links = views_ui_view_preview_section_handler_links($variables['view'], $variables['section']);
  463. break;
  464. case 'empty':
  465. $variables['title'] = t('No results behavior');
  466. $links = views_ui_view_preview_section_handler_links($variables['view'], $variables['section']);
  467. break;
  468. case 'exposed':
  469. // @todo Sorts can be exposed too, so we may need a better title.
  470. $variables['title'] = t('Exposed Filters');
  471. $links = views_ui_view_preview_section_display_category_links($variables['view'], 'exposed_form_options', $variables['title']);
  472. break;
  473. case 'rows':
  474. // @todo The title needs to depend on what is being viewed.
  475. $variables['title'] = t('Content');
  476. $links = views_ui_view_preview_section_rows_links($variables['view']);
  477. break;
  478. case 'pager':
  479. $variables['title'] = t('Pager');
  480. $links = views_ui_view_preview_section_display_category_links($variables['view'], 'pager_options', $variables['title']);
  481. break;
  482. case 'more':
  483. $variables['title'] = t('More');
  484. $links = views_ui_view_preview_section_display_category_links($variables['view'], 'use_more', $variables['title']);
  485. break;
  486. case 'footer':
  487. $variables['title'] = t('Footer');
  488. $links = views_ui_view_preview_section_handler_links($variables['view'], $variables['section']);
  489. break;
  490. case 'attachment_before':
  491. // @todo: Add links to the attachment configuration page.
  492. $variables['title'] = t('Attachment before');
  493. break;
  494. case 'attachment_after':
  495. // @todo: Add links to the attachment configuration page.
  496. $variables['title'] = t('Attachment after');
  497. break;
  498. }
  499. if (isset($links)) {
  500. $build = [
  501. '#theme' => 'links__contextual',
  502. '#links' => $links,
  503. '#attributes' => ['class' => ['contextual-links']],
  504. '#attached' => [
  505. 'library' => ['contextual/drupal.contextual-links'],
  506. ],
  507. ];
  508. $variables['links'] = $build;
  509. }
  510. }