Further Drupal 8.6.4 changes. Some core files were not committed before a commit...
[yaffs-website] / web / core / lib / Drupal / Core / Render / Element / Actions.php
1 <?php
2
3 namespace Drupal\Core\Render\Element;
4
5 use Drupal\Core\Form\FormStateInterface;
6 use Drupal\Core\Render\BubbleableMetadata;
7 use Drupal\Core\Render\Element;
8
9 /**
10  * Provides a wrapper element to group one or more buttons in a form.
11  *
12  * Use of a single Actions element with an array key of 'actions' to group the
13  * primary submit buttons on a form helps to ensure proper styling in themes,
14  * and enables other modules to properly alter a form's actions.
15  *
16  * Usage example:
17  * @code
18  * $form['actions'] = array('#type' => 'actions');
19  * $form['actions']['submit'] = array(
20  *   '#type' => 'submit',
21  *   '#value' => $this->t('Save'),
22  * );
23  * @endcode
24  *
25  * @RenderElement("actions")
26  */
27 class Actions extends Container {
28
29   /**
30    * {@inheritdoc}
31    */
32   public function getInfo() {
33     $class = get_class($this);
34     return [
35       '#process' => [
36         // @todo Move this to #pre_render.
37         [$class, 'preRenderActionsDropbutton'],
38         [$class, 'processActions'],
39         [$class, 'processContainer'],
40       ],
41       '#weight' => 100,
42       '#theme_wrappers' => ['container'],
43     ];
44   }
45
46   /**
47    * Processes a form actions container element.
48    *
49    * @param array $element
50    *   An associative array containing the properties and children of the
51    *   form actions container.
52    * @param \Drupal\Core\Form\FormStateInterface $form_state
53    *   The current state of the form.
54    * @param array $complete_form
55    *   The complete form structure.
56    *
57    * @return array
58    *   The processed element.
59    */
60   public static function processActions(&$element, FormStateInterface $form_state, &$complete_form) {
61     $element['#attributes']['class'][] = 'form-actions';
62     return $element;
63   }
64
65   /**
66    * #pre_render callback for #type 'actions'.
67    *
68    * This callback iterates over all child elements of the #type 'actions'
69    * container to look for elements with a #dropbutton property, so as to group
70    * those elements into dropbuttons. As such, it works similar to #group, but is
71    * specialized for dropbuttons.
72    *
73    * The value of #dropbutton denotes the dropbutton to group the child element
74    * into. For example, two different values of 'foo' and 'bar' on child elements
75    * would generate two separate dropbuttons, which each contain the corresponding
76    * buttons.
77    *
78    * @param array $element
79    *   The #type 'actions' element to process.
80    * @param \Drupal\Core\Form\FormStateInterface $form_state
81    *   The current state of the form.
82    * @param array $complete_form
83    *   The complete form structure.
84    *
85    * @return array
86    *   The processed #type 'actions' element, including individual buttons grouped
87    *   into new #type 'dropbutton' elements.
88    */
89   public static function preRenderActionsDropbutton(&$element, FormStateInterface $form_state, &$complete_form) {
90     $dropbuttons = [];
91     foreach (Element::children($element, TRUE) as $key) {
92       if (isset($element[$key]['#dropbutton'])) {
93         $dropbutton = $element[$key]['#dropbutton'];
94         // If there is no dropbutton for this button group yet, create one.
95         if (!isset($dropbuttons[$dropbutton])) {
96           $dropbuttons[$dropbutton] = [
97             '#type' => 'dropbutton',
98           ];
99         }
100         // Add this button to the corresponding dropbutton.
101         // @todo Change #type 'dropbutton' to be based on item-list.html.twig
102         //   instead of links.html.twig to avoid this preemptive rendering.
103         $button = \Drupal::service('renderer')->renderPlain($element[$key]);
104         $dropbuttons[$dropbutton]['#links'][$key] = [
105           'title' => $button,
106         ];
107         // Merge metadata like drupalSettings.
108         BubbleableMetadata::createFromRenderArray($dropbuttons[$dropbutton])
109           ->merge(BubbleableMetadata::createFromRenderArray($element[$key]))
110           ->applyTo($dropbuttons[$dropbutton]);
111       }
112     }
113     // @todo For now, all dropbuttons appear first. Consider to invent a more
114     //   fancy sorting/injection algorithm here.
115     return $dropbuttons + $element;
116   }
117
118 }