TempStoreTrait.php

Namespace

Drupal\rules\Ui

File

src/Ui/TempStoreTrait.php

View source
<?php

namespace Drupal\rules\Ui;

use Drupal\Core\Datetime\DateFormatterInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\TempStore\SharedTempStoreFactory;
use Drupal\Core\Url;

/**
 * Provides methods for modified rules components in temporary storage.
 *
 * Note that this implements the lock-related methods of
 * \Drupal\rules\Ui\RulesUiHandlerInterface.
 *
 * @see \Drupal\rules\Ui\RulesUiHandlerInterface
 * @see \Drupal\rules\Ui\RulesUiConfigHandler
 */
trait TempStoreTrait {
    
    /**
     * The tempstore factory.
     *
     * @var \Drupal\Core\TempStore\SharedTempStoreFactory
     */
    protected $tempStoreFactory;
    
    /**
     * The temporary store for the rules component.
     *
     * @var \Drupal\Core\TempStore\SharedTempStore
     */
    protected $tempStore;
    
    /**
     * The currently active rules UI handler.
     *
     * @var \Drupal\rules\Ui\RulesUiHandlerInterface
     */
    protected $rulesUiHandler;
    
    /**
     * The date formatter service.
     *
     * @var \Drupal\Core\Datetime\DateFormatterInterface
     */
    protected $dateFormatter;
    
    /**
     * The renderer service.
     *
     * @var \Drupal\Core\Render\RendererInterface
     */
    protected $renderer;
    
    /**
     * The entity type manager service.
     *
     * @var \Drupal\Core\Entity\EntityTypeManagerInterface
     */
    protected $entityTypeManager;
    
    /**
     * Retrieves the renderer service if not already present.
     *
     * @return \Drupal\Core\Render\RendererInterface
     *   The renderer service.
     */
    public function getRenderer() {
        if (!isset($this->renderer)) {
            $this->renderer = \Drupal::service('renderer');
        }
        return $this->renderer;
    }
    
    /**
     * Retrieves the temporary storage service if not already present.
     *
     * @return \Drupal\Core\TempStore\SharedTempStoreFactory
     *   The factory.
     */
    protected function getTempStoreFactory() {
        if (!isset($this->tempStoreFactory)) {
            $this->tempStoreFactory = \Drupal::service('tempstore.shared');
        }
        return $this->tempStoreFactory;
    }
    
    /**
     * Setter injection for the temporary storage factory.
     *
     * @param \Drupal\Core\TempStore\SharedTempStoreFactory $temp_store_factory
     *   The factory.
     *
     * @return $this
     */
    public function setTempStoreFactory(SharedTempStoreFactory $temp_store_factory) {
        $this->tempStoreFactory = $temp_store_factory;
        return $this;
    }
    
    /**
     * Retrieves the date formatter service if not already present.
     *
     * @return \Drupal\Core\Datetime\DateFormatterInterface
     *   The service.
     */
    protected function getDateFormatter() {
        if (!isset($this->dateFormatter)) {
            $this->dateFormatter = \Drupal::service('date.formatter');
        }
        return $this->dateFormatter;
    }
    
    /**
     * Setter injection for the date formatter service.
     *
     * @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
     *   The service.
     *
     * @return $this
     */
    public function setDateFormatter(DateFormatterInterface $date_formatter) {
        $this->dateFormatter = $date_formatter;
        return $this;
    }
    
    /**
     * Retrieves the entity type manager service if not already present.
     *
     * @return \Drupal\Core\Entity\EntityTypeManagerInterface
     *   The entity type manager.
     */
    protected function getEntityTypeManager() {
        if (!isset($this->entityTypeManager)) {
            $this->entityTypeManager = \Drupal::service('entity_type.manager');
        }
        return $this->entityTypeManager;
    }
    
    /**
     * Gets the currently active RulesUI's handler.
     *
     * @return \Drupal\rules\Ui\RulesUiHandlerInterface
     *   The RulesUI handler.
     */
    protected function getRulesUiHandler() {
        // Usually the trait is used on the RulesUI handler.
        return $this;
    }
    
    /**
     * Fetches the stored data from the temporary storage.
     *
     * @return mixed|null
     *   The stored data or NULL if the temp store is empty.
     */
    protected function fetchFromTempStore() {
        return $this->getTempStore()
            ->get($this->getTempStoreItemId());
    }
    
    /**
     * Stores some data in the temporary storage.
     *
     * @param mixed $data
     *   The data to store.
     */
    protected function storeToTempStore($data) {
        $this->getTempStore()
            ->set($this->getTempStoreItemId(), $data);
    }
    
    /**
     * @see \Drupal\rules\Ui\RulesUiHandlerInterface::clearTemporaryStorage()
     */
    public function clearTemporaryStorage() {
        $this->getTempStore()
            ->delete($this->getTempStoreItemId());
    }
    
    /**
     * @see \Drupal\rules\Ui\RulesUiHandlerInterface::isLocked()
     */
    public function isLocked() {
        // If there is an object in the temporary storage from another user then
        // this component is locked.
        if ($this->getTempStore()
            ->get($this->getTempStoreItemId()) && !$this->getTempStore()
            ->getIfOwner($this->getTempStoreItemId())) {
            return TRUE;
        }
        return FALSE;
    }
    
    /**
     * Generates the temp store item's ID to use for the edited component.
     *
     * @return string
     *   The temp store ID.
     */
    private function getTempStoreItemId() {
        // The internal path is unique for the currently edited component.
        return $this->getRulesUiHandler()
            ->getBaseRouteUrl()
            ->getInternalPath();
    }
    
    /**
     * Gets the temporary storage repository from the factory.
     *
     * @return \Drupal\Core\TempStore\SharedTempStore
     *   The shared storage.
     */
    private function getTempStore() {
        if (!isset($this->tempStore)) {
            $this->tempStore = $this->getTempStoreFactory()
                ->get($this->getRulesUiHandler()
                ->getPluginId());
        }
        return $this->tempStore;
    }
    
    /**
     * @see \Drupal\rules\Ui\RulesUiHandlerInterface::getLockMetaData()
     */
    public function getLockMetaData() {
        return $this->getTempStore()
            ->getMetadata($this->getTempStoreItemId());
    }
    
    /**
     * @see \Drupal\rules\Ui\RulesUiHandlerInterface::isEdited()
     */
    public function isEdited() {
        if ($this->getTempStore()
            ->get($this->getTempStoreItemId())) {
            return TRUE;
        }
        return FALSE;
    }
    
    /**
     * @see \Drupal\rules\Ui\RulesUiHandlerInterface::addLockInformation()
     */
    public function addLockInformation() {
        $build = [];
        if ($this->isLocked()) {
            $build['locked'] = [
                '#type' => 'container',
                '#attributes' => [
                    'class' => [
                        'rules-locked',
                        'messages',
                        'messages--warning',
                    ],
                ],
                '#children' => $this->lockInformationMessage(),
                '#weight' => -10,
            ];
        }
        else {
            $build['changed'] = [
                '#type' => 'container',
                '#attributes' => [
                    'class' => [
                        'rules-changed',
                        'messages',
                        'messages--warning',
                    ],
                ],
                '#children' => $this->t('You have unsaved changes.'),
                '#weight' => -10,
            ];
            if (!$this->isEdited()) {
                $build['changed']['#attributes']['class'][] = 'js-hide';
            }
        }
        return $build;
    }
    
    /**
     * @see \Drupal\rules\Ui\RulesUiHandlerInterface::validateLock()
     */
    public function validateLock(array &$form, FormStateInterface $form_state) {
        if ($this->isLocked()) {
            $form_state->setErrorByName('locked', $this->lockInformationMessage());
        }
    }
    
    /**
     * Provides a lock info message.
     *
     * @return \Drupal\Core\StringTranslation\TranslatableMarkup
     *   The message suitable to be shown in the UI.
     */
    private function lockInformationMessage() {
        $lock = $this->getLockMetaData();
        $username = [
            '#theme' => 'username',
            '#account' => $this->getEntityTypeManager()
                ->getStorage('user')
                ->load($lock->getOwnerId()),
        ];
        $lock_message_substitutions = [
            '@user' => $this->getRenderer()
                ->render($username),
            '@age' => $this->getDateFormatter()
                ->formatTimeDiffSince($lock->getUpdated()),
            '@component_type' => $this->getRulesUiHandler()
                ->getPluginDefinition()->component_type_label,
            ':url' => Url::fromRoute($this->getRulesUiHandler()
                ->getPluginDefinition()->base_route . '.break_lock', \Drupal::routeMatch()->getRawParameters()
                ->all())
                ->toString(),
        ];
        return $this->t('This @component_type is being edited by user @user, and is therefore locked from editing by others. This lock is @age old. Click here to <a href=":url">break this lock</a>.', $lock_message_substitutions);
    }

}

Traits

Title Deprecated Summary
TempStoreTrait Provides methods for modified rules components in temporary storage.