Loading modules/context_stack_form/context_stack_form.info.yml 0 → 100644 +7 −0 Original line number Diff line number Diff line type: module name: "Context Stack Form" description: "Provides a context stack for objects that belong to forms." core_version_requirement: ^9 || ^10 package: Other dependencies: - context_stack:context_stack modules/context_stack_form/context_stack_form.module 0 → 100644 +72 −0 Original line number Diff line number Diff line <?php /** * @file * The Context Stack Form module file. */ use Drupal\context_stack\ContextStackFactory; use Drupal\context_stack\Plugin\Context\GenericEntityContext; use Drupal\Core\Cache\CacheableMetadata; use Drupal\Core\Entity\EntityFormInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Form\FormStateInterface; /** * Implements hook_form_alter(). */ function context_stack_form_form_alter(&$form, FormStateInterface $form_state) { $form_object = $form_state->getFormObject(); $entities = []; foreach ($form as $entry) { if (($entry instanceof EntityInterface) && !isset($entities[$entry->getEntityTypeId()])) { $entities[$entry->getEntityTypeId()] = $entry; } } if ($form_object instanceof EntityFormInterface) { $entity = $form_object->getEntity(); if (!isset($entities[$entity->getEntityTypeId()])) { $entities[$entity->getEntityTypeId()] = $entity; } } if (empty($entities)) { return; } $collection = ContextStackFactory::get()->createCollection(); foreach ($entities as $entity_type_id => $entity) { $collection->addContext(GenericEntityContext::fromEntity($entity, $entity->getEntityType()->getLabel()), $entity_type_id); } $form['#context_stack']['form'] = $collection; // Add cacheability from the context stack to the render array. This is done // by temporarily adding the collection to the stack, fetch its calculated // metadata, then remove it so the render system would render every entity // one-by-one, using the current context that is being pushed via pre-render. /** @var \Drupal\context_stack\ContextStackInterface $context_stack */ $context_stack = \Drupal::service('context_stack.form'); $context_stack->push(clone $collection); CacheableMetadata::createFromRenderArray($form) ->addCacheableDependency($context_stack) ->applyTo($form); $context_stack->pop(); // Add the pre-render callback that will push the current context into the // context stack. The post-render callback is responsible for removing the // added context collection from the stack afterwards. $form['#pre_render'][] = [ '\Drupal\context_stack_form\Render\FormStack', 'preRender', ]; $form['#post_render'][] = [ '\Drupal\context_stack_form\Render\FormStack', 'postRender', ]; } /** * Implements hook_inline_entity_form_entity_form_alter(). * * This hook is only available when inline_entity_form is installed. */ function context_stack_form_inline_entity_form_entity_form_alter(&$form, FormStateInterface $form_state) { context_stack_form_form_alter($form, $form_state); } modules/context_stack_form/context_stack_form.services.yml 0 → 100644 +7 −0 Original line number Diff line number Diff line services: context_stack.form: class: Drupal\context_stack\ContextStack factory: ['@context_stack.factory', createStack] arguments: [form] tags: - { name: context_stack } modules/context_stack_form/src/Render/FormStack.php 0 → 100644 +63 −0 Original line number Diff line number Diff line <?php namespace Drupal\context_stack_form\Render; use Drupal\Core\Security\TrustedCallbackInterface; /** * Trusted callbacks for pushing entities into the "form" stack. */ final class FormStack implements TrustedCallbackInterface { /** * Pre render callback to add form entities to the stack. * * @param array $element * The render element. * * @return array * The (preprocessed) render element. */ public static function preRender(array $element) { if (!empty($element['#context_stack']['form'])) { /** @var \Drupal\context_stack\ContextCollectionInterface $collection */ $collection = $element['#context_stack']['form']; /** @var \Drupal\context_stack\ContextStackInterface $context_stack */ $context_stack = \Drupal::service('context_stack.form'); if (!$collection->getParent() && $collection !== $context_stack->current()) { $context_stack->push($collection); } unset($element['#context_stack']['form']); } return $element; } /** * Post render callback to pop form entities off the stack. * * @param mixed $children * The result of rendering the children. * @param mixed $element * The element as render array. * * @return mixed * The post-processed result. */ public static function postRender($children, $element) { if (!empty($element['#context_stack']['form'])) { $collection = $element['#context_stack']['form']; /** @var \Drupal\context_stack\ContextStackInterface $context_stack */ $context_stack = \Drupal::service('context_stack.form'); while ($collection !== $context_stack->pop() && $context_stack->current()); } return $children; } /** * {@inheritdoc} */ public static function trustedCallbacks() { return ['preRender', 'postRender']; } } Loading
modules/context_stack_form/context_stack_form.info.yml 0 → 100644 +7 −0 Original line number Diff line number Diff line type: module name: "Context Stack Form" description: "Provides a context stack for objects that belong to forms." core_version_requirement: ^9 || ^10 package: Other dependencies: - context_stack:context_stack
modules/context_stack_form/context_stack_form.module 0 → 100644 +72 −0 Original line number Diff line number Diff line <?php /** * @file * The Context Stack Form module file. */ use Drupal\context_stack\ContextStackFactory; use Drupal\context_stack\Plugin\Context\GenericEntityContext; use Drupal\Core\Cache\CacheableMetadata; use Drupal\Core\Entity\EntityFormInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Form\FormStateInterface; /** * Implements hook_form_alter(). */ function context_stack_form_form_alter(&$form, FormStateInterface $form_state) { $form_object = $form_state->getFormObject(); $entities = []; foreach ($form as $entry) { if (($entry instanceof EntityInterface) && !isset($entities[$entry->getEntityTypeId()])) { $entities[$entry->getEntityTypeId()] = $entry; } } if ($form_object instanceof EntityFormInterface) { $entity = $form_object->getEntity(); if (!isset($entities[$entity->getEntityTypeId()])) { $entities[$entity->getEntityTypeId()] = $entity; } } if (empty($entities)) { return; } $collection = ContextStackFactory::get()->createCollection(); foreach ($entities as $entity_type_id => $entity) { $collection->addContext(GenericEntityContext::fromEntity($entity, $entity->getEntityType()->getLabel()), $entity_type_id); } $form['#context_stack']['form'] = $collection; // Add cacheability from the context stack to the render array. This is done // by temporarily adding the collection to the stack, fetch its calculated // metadata, then remove it so the render system would render every entity // one-by-one, using the current context that is being pushed via pre-render. /** @var \Drupal\context_stack\ContextStackInterface $context_stack */ $context_stack = \Drupal::service('context_stack.form'); $context_stack->push(clone $collection); CacheableMetadata::createFromRenderArray($form) ->addCacheableDependency($context_stack) ->applyTo($form); $context_stack->pop(); // Add the pre-render callback that will push the current context into the // context stack. The post-render callback is responsible for removing the // added context collection from the stack afterwards. $form['#pre_render'][] = [ '\Drupal\context_stack_form\Render\FormStack', 'preRender', ]; $form['#post_render'][] = [ '\Drupal\context_stack_form\Render\FormStack', 'postRender', ]; } /** * Implements hook_inline_entity_form_entity_form_alter(). * * This hook is only available when inline_entity_form is installed. */ function context_stack_form_inline_entity_form_entity_form_alter(&$form, FormStateInterface $form_state) { context_stack_form_form_alter($form, $form_state); }
modules/context_stack_form/context_stack_form.services.yml 0 → 100644 +7 −0 Original line number Diff line number Diff line services: context_stack.form: class: Drupal\context_stack\ContextStack factory: ['@context_stack.factory', createStack] arguments: [form] tags: - { name: context_stack }
modules/context_stack_form/src/Render/FormStack.php 0 → 100644 +63 −0 Original line number Diff line number Diff line <?php namespace Drupal\context_stack_form\Render; use Drupal\Core\Security\TrustedCallbackInterface; /** * Trusted callbacks for pushing entities into the "form" stack. */ final class FormStack implements TrustedCallbackInterface { /** * Pre render callback to add form entities to the stack. * * @param array $element * The render element. * * @return array * The (preprocessed) render element. */ public static function preRender(array $element) { if (!empty($element['#context_stack']['form'])) { /** @var \Drupal\context_stack\ContextCollectionInterface $collection */ $collection = $element['#context_stack']['form']; /** @var \Drupal\context_stack\ContextStackInterface $context_stack */ $context_stack = \Drupal::service('context_stack.form'); if (!$collection->getParent() && $collection !== $context_stack->current()) { $context_stack->push($collection); } unset($element['#context_stack']['form']); } return $element; } /** * Post render callback to pop form entities off the stack. * * @param mixed $children * The result of rendering the children. * @param mixed $element * The element as render array. * * @return mixed * The post-processed result. */ public static function postRender($children, $element) { if (!empty($element['#context_stack']['form'])) { $collection = $element['#context_stack']['form']; /** @var \Drupal\context_stack\ContextStackInterface $context_stack */ $context_stack = \Drupal::service('context_stack.form'); while ($collection !== $context_stack->pop() && $context_stack->current()); } return $children; } /** * {@inheritdoc} */ public static function trustedCallbacks() { return ['preRender', 'postRender']; } }