You are here

function _cms_content_sync_form_alter_disabled_fields in CMS Content Sync 2.1.x

Same name and namespace in other branches
  1. 8 cms_content_sync.module \_cms_content_sync_form_alter_disabled_fields()
  2. 2.0.x cms_content_sync.module \_cms_content_sync_form_alter_disabled_fields()

Disable all form elements if the content has been pulled and the user should not be able to alter pulled content.

Parameters

array $form:

\Drupal\Core\Form\FormStateInterface $form_state: The form state to get default values from.

\Drupal\Core\Entity\EntityInterface $entity:

See also

\cms_content_sync_form_alter()

2 calls to _cms_content_sync_form_alter_disabled_fields()
cms_content_sync_form_alter in ./cms_content_sync.module
1) Make sure the user is informed that content will not only be deleted on this * instance but also on all connected instances if configured that way.
_cms_content_sync_paragraphs_push_settings_form in ./cms_content_sync.module
Add the Push settings for to the several Paragraph widget types.

File

./cms_content_sync.module, line 1344
Module file for cms_content_sync.

Code

function _cms_content_sync_form_alter_disabled_fields(array &$form, FormStateInterface $form_state, EntityInterface $entity) {
  $value_path = [];
  if (!empty($form['#field_parents'])) {
    $value_path = $form['#field_parents'];
  }
  if ($entity
    ->getEntityTypeId() == 'paragraph') {
    $value_path[] = $entity
      ->get('parent_field_name')->value;
    $value_path[] = $form['#delta'];
  }
  $value_path[] = 'cms_content_sync_edit_override';
  if ($form_state
    ->hasValue($value_path)) {
    $value = boolval($form_state
      ->getValue($value_path));
  }
  else {
    $input = $form_state
      ->getUserInput();
    foreach ($value_path as $key) {
      if (empty($input[$key])) {
        $input = NULL;
        break;
      }
      $input = $input[$key];
    }
    $value = boolval($input);
  }
  $entity_status = EntityStatus::getInfosForEntity($entity
    ->getEntityTypeId(), $entity
    ->uuid());
  $behavior = NULL;
  $overridden = FALSE;
  $pull_deletion = FALSE;
  $merged_fields = [];
  foreach ($entity_status as $info) {
    if (!$info || !$info
      ->getLastPull()) {
      continue;
    }
    if ($info
      ->isSourceEntity()) {
      continue;
    }
    if (!$info
      ->getFlow()) {
      continue;
    }
    $config = $info
      ->getFlow()
      ->getController()
      ->getEntityTypeConfig($entity
      ->getEntityTypeId(), $entity
      ->bundle());
    if (isset($config['import_updates']) && ($config['import_updates'] == PullIntent::PULL_UPDATE_FORCE_AND_FORBID_EDITING || $config['import_updates'] == PullIntent::PULL_UPDATE_FORCE_UNLESS_OVERRIDDEN)) {
      $behavior = $config['import_updates'];
      $overridden = $info
        ->isOverriddenLocally() || $value;
      $pull_deletion = boolval($config['import_deletion_settings']['import_deletion']);
      if (EntityHandlerPluginManager::isEntityTypeFieldable($entity
        ->getEntityTypeId())) {

        /** @var \Drupal\Core\Entity\EntityFieldManagerInterface $entityFieldManager */
        $entityFieldManager = Drupal::service('entity_field.manager');
        $type = $entity
          ->getEntityTypeId();
        $bundle = $entity
          ->bundle();
        $field_definitions = $entityFieldManager
          ->getFieldDefinitions($type, $bundle);
        foreach ($field_definitions as $key => $definition) {
          $field_config = $info
            ->getFlow()
            ->getController()
            ->getPropertyConfig($entity
            ->getEntityTypeId(), $entity
            ->bundle(), $key);
          if (!empty($field_config['handler_settings']['merge_local_changes'])) {
            $merged_fields[] = $definition
              ->getLabel();
          }
        }
      }
      break;
    }
  }
  if (!$behavior) {
    return;
  }
  $id = bin2hex(random_bytes(4));
  $allow_overrides = $behavior == PullIntent::PULL_UPDATE_FORCE_UNLESS_OVERRIDDEN;

  // $hide_elements = ['container', 'vertical_tabs', 'details'];.
  foreach ($form as $key => $form_item) {
    if (!is_array($form_item)) {
      continue;
    }
    if (!isset($form_item['#type'])) {
      continue;
    }
    if ($key != 'actions') {
      if ($allow_overrides) {

        // If we used the DISABLED attribute, we couldn't reliably remove it
        // from all elements, as some should still have the attribute from other
        // circumstances and we would also have to apply it nested.
        // Otherwise we'd have to either submit the form and redirect to the
        // edit page or reload the whole form via AJAX, conflicting with
        // embedded forms.
        // So instead we hide and show the elements via JavaScript, leading
        // to the best usability and overall simplest / most reliable
        // implementation from the options available.
        $form[$key]['#attributes']['class'][] = 'cms-content-sync-edit-override-id-' . $id;
        if (!$overridden) {
          $form[$key]['#attributes']['class'][] = 'cms-content-sync-edit-override-hide';
        }
      }
      else {
        if ($form[$key]['#type'] != 'hidden' && $form[$key]['#type'] != 'token' && empty($form[$key]['#disabled'])) {
          if ($key == 'menu') {
            $allow = TRUE;
            $menu_link_manager = Drupal::service('plugin.manager.menu.link');

            /**
             * @var \Drupal\Core\Menu\MenuLinkManager $menu_link_manager
             */
            $menu_items = $menu_link_manager
              ->loadLinksByRoute('entity.' . $entity
              ->getEntityTypeId() . '.canonical', [
              $entity
                ->getEntityTypeId() => $entity
                ->id(),
            ]);
            foreach ($menu_items as $menu_item) {
              if (!$menu_item instanceof MenuLinkContent) {
                continue;
              }

              /**
               * @var \Drupal\menu_link_content\Entity\MenuLinkContent $item
               */
              $item = Drupal::service('entity.repository')
                ->loadEntityByUuid('menu_link_content', $menu_item
                ->getDerivativeId());
              if (!$item) {
                continue;
              }
              $entity_status = EntityStatus::getInfosForEntity($item
                ->getEntityTypeId(), $item
                ->uuid());
              foreach ($entity_status as $info) {
                if (!$info || !$info
                  ->getLastPull()) {
                  continue;
                }
                if ($info
                  ->isSourceEntity()) {
                  continue;
                }
                if (!$info
                  ->getFlow()) {
                  continue;
                }
                $config = $info
                  ->getFlow()
                  ->getController()
                  ->getEntityTypeConfig($item
                  ->getEntityTypeId(), $item
                  ->bundle());
                if ($config['import_updates'] == PullIntent::PULL_UPDATE_FORCE_AND_FORBID_EDITING || $config['import_updates'] == PullIntent::PULL_UPDATE_FORCE_UNLESS_OVERRIDDEN && !$info
                  ->isOverriddenLocally()) {
                  $allow = FALSE;
                }
              }
            }
            if ($allow) {
              continue;
            }
          }

          // This will transform the field from being disabled to being readonly instead. This will interfere with
          // Drupal's default behavior however, so we leave it out by default.
          // $form[$key]['#attributes']['class'][] = 'cms-content-sync-edit-override-disabled';.
          $form[$key]['#disabled'] = TRUE;
        }
      }
    }

    // Disable entity actions for the core layout builder.
    $form_object = $form_state
      ->getFormObject();
    if ($key == 'actions' && $form_object instanceof OverridesEntityForm) {
      if ($behavior == PullIntent::PULL_UPDATE_FORCE_AND_FORBID_EDITING) {
        $form['actions']['submit']['#attributes']['disabled'] = 'disabled';
        $form['actions']['discard_changes']['#attributes']['disabled'] = 'disabled';
        $form['actions']['revert']['#attributes']['disabled'] = 'disabled';
      }
    }

    // Disable the submit button when the editing of the entity is forbidden.
    if ($key == 'actions' && $behavior == PullIntent::PULL_UPDATE_FORCE_AND_FORBID_EDITING) {
      $form['actions']['submit']['#attributes']['disabled'] = 'disabled';
    }
  }
  $is_embedded = $entity
    ->getEntityTypeId() == 'paragraph';
  if ($allow_overrides) {
    $form['cms_content_sync_edit_override'] = [
      '#type' => 'checkbox',
      '#default_value' => $overridden,
      '#weight' => -10000,
      '#title' => t('Overwrite locally and ignore future remote updates'),
      '#description' => t('%label has been pulled and future remote updates would overwrite local changes.<br>Checking this will make sure that future remote updates will be ignored so your local changes persist.<br>Unchecking this will immediately reset all local changes.', [
        '%label' => $is_embedded ? t('This content') : $entity
          ->label(),
      ]) . (count($merged_fields) ? '<br>' . t('Changes to @name will still be merged.', [
        '@name' => implode(', ', $merged_fields),
      ]) : '') . ($pull_deletion ? '<br><strong>' . t('If the remote content is deleted, this content will also be deleted locally.') . '</strong>' : ''),
      '#attributes' => [
        'class' => [
          'cms-content-sync-edit-override',
        ],
        'data-cms-content-sync-edit-override-id' => $id,
      ],
    ];
    $form['cms_content_sync_edit_override__entity_type'] = [
      '#type' => 'hidden',
      '#value' => $entity
        ->getEntityTypeId(),
    ];
    $form['cms_content_sync_edit_override__entity_uuid'] = [
      '#type' => 'hidden',
      '#value' => $entity
        ->uuid(),
    ];
    $form['actions']['submit']['#submit'][] = '_cms_content_sync_override_entity_submit';
  }
  elseif (!$is_embedded) {
    $messenger = Drupal::messenger();
    $messenger
      ->addWarning(t('%label cannot be edited as it has been pulled.', [
      '%label' => $entity
        ->label(),
    ]));
  }
}