delivery-8.x-1.x-dev/modules/workspaces_negotiator_path/src/PathPrefixWorkspaceNegotiator.php

modules/workspaces_negotiator_path/src/PathPrefixWorkspaceNegotiator.php
<?php

namespace Drupal\workspaces_negotiator_path;

use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Logger\LoggerChannelInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\TempStore\PrivateTempStoreFactory;
use Drupal\Core\TempStore\TempStoreException;
use Drupal\workspaces\Negotiator\WorkspaceNegotiatorInterface;
use Drupal\workspaces\WorkspaceAccessException;
use Drupal\workspaces\WorkspaceInterface;
use Drupal\workspaces_negotiator_path\Utils\PathPrefixHelper;
use Symfony\Component\HttpFoundation\Request;

/**
 *
 */
class PathPrefixWorkspaceNegotiator implements WorkspaceNegotiatorInterface {

  /**
   * The name of the private temp store.
   *
   * @var string
   */
  static $STORE = 'workspaces_negotiator_path';

  /**
   * The name of the key in the tempstore.
   *
   * @var string
   */
  static $KEY = 'new_workspace';

  /**
   * The workspace storage handler.
   *
   * @var \Drupal\Core\Entity\EntityStorageInterface
   */
  protected $workspaceStorage;

  /**
   * @var \Drupal\Core\TempStore\PrivateTempStore
   */
  protected $tempStore;

  /**
   * The workspaces' logger channel.
   *
   * @var \Drupal\Core\Logger\LoggerChannelInterface
   */
  protected $logger;

  /**
   * The messenger service.
   *
   * @var \Drupal\Core\Messenger\MessengerInterface
   */
  protected $messenger;

  /**
   * Return the path prefix for a given workspace, without the leading slash.
   *
   * @param \Drupal\workspaces\WorkspaceInterface $workspace
   *   The given workspace.
   * @param bool $stripSlash
   *   Whether to remove the leading slash. Defaults to false.
   *
   * @return string|NULL
   */
  public static function getPrefix(WorkspaceInterface $workspace, $stripSlash = FALSE) {
    $prefix = trim($workspace->get('path_prefix')->value);
    if ($stripSlash) {
      $prefix = substr($prefix, 1);
    }
    return $prefix;
  }

  /**
   * Constructor.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager.
   * @param \Drupal\Core\TempStore\PrivateTempStoreFactory $tempStoreFactory
   *   The temp store factory.
   * @param \Drupal\Core\Logger\LoggerChannelInterface $logger
   *   The workspaces' logger channel.
   * @param \Drupal\Core\Messenger\MessengerInterface $messenger
   *   The messenger service.
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  public function __construct(EntityTypeManagerInterface $entity_type_manager, PrivateTempStoreFactory $tempStoreFactory, LoggerChannelInterface $logger, MessengerInterface $messenger) {
    $this->workspaceStorage = $entity_type_manager->getStorage('workspace');
    $this->tempStore = $tempStoreFactory->get(self::$STORE);
    $this->logger = $logger;
    $this->messenger = $messenger;
  }

  /**
   * {@inheritdoc}
   */
  public function applies(Request $request) {
    return TRUE;
  }

  /**
   * {@inheritdoc}
   */
  public function getActiveWorkspace(Request $request) {
    $valid_workspaces = array_map(function (WorkspaceInterface $workspace) {
      return [
        'id' => $workspace->id(),
        'path_prefix' => self::getPrefix($workspace),
      ];
    }, $this->getValidWorkspaces());
    $best_fit = PathPrefixHelper::findBestPathPrefixFit(urldecode($request->getPathInfo()), $valid_workspaces);
    if (!empty($best_fit)) {
      if ($best_fit['id'] && ($workspace = $this->workspaceStorage->load($best_fit['id']))) {
        return $workspace;
      }
    }
    return NULL;
  }

  /**
   * {@inheritdoc}
   */
  public function setActiveWorkspace(WorkspaceInterface $workspace) {
    $prefix = self::getPrefix($workspace, TRUE);
    if ($prefix === FALSE) {
      $message = 'The @name workspace doesn\'t have any path prefix set and thus is inactive.';
      $replacements = ['@name' => $workspace->label()];
      $this->messenger->addError(new TranslatableMarkup($message, $replacements));
      throw new WorkspaceAccessException();
    } else {
      $this->setRedirectPrefix($prefix);
    }
  }

  /**
   * {@inheritdoc}
   */
  public function unsetActiveWorkspace() {
      $this->deleteRedirectPrefix();
  }

  /**
   * Returns an array with all the workspaces which should be checked by the
   * path prefix negotiator.
   */
  protected function getValidWorkspaces() {
    $workspaces = $this->workspaceStorage->loadMultiple();
    return array_filter($workspaces, function ($workspace) {
      // Remove the workspaces which have an empty path_prefix field.
      $path_prefix = self::getPrefix($workspace);
      return !empty($path_prefix);
    });
  }

  /**
   * Returns the prefix of the workspace that is being activated.
   *
   * @return string|NULL
   *   The new workspace's prefix, without the leading slash.
   *
   * @see \Drupal\workspaces_negotiator_path\EventSubscriber\WorkspaceRedirectSubscriber::checkRedirection()
   */
  public function getRedirectPrefix() {
    return $this->tempStore->get(self::$KEY);
  }

  /**
   * Sets the redirect prefix.
   *
   * @param string $prefix
   *   The workspace prefix to set, without the leading slash.
   */
  public function setRedirectPrefix($prefix) {
    try {
      $this->tempStore->set(self::$KEY, $prefix);
    } catch (TempStoreException $e) {
      $this->logger->error('Could not save the redirection item to the tempstore.');
    }
  }

  /**
   * Clears the prefix, used when the redirection has taken place.
   *
   * @see \Drupal\workspaces_negotiator_path\EventSubscriber\WorkspaceRedirectSubscriber::checkRedirection()
   */
  public function deleteRedirectPrefix() {
    try {
      $this->tempStore->delete(self::$KEY);
    } catch (TempStoreException $e) {
      $this->logger->error('Could not delete the redirection item from the tempstore.');
    }
  }

  /**
   * Returns the given path without any workspace prefix.
   *
   * @param string $path
   *   The path as returned by parse_url, i.e. with the leading slash.
   *
   * @return string
   *   The path with workspace prefix stripped, starting with a slash.
   */
  public function stripWorkspacePrefix($path) {
    $pathParts = explode('/', $path);

    if (empty($pathParts)) {
      return '';
    }

    /** @var \Drupal\workspaces\WorkspaceInterface $workspace */
    foreach ($this->getValidWorkspaces() as $workspace) {
      $prefix = self::getPrefix($workspace, TRUE);

      // Default workspaces don't have any prefix so there's nothing to strip.
      if (empty($prefix)) {
        continue;
      }

      if ($pathParts[1] === $prefix) {
        unset($pathParts[1]);
        break;
      }
    }

    // The path can consist solely of the workspace prefix which's been unset.
    if (empty($pathParts)) {
      return '';
    }

    return implode('/', $pathParts);
  }

}

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

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