pm-4.1.x-dev/src/PmContentEntityForm.php

src/PmContentEntityForm.php
<?php

namespace Drupal\pm;

use Drupal\Core\Render\Element;
use Drupal\Component\Datetime\TimeInterface;
use Drupal\Component\Utility\Html;
use Drupal\Core\Datetime\DateFormatterInterface;
use Drupal\Core\Entity\ContentEntityForm;
use Drupal\Core\Entity\EntityRepositoryInterface;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\TempStore\PrivateTempStoreFactory;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Routing\RouterInterface;

class PmContentEntityForm extends ContentEntityForm {

  /**
   * The request stack.
   *
   * @var \Symfony\Component\HttpFoundation\RequestStack
   */
  protected $request;

  /**
   * The tempstore factory.
   *
   * @var \Drupal\Core\TempStore\PrivateTempStoreFactory
   */
  protected $tempStoreFactory;

  /**
   * The Current User object.
   *
   * @var \Drupal\Core\Session\AccountInterface
   */
  protected $currentUser;

  /**
   * The date formatter service.
   *
   * @var \Drupal\Core\Datetime\DateFormatterInterface
   */
  protected $dateFormatter;

  /**
   * The router service.
   *
   * @var \Drupal\Core\Routing\Router
   */
  protected $router;

  /**
   * The whitelisted element types that can be pre-populated.
   *
   * The default list is intentionally limited to not include radios and
   * checkboxes for security reasons. Site visitors cannot click a link
   * to an admin page that prepopulates additional permissions or settings
   * that are un-noticed and unknowingly aggregated to the site.
   *
   * @var array
   */
  protected $whitelistedTypes = [
    'container',
    'date',
    'datelist',
    'datetime',
    'entity_autocomplete',
    'email',
    'fieldset',
    'inline_entity_form',
    'language_select',
    'machine_name',
    'number',
    'path',
    'select',
    'radios',
    'tel',
    'textarea',
    'text_format',
    'textfield',
    'url',
  ];

  /**
   * Constructs a PmContentEntityForm object.
   *
   * @param \Symfony\Component\HttpFoundation\RequestStack $request
   *   The Request stack.
   * @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository
   *   The entity repository.
   * @param \Drupal\Core\TempStore\PrivateTempStoreFactory $temp_store_factory
   *   The factory for the temp store object.
   * @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entity_type_bundle_info
   *   The entity type bundle service.
   * @param \Drupal\Component\Datetime\TimeInterface $time
   *   The time service.
   * @param \Drupal\Core\Session\AccountInterface $current_user
   *   The current user.
   * @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
   *   The date formatter service.
   * @param \Symfony\Component\Routing\RouterInterface $router
   *   The Router service.
   */
  public function __construct(RequestStack $request, EntityRepositoryInterface $entity_repository, PrivateTempStoreFactory $temp_store_factory, EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL, TimeInterface $time = NULL, AccountInterface $current_user, DateFormatterInterface $date_formatter, RouterInterface $router) {
    parent::__construct($entity_repository, $entity_type_bundle_info, $time);
    $this->tempStoreFactory = $temp_store_factory;
    $this->currentUser = $current_user;
    $this->dateFormatter = $date_formatter;
    $this->request = $request;
    $this->router = $router;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    /* @phpstan-ignore new.static */
    return new static(
      $container->get('request_stack'),
      $container->get('entity.repository'),
      $container->get('tempstore.private'),
      $container->get('entity_type.bundle.info'),
      $container->get('datetime.time'),
      $container->get('current_user'),
      $container->get('date.formatter'),
      $container->get('router')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $form = parent::buildForm($form, $form_state);
    return $this->adjustForm($form);
  }

  /**
   * {@inheritdoc}
   */
  public function save(array $form, FormStateInterface $form_state) {
    $result = parent::save($form, $form_state);

    $entity = $this->getEntity();
    $entity_type = $entity->getEntityType();

    $message_arguments = [
      '%label' => $entity->toLink()->toString(),
      '%type' => $entity_type->getLabel(),
    ];
    $logger_arguments = [
      '%label' => $entity->label(),
      'link' => $entity->toLink($this->t('View'))->toString(),
    ];

    switch ($result) {
      case SAVED_NEW:
        $this->messenger()->addStatus($this->t('New %type %label has been created.', $message_arguments));
        $this->logger('pm')->notice('Created new %type %label', $logger_arguments);
        break;

      case SAVED_UPDATED:
        $this->messenger()->addStatus($this->t('The %type %label has been updated.', $message_arguments));
        $this->logger('pm')->notice('Updated %type %label.', $logger_arguments);
        break;
    }

    $arguments = [
      $entity_type->id() => $entity->id(),
    ];

    if ($entity->hasField('pm_project')) {
      $project = $entity->get('pm_project');
      if ($project_id = $project->getValue()['0']['target_id'] ?? NULL) {
        $arguments['pm_project'] = $project_id;
      }
    }
    $route = 'entity.' . $entity_type->id() . '.collection';
    if ($this->router->getRouteCollection()->get($route)) {
      $form_state->setRedirect($route, $arguments);
    }
    else {
      $form_state->setRedirect('entity.' . $entity_type->id() . '.canonical', $arguments);
    }
    return $result;
  }

  /**
   * Make form look pretty out of the box.
   */
  protected function adjustForm(array $form): array {
    /** @var \Drupal\Core\Entity\EntityInterface $entity */
    $entity = $this->entity;
    $form['meta'] = [
      '#type' => 'container',
      '#group' => 'advanced',
      '#weight' => -10,
      '#title' => $this->t('Status'),
      '#attributes' => ['class' => ['entity-meta__header']],
      '#tree' => TRUE,
    ];
    $form['meta']['changed'] = [
      '#type' => 'item',
      '#title' => $this->t('Last updated'),
      '#markup' => !$entity->isNew() ? $this->dateFormatter->format($entity->getChangedTime(), 'short') : $this->t('Not saved yet'),
      '#wrapper_attributes' => ['class' => ['entity-meta__last-saved']],
    ];
    $form['meta']['author'] = [
      '#type' => 'item',
      '#title' => $this->t('Creator'),
      '#markup' => $entity->getOwner()->getAccountName(),
      '#wrapper_attributes' => ['class' => ['entity-meta__author']],
    ];

    // Node author information for administrators.
    $form['author'] = [
      '#type' => 'details',
      '#title' => $this->t('Editing information'),
      '#group' => 'advanced',
      '#attributes' => [
        'class' => ['node-form-author'],
      ],
      '#attached' => [
        'library' => ['node/drupal.node'],
      ],
      '#weight' => 90,
      '#optional' => TRUE,
    ];
    if (isset($form['uid'])) {
      $form['uid']['#group'] = 'author';
    }
    if (isset($form['created'])) {
      $form['created']['#group'] = 'author';
    }
    if (isset($form['pm_project'])) {
      $form['pm_project']['#group'] = 'meta';
    }
    if (isset($form['pm_assignee'])) {
      $form['pm_assignee']['#group'] = 'meta';
    }
    if (isset($form['pm_reviewer'])) {
      $form['pm_reviewer']['#group'] = 'meta';
    }
    if (isset($form['pm_date'])) {
      $form['pm_date']['#group'] = 'meta';
    }
    $form['#theme'] = ['node_edit_form'];
    $form['#attached']['library'][] = 'node/form';
    $form['#attached']['library'][] = 'node/drupal.node';
    $form['#attached']['library'][] = 'claro/node-form';

    // Following is very specific to Claro Theme.
    $form['advanced'] = [
      '#type' => 'container',
      '#attributes' => ['class' => ['entity-meta']],
      '#weight' => 99,
      '#accordion' => TRUE,
    ];
    $this->pmPopulateForm($form);
    return $form;
  }

  /**
   * Pre-populate form elements based on query param.
   */
  protected function pmPopulateForm(array &$form, $request_slice = NULL) {
    $query = $this->request->getCurrentRequest()->query->all();
    if (isset($query['pm-project'])) {
      $this->populateForm($form, [
        'pm_project' => [
          'widget' => $query['pm-project'],
        ],
      ]);
      $this->populateForm($form, [
        'pm_project' => [
          'widget' => [
            0 => [
              'target_id' => $query['pm-project'],
            ],
          ],
        ],
      ]);
    }
  }

  /**
   * Populate form element in a FORM-API array.
   *
   * Heavily based on drupal/prepoulate module to adjust form elements.
   */
  protected function populateForm(array &$form, $request_slice = NULL) {
    if (is_array($request_slice)) {
      foreach (array_keys($request_slice) as $request_variable) {
        if (isset($form[$request_variable])) {
          $element = &$form[$request_variable];
          if (isset($element['widget'][0]['value']['#type'])) {
            $type = $element['widget'][0]['value']['#type'];
          }
          elseif (isset($element['widget'][0]['target_id']['#type'])) {
            $type = $element['widget'][0]['target_id']['#type'];
          }
          elseif (isset($element['widget']['#type'])) {
            $type = $element['widget']['#type'];
          }
          elseif (isset($element['#type'])) {
            $type = $element['#type'];
          }
          if (Element::child($request_variable) && !empty($element) && (empty($type) || in_array($type, $this->whitelistedTypes))) {
            $this->populateForm($element, $request_slice[$request_variable]);
          }
        }
      }
    }
    else {
      // If we don't have a form type, we cannot do anything.
      if (empty($form['#type'])) {
        return;
      }
      // If we already have a value in the form, don't overwrite it.
      if (!empty($form['#value']) && is_scalar($form['#value'])) {
        return;
      }
      // If we don't have access, don't alter it.
      if (isset($form['#access']) && $form['#access'] === FALSE) {
        return;
      }
      $value = Html::escape($request_slice);
      switch ($form['#type']) {
        case 'radios':
          $form['#value'] = $value;
          $form['#default_value'] = $value;
          $form['#disabled']  = TRUE;
          break;

        case 'select':
          $form['#value'] = [$value];
          $form['#default_value'] = [$value];
          $form['#disabled']  = TRUE;
          break;

        case 'entity_autocomplete':
          $form['#value'] = $this->formatEntityAutocomplete($value, $form);
          $form['#disabled'] = TRUE;
          break;

        case 'checkbox':
          $form['#checked'] = $value === 'true';
          $form['#disabled'] = TRUE;
          break;

        default:
          $form['#value'] = $value;
          $form['#disabled'] = TRUE;
          break;
      }
    }
  }

  /**
   * Check access and properly format an autocomplete string.
   *
   * @param string $value
   *   The value.
   * @param array $element
   *   The form element to populate.
   *
   * @return string
   *   The formatted label if entity exists and view label access is allowed.
   *   Otherwise, the value.
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  protected function formatEntityAutocomplete($value, array &$element) {
    $entity = $this->entityTypeManager
      ->getStorage($element['#target_type'])
      ->load($value);
    if ($entity && $entity->access('view label')) {
      return "{$entity->label()} ($value)";
    }
    return $value;
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc