Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
| Total | |
0.00% |
0 / 1 |
|
0.00% |
0 / 17 |
CRAP | |
0.00% |
0 / 78 |
| ContentEntityForm | |
0.00% |
0 / 1 |
|
0.00% |
0 / 17 |
702 | |
0.00% |
0 / 78 |
| __construct | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
| create | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 4 |
|||
| form | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 6 |
|||
| submitForm | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 3 |
|||
| buildEntity | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 4 |
|||
| validateForm | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 11 |
|||
| getEditedFieldNames | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
| flagViolations | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 5 |
|||
| init | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 7 |
|||
| initFormLangcodes | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 7 |
|||
| getFormLangcode | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 3 |
|||
| isDefaultFormLangcode | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 3 |
|||
| copyFormValuesToEntity | |
0.00% |
0 / 1 |
20 | |
0.00% |
0 / 7 |
|||
| getFormDisplay | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
| setFormDisplay | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 3 |
|||
| updateFormLangcode | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 5 |
|||
| updateChangedTime | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 4 |
|||
| <?php | |
| /** | |
| * @file | |
| * Contains \Drupal\Core\Entity\ContentEntityForm. | |
| */ | |
| namespace Drupal\Core\Entity; | |
| use Drupal\Core\Entity\Display\EntityFormDisplayInterface; | |
| use Drupal\Core\Entity\Entity\EntityFormDisplay; | |
| use Drupal\Core\Form\FormStateInterface; | |
| use Symfony\Component\DependencyInjection\ContainerInterface; | |
| /** | |
| * Entity form variant for content entity types. | |
| * | |
| * @see \Drupal\Core\ContentEntityBase | |
| */ | |
| class ContentEntityForm extends EntityForm implements ContentEntityFormInterface { | |
| /** | |
| * The entity manager. | |
| * | |
| * @var \Drupal\Core\Entity\EntityManagerInterface | |
| */ | |
| protected $entityManager; | |
| /** | |
| * Constructs a ContentEntityForm object. | |
| * | |
| * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager | |
| * The entity manager. | |
| */ | |
| public function __construct(EntityManagerInterface $entity_manager) { | |
| $this->entityManager = $entity_manager; | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public static function create(ContainerInterface $container) { | |
| return new static( | |
| $container->get('entity.manager') | |
| ); | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public function form(array $form, FormStateInterface $form_state) { | |
| $form = parent::form($form, $form_state); | |
| // Content entity forms do not use the parent's #after_build callback | |
| // because they only need to rebuild the entity in the validation and the | |
| // submit handler because Field API uses its own #after_build callback for | |
| // its widgets. | |
| unset($form['#after_build']); | |
| $this->getFormDisplay($form_state)->buildForm($this->entity, $form, $form_state); | |
| // Allow modules to act before and after form language is updated. | |
| $form['#entity_builders']['update_form_langcode'] = [$this, 'updateFormLangcode']; | |
| return $form; | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public function submitForm(array &$form, FormStateInterface $form_state) { | |
| parent::submitForm($form, $form_state); | |
| // Update the changed timestamp of the entity. | |
| $this->updateChangedTime($this->entity); | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public function buildEntity(array $form, FormStateInterface $form_state) { | |
| /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */ | |
| $entity = parent::buildEntity($form, $form_state); | |
| // Mark the entity as requiring validation. | |
| $entity->setValidationRequired(!$form_state->getTemporaryValue('entity_validated')); | |
| return $entity; | |
| } | |
| /** | |
| * {@inheritdoc} | |
| * | |
| * Button-level validation handlers are highly discouraged for entity forms, | |
| * as they will prevent entity validation from running. If the entity is going | |
| * to be saved during the form submission, this method should be manually | |
| * invoked from the button-level validation handler, otherwise an exception | |
| * will be thrown. | |
| */ | |
| public function validateForm(array &$form, FormStateInterface $form_state) { | |
| parent::validateForm($form, $form_state); | |
| /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */ | |
| $entity = $this->buildEntity($form, $form_state); | |
| $violations = $entity->validate(); | |
| // Remove violations of inaccessible fields and not edited fields. | |
| $violations | |
| ->filterByFieldAccess($this->currentUser()) | |
| ->filterByFields(array_diff(array_keys($entity->getFieldDefinitions()), $this->getEditedFieldNames($form_state))); | |
| $this->flagViolations($violations, $form, $form_state); | |
| // The entity was validated. | |
| $entity->setValidationRequired(FALSE); | |
| $form_state->setTemporaryValue('entity_validated', TRUE); | |
| return $entity; | |
| } | |
| /** | |
| * Gets the names of all fields edited in the form. | |
| * | |
| * If the entity form customly adds some fields to the form (i.e. without | |
| * using the form display), it needs to add its fields here and override | |
| * flagViolations() for displaying the violations. | |
| * | |
| * @param \Drupal\Core\Form\FormStateInterface $form_state | |
| * The current state of the form. | |
| * | |
| * @return string[] | |
| * An array of field names. | |
| */ | |
| protected function getEditedFieldNames(FormStateInterface $form_state) { | |
| return array_keys($this->getFormDisplay($form_state)->getComponents()); | |
| } | |
| /** | |
| * Flags violations for the current form. | |
| * | |
| * If the entity form customly adds some fields to the form (i.e. without | |
| * using the form display), it needs to add its fields to array returned by | |
| * getEditedFieldNames() and overwrite this method in order to show any | |
| * violations for those fields; e.g.: | |
| * @code | |
| * foreach ($violations->getByField('name') as $violation) { | |
| * $form_state->setErrorByName('name', $violation->getMessage()); | |
| * } | |
| * parent::flagViolations($violations, $form, $form_state); | |
| * @endcode | |
| * | |
| * @param \Drupal\Core\Entity\EntityConstraintViolationListInterface $violations | |
| * The violations to flag. | |
| * @param array $form | |
| * A nested array of form elements comprising the form. | |
| * @param \Drupal\Core\Form\FormStateInterface $form_state | |
| * The current state of the form. | |
| */ | |
| protected function flagViolations(EntityConstraintViolationListInterface $violations, array $form, FormStateInterface $form_state) { | |
| // Flag entity level violations. | |
| foreach ($violations->getEntityViolations() as $violation) { | |
| /** @var \Symfony\Component\Validator\ConstraintViolationInterface $violation */ | |
| $form_state->setErrorByName('', $violation->getMessage()); | |
| } | |
| // Let the form display flag violations of its fields. | |
| $this->getFormDisplay($form_state)->flagWidgetsErrorsFromViolations($violations, $form, $form_state); | |
| } | |
| /** | |
| * Initializes the form state and the entity before the first form build. | |
| * | |
| * @param \Drupal\Core\Form\FormStateInterface $form_state | |
| * The current state of the form. | |
| */ | |
| protected function init(FormStateInterface $form_state) { | |
| // Ensure we act on the translation object corresponding to the current form | |
| // language. | |
| $this->initFormLangcodes($form_state); | |
| $langcode = $this->getFormLangcode($form_state); | |
| $this->entity = $this->entity->hasTranslation($langcode) ? $this->entity->getTranslation($langcode) : $this->entity->addTranslation($langcode); | |
| $form_display = EntityFormDisplay::collectRenderDisplay($this->entity, $this->getOperation()); | |
| $this->setFormDisplay($form_display, $form_state); | |
| parent::init($form_state); | |
| } | |
| /** | |
| * Initializes form language code values. | |
| * | |
| * @param \Drupal\Core\Form\FormStateInterface $form_state | |
| * The current state of the form. | |
| */ | |
| protected function initFormLangcodes(FormStateInterface $form_state) { | |
| // Store the entity default language to allow checking whether the form is | |
| // dealing with the original entity or a translation. | |
| if (!$form_state->has('entity_default_langcode')) { | |
| $form_state->set('entity_default_langcode', $this->entity->getUntranslated()->language()->getId()); | |
| } | |
| // This value might have been explicitly populated to work with a particular | |
| // entity translation. If not we fall back to the most proper language based | |
| // on contextual information. | |
| if (!$form_state->has('langcode')) { | |
| // Imply a 'view' operation to ensure users edit entities in the same | |
| // language they are displayed. This allows to keep contextual editing | |
| // working also for multilingual entities. | |
| $form_state->set('langcode', $this->entityManager->getTranslationFromContext($this->entity)->language()->getId()); | |
| } | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public function getFormLangcode(FormStateInterface $form_state) { | |
| $this->initFormLangcodes($form_state); | |
| return $form_state->get('langcode'); | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public function isDefaultFormLangcode(FormStateInterface $form_state) { | |
| $this->initFormLangcodes($form_state); | |
| return $form_state->get('langcode') == $form_state->get('entity_default_langcode'); | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| protected function copyFormValuesToEntity(EntityInterface $entity, array $form, FormStateInterface $form_state) { | |
| // First, extract values from widgets. | |
| $extracted = $this->getFormDisplay($form_state)->extractFormValues($entity, $form, $form_state); | |
| // Then extract the values of fields that are not rendered through widgets, | |
| // by simply copying from top-level form values. This leaves the fields | |
| // that are not being edited within this form untouched. | |
| foreach ($form_state->getValues() as $name => $values) { | |
| if ($entity->hasField($name) && !isset($extracted[$name])) { | |
| $entity->set($name, $values); | |
| } | |
| } | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public function getFormDisplay(FormStateInterface $form_state) { | |
| return $form_state->get('form_display'); | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public function setFormDisplay(EntityFormDisplayInterface $form_display, FormStateInterface $form_state) { | |
| $form_state->set('form_display', $form_display); | |
| return $this; | |
| } | |
| /** | |
| * Updates the form language to reflect any change to the entity language. | |
| * | |
| * There are use cases for modules to act both before and after form language | |
| * being updated, thus the update is performed through an entity builder | |
| * callback, which allows to support both cases. | |
| * | |
| * @param string $entity_type_id | |
| * The entity type identifier. | |
| * @param \Drupal\Core\Entity\EntityInterface $entity | |
| * The entity updated with the submitted values. | |
| * @param array $form | |
| * The complete form array. | |
| * @param \Drupal\Core\Form\FormStateInterface $form_state | |
| * The current state of the form. | |
| * | |
| * @see \Drupal\Core\Entity\ContentEntityForm::form() | |
| */ | |
| public function updateFormLangcode($entity_type_id, EntityInterface $entity, array $form, FormStateInterface $form_state) { | |
| // Update the form language as it might have changed. | |
| if ($this->isDefaultFormLangcode($form_state)) { | |
| $langcode = $entity->language()->getId(); | |
| $form_state->set('langcode', $langcode); | |
| } | |
| } | |
| /** | |
| * Updates the changed time of the entity. | |
| * | |
| * Applies only if the entity implements the EntityChangedInterface. | |
| * | |
| * @param \Drupal\Core\Entity\EntityInterface $entity | |
| * The entity updated with the submitted values. | |
| */ | |
| public function updateChangedTime(EntityInterface $entity) { | |
| if ($entity->getEntityType()->isSubclassOf(EntityChangedInterface::class)) { | |
| $entity->setChangedTime(REQUEST_TIME); | |
| } | |
| } | |
| } |