pate-1.0.0/src/Controller/PateCreateNodeFromTemplateController.php

src/Controller/PateCreateNodeFromTemplateController.php
<?php

namespace Drupal\pate\Controller;

use Drupal\Component\Datetime\TimeInterface;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Datetime\DateFormatterInterface;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\node\NodeInterface;
use Drupal\paragraphs\ParagraphInterface;
use Drupal\replicate\Replicator;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

/**
 * Handles the operation of creating a node from an existing template.
 */
class PateCreateNodeFromTemplateController extends ControllerBase implements ContainerInjectionInterface {

  /**
   * The replicator service.
   *
   * @var \Drupal\replicate\Replicator
   */
  protected $replicator;

  /**
   * The time service.
   *
   * @var \Drupal\Component\Datetime\TimeInterface
   */
  protected $time;

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

  /**
   * Constructs a new controller object.
   *
   * @param \Drupal\replicate\Replicator $replicator
   *   The replicator service.
   * @param \Drupal\Component\Datetime\TimeInterface $time
   *   The time service.
   * @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
   */
  public function __construct(Replicator $replicator, TimeInterface $time, DateFormatterInterface $date_formatter) {
    $this->replicator = $replicator;
    $this->time = $time;
    $this->dateFormatter = $date_formatter;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('replicate.replicator'),
      $container->get('datetime.time'),
      $container->get('date.formatter')
    );
  }

  /**
   * Page callback for creating a new node from template.
   *
   * @param \Drupal\node\NodeInterface $node
   *   The template node.
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   The request object.
   */
  public function createNode(NodeInterface $node, Request $request) {
    // Make sure we only go ahead if this user can do what they are trying
    // to do, and this is really a template.
    $user = $this->currentUser();
    if (!$user->hasPermission('use page templates')) {
      throw new AccessDeniedHttpException('You do not have permission to use page templates.');
    }
    if (empty($node->pate_is_template->value)) {
      throw new NotFoundHttpException('This content is not the template you are looking for.');
    }

    $content_type = $this->entityTypeManager()->getStorage('node_type')->load($node->bundle());
    $timezone = date_default_timezone_get();

    // We use ::cloneEntity() instead of ::replicateEntity() because we don't
    // want to trigger the AFTER_SAVE event (which contrib or custom modules
    // could be listening to). Since we are confident enough at this point
    // that all translations of the cloned entity are already unpublished, we
    // can just set our flag and save it now.
    $new_node = $this->replicator->cloneEntity($node);
    $new_node->pate_is_template->value = FALSE;
    $new_node->pate_structure_only->value = FALSE;
    $new_node->title->value = $this->t('New @type (@template_title) - @timestamp', [
      '@type' => $content_type->label(),
      '@template_title' => $new_node->title->value,
      '@timestamp' => $this->dateFormatter->format($this->time->getRequestTime(), 'custom', 'm/d - H:i', $timezone),
    ]);
    // Reset non-structural field values if this template was marked as
    // structure-only.
    if (!empty($node->pate_structure_only->value)) {
      $this->resetNonStructuralFieldValues($new_node);
    }
    $new_node->save();

    // Display a confirmation message.
    $this->messenger()->addStatus($this->t('Editing node created from template.'));

    // Redirect to the edit form of the new node.
    $route_parameters = ['node' => $new_node->id()];
    $options = ['query' => ['pate_template' => $node->id()]];
    return $this->redirect('entity.node.edit_form', $route_parameters, $options);
  }


  /**
   * Unset all configurable field values, except for paragraph relationships.
   *
   * This will loop over all configurable fields on the entity passed in
   * (ignoring base fields and computed fields). If the field is a reference to
   * a paragraph entity, this will be called recursively on that entity. In all
   * other fields, the field value will be unset.
   *
   * As a result, the entity passed in will have all its configurable field
   * values removed, except for references to paragraph items, which will be
   * there, but will also have their field values removed (except for nested
   * paragraphs, which will also be there, but empty. And so on...).
   *
   * @param \Drupal\Core\Entity\FieldableEntityInterface $entity
   *   The entity we want to delete fields on. Will be modified by reference.
   */
  protected function resetNonStructuralFieldValues(FieldableEntityInterface $entity) {
    foreach ($entity->getFieldDefinitions() as $name => $definition) {
      // Leave base fields and computed fields alone.
      if ($definition->getFieldStorageDefinition()->isBaseField() || $definition->isComputed()) {
        continue;
      }
      // If this is an ERR (paragraphs) field, recurse through it.
      if ($definition->getType() === 'entity_reference_revisions'
        && !empty($entity->get($name)->entity)) {
        foreach ($entity->get($name) as $item) {
          if ($item->entity instanceof ParagraphInterface) {
            $this->resetNonStructuralFieldValues($item->entity);
          }
        }
      }
      else {
        // In all other configurable fields, unset the field value, but allow
        // modules to have a say in this first.
        $context = [
          'field_definition' => $definition,
          'entity' => $entity,
        ];
        $skip = $this->moduleHandler()->invokeAll('pate_skip_field_cleanup', $context);
        // If at least one module wants to skip this field, leave it alone.
        if (in_array(TRUE, $skip, TRUE)) {
          continue;
        }
        else {
          // Clean it up! Or better actually, reset to its default value.
          $entity->set($name, $definition->getDefaultValue($entity), FALSE);
        }
      }
    }
    // If this is a paragraph, save it before leaving.
    if ($entity instanceof ParagraphInterface) {
      $entity->save();
    }
  }

  /**
   * Access handler for this route.
   *
   * @param \Drupal\Core\Session\AccountInterface $account
   *   Run access checks for this account.
   * @param \Drupal\node\NodeInterface $node
   *   The template node.
   *
   * @return \Drupal\Core\Access\AccessResultInterface
   *   The access result.
   */
  public function access(AccountInterface $account, NodeInterface $node) {
    if ($node && $node->access('create', $account) && $account->hasPermission('use page templates')) {
      return AccessResult::allowed()
        ->addCacheableDependency($node)
        ->addCacheableDependency($account);
    }
    return AccessResult::forbidden('You cannot create from this template.')
      ->addCacheableDependency($node)
      ->addCacheableDependency($account);
  }

}

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

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