diff --git a/modules/entity_reference_integrity_enforce/entity_reference_integrity_enforce.module b/modules/entity_reference_integrity_enforce/entity_reference_integrity_enforce.module index 51929f9..7105163 100644 --- a/modules/entity_reference_integrity_enforce/entity_reference_integrity_enforce.module +++ b/modules/entity_reference_integrity_enforce/entity_reference_integrity_enforce.module @@ -94,3 +94,71 @@ function entity_reference_integrity_enforce_action_info_alter(&$definitions) { } } } + +/** + * FieldAPI form validation callback. + * + * @see \Drupal\entity_reference_integrity_enforce\FormAlter::formAlter() + */ +function entity_reference_integrity_enforce_state_validation(&$form, FormStateInterface $form_state) { + // Look to see if any entities were defined as possibly blocking this edit. + $entities = $form['referencing_entities_list']['#value']; + + // Nothing to worry about, so skip all further logic. + if (empty($entities)) { + return; + } + + // Support the Content Moderation workflow system. + $new_state = $form_state->getValue('moderation_state'); + if (isset($new_state)) { + // Identify what the actual moderation state is, and if it is both changing + // the publication status to "unpublished" and changing the default revision + // to point to the new revision, block the change. + if (!empty($new_state[0]['value'])) { + // Get the entity that was being edited. + $form_object = $form_state->getFormObject(); + $entity = $form_object->getEntity(); + + /** @var \Drupal\content_moderation\ModerationInformationInterface $moderation_info */ + $moderation_info = \Drupal::service('content_moderation.moderation_information'); + if (!$moderation_info->shouldModerateEntitiesOfBundle($entity->getEntityType(), $entity->bundle())) { + return; + } + + // Load the moderation state. + $workflow = $moderation_info->getWorkflowForEntity($entity); + + // Check the new moderation status. Don't allow the page to be archived, + // which means that the new revision is unpublished and the new revision + // is made the default revision. + $new_moderation_state = $workflow->getTypePlugin()->getState($new_state[0]['value']); + if (!$new_moderation_state->isPublishedState()) { + if ($new_moderation_state->isDefaultRevisionState()) { + $form_state->setErrorByName('moderation_state', t('You can not archive this as it is being referenced by another entity.')); + + // Render the list of entities; no point in doing it earlier if it + // isn't actually needed. + // @see \Drupal\entity_reference_integrity_enforce\FormAlter::buildReferencingEntitiesList() + $form_state->setErrorByName('referencing_entities_list', \Drupal::service('renderer')->render($entities)); + } + } + } + } + + // Standard/legacy node publication states. + else { + $complete_form = $form_state->getCompleteForm(); + $new_status = $form_state->getValue('status'); + + // The node is being unpublished. + if (empty($new_status['value']) && isset($complete_form['status'])) { + $form_state->setErrorByName('status', t('You can not unpublish this as it is being referenced by another entity.')); + + // Render the list of entities; no point in doing it earlier if it isn't + // actually needed. + // @see \Drupal\entity_reference_integrity_enforce\FormAlter::buildReferencingEntitiesList() + $form_state->setErrorByName('referencing_entities_list', \Drupal::service('renderer')->render($entities)); + } + } +} diff --git a/modules/entity_reference_integrity_enforce/src/Form/SettingsForm.php b/modules/entity_reference_integrity_enforce/src/Form/SettingsForm.php index 215a2f3..742c3f0 100644 --- a/modules/entity_reference_integrity_enforce/src/Form/SettingsForm.php +++ b/modules/entity_reference_integrity_enforce/src/Form/SettingsForm.php @@ -72,6 +72,12 @@ class SettingsForm extends ConfigFormBase { '#options' => $options, '#default_value' => $this->config('entity_reference_integrity_enforce.settings')->get('enabled_entity_type_ids'), ]; + $form['show_node_edit_link'] = array( + '#type' => 'checkbox', + '#title' => t('Show node edit link'), + '#description' => t('Show node edit link instead of node link in error message.'), + '#default_value' => $this->config('entity_reference_integrity_enforce.settings')->get('show_node_edit_link'), + ); return parent::buildForm($form, $form_state); } @@ -82,6 +88,7 @@ class SettingsForm extends ConfigFormBase { $this ->config('entity_reference_integrity_enforce.settings') ->set('enabled_entity_type_ids', $form_state->getValue('enabled_entity_type_ids')) + ->set('show_node_edit_link', $form_state->getValue('show_node_edit_link')) ->save(); parent::submitForm($form, $form_state); } diff --git a/modules/entity_reference_integrity_enforce/src/FormAlter.php b/modules/entity_reference_integrity_enforce/src/FormAlter.php index 430944e..9add744 100644 --- a/modules/entity_reference_integrity_enforce/src/FormAlter.php +++ b/modules/entity_reference_integrity_enforce/src/FormAlter.php @@ -8,6 +8,11 @@ use Drupal\Core\Form\FormStateInterface; use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\entity_reference_integrity\EntityReferenceDependencyManagerInterface; use Symfony\Component\DependencyInjection\ContainerInterface; +use Drupal\Core\Url; +use Drupal\Core\Link; +use Drupal\path_alias\AliasManagerInterface; +use Drupal\Core\Config\ConfigFactoryInterface; + /** * Alter entity delete forms to provide some warning deletes will fail. @@ -30,12 +35,29 @@ class FormAlter implements ContainerInjectionInterface { */ protected $enabledEntityTypeIds; + /** + * The path alias manager. + * + * @var \Drupal\path_alias\AliasManagerInterface + */ + protected $aliasManager; + + /** + * The config factory. + * + * @var \Drupal\Core\Config\ConfigFactoryInterface + */ + protected $configFactory; + + /** * Create a DeleteFormAlter object. */ - public function __construct(EntityReferenceDependencyManagerInterface $calculator, $enabled_entity_type_ids) { + public function __construct(EntityReferenceDependencyManagerInterface $calculator, $enabled_entity_type_ids, AliasManagerInterface $alias_manager, ConfigFactoryInterface $config_factory) { $this->dependencyManager = $calculator; $this->enabledEntityTypeIds = $enabled_entity_type_ids; + $this->aliasManager = $alias_manager; + $this->configFactory = $config_factory; } /** @@ -44,7 +66,9 @@ class FormAlter implements ContainerInjectionInterface { public static function create(ContainerInterface $container) { return new static( $container->get('entity_reference_integrity.dependency_manager'), - $container->get('config.factory')->get('entity_reference_integrity_enforce.settings')->get('enabled_entity_type_ids') + $container->get('config.factory')->get('entity_reference_integrity_enforce.settings')->get('enabled_entity_type_ids'), + $container->get('path_alias.manager'), + $container->get('config.factory') ); } @@ -54,7 +78,7 @@ class FormAlter implements ContainerInjectionInterface { public function formAlter(&$form, FormStateInterface $form_state, $form_id) { /** @var \Drupal\Core\Entity\EntityFormInterface $form_object */ $form_object = $form_state->getFormObject(); - if (!$this->isDeleteForm($form_object)) { + if (!$this->isDeleteForm($form_object) && !$this->isEditForm($form_object)) { return; } @@ -62,20 +86,28 @@ class FormAlter implements ContainerInjectionInterface { if (in_array($entity->getEntityTypeId(), $this->enabledEntityTypeIds, TRUE) && $this->dependencyManager->hasDependents($entity)) { $referencing_entities = $this->dependencyManager->getDependentEntities($entity); - - unset($form['actions']['submit']); - unset($form['description']); - - $form['referencing_entities_list'] = [ - '#weight' => -10, - 'explanation' => [ - '#prefix' => '
', - ], - 'entities' => $this->buildReferencingEntitiesList($referencing_entities), - '#suffix' => '