3 namespace Drupal\inline_entity_form;
5 use Drupal\Component\Utility\NestedArray;
6 use Drupal\Core\Form\FormStateInterface;
7 use Drupal\Core\Render\Element;
10 * Provides #ief_element_submit, the submit version of #element_validate.
12 * #ief_element_submit callbacks are invoked by a #submit callback added
13 * to the form's main submit button.
18 * Attaches the #ief_element_submit functionality to the given form.
22 * @param \Drupal\Core\Form\FormStateInterface $form_state
25 public static function attach(&$form, FormStateInterface $form_state) {
26 // attach() is called for each IEF form element, but the callbacks only
27 // need to be added once per form build.
28 if (isset($form['#ief_element_submit_attached'])) {
31 $form['#ief_element_submit_attached'] = TRUE;
33 // Entity form actions.
34 foreach (['submit', 'publish', 'unpublish'] as $action) {
35 if (!empty($form['actions'][$action])) {
36 self::addCallback($form['actions'][$action], $form);
39 // Generic submit button.
40 if (!empty($form['submit'])) {
41 self::addCallback($form['submit'], $form);
46 * Adds the trigger callback to the given submit element.
48 * @param array $element
50 * @param array $complete_form
53 public static function addCallback(&$element, $complete_form) {
54 if (empty($element['#submit'])) {
55 // Drupal runs either the button-level callbacks or the form-level ones.
56 // Having no button-level callbacks indicates that the form has relied
57 // on form-level callbacks, which now need to be transferred.
58 $element['#submit'] = $complete_form['#submit'];
61 $element['#submit'] = array_merge([[get_called_class(), 'trigger']], $element['#submit']);
62 // Used to distinguish between an inline form submit and main form submit.
63 $element['#ief_submit_trigger'] = TRUE;
64 $element['#ief_submit_trigger_all'] = TRUE;
68 * Button #submit callback: Triggers submission of element forms.
72 * @param \Drupal\Core\Form\FormStateInterface $form_state
75 public static function trigger($form, FormStateInterface $form_state) {
76 $triggered_element = $form_state->getTriggeringElement();
77 if (!empty($triggered_element['#ief_submit_trigger_all'])) {
78 // The parent form was submitted, process all IEFs and their children.
79 static::doSubmit($form, $form_state);
82 // A specific element was submitted, process it and all of its children.
83 $array_parents = $triggered_element['#array_parents'];
84 $array_parents = array_slice($array_parents, 0, -2);
85 $element = NestedArray::getValue($form, $array_parents);
86 static::doSubmit($element, $form_state);
91 * Submits elements by calling their #ief_element_submit callbacks.
93 * @param array $element
95 * @param \Drupal\Core\Form\FormStateInterface $form_state
98 public static function doSubmit($element, FormStateInterface $form_state) {
99 // Recurse through all children.
100 foreach (Element::children($element) as $key) {
101 if (!empty($element[$key])) {
102 static::doSubmit($element[$key], $form_state);
106 // If there are callbacks on this level, run them.
107 if (!empty($element['#ief_element_submit'])) {
108 foreach ($element['#ief_element_submit'] as $callback) {
109 call_user_func_array($callback, [&$element, &$form_state]);