wse-1.0.x-dev/src/Form/WseWorkspaceSwitcherForm.php

src/Form/WseWorkspaceSwitcherForm.php
<?php

namespace Drupal\wse\Form;

use Drupal\Component\Datetime\TimeInterface;
use Drupal\Component\Serialization\Json;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Form\WorkspaceSafeFormInterface;
use Drupal\Core\TempStore\PrivateTempStoreFactory;
use Drupal\Core\Url;
use Drupal\workspaces\WorkspaceAccessException;
use Drupal\workspaces\WorkspaceManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Provides a form that activates a different workspace.
 */
class WseWorkspaceSwitcherForm extends FormBase implements WorkspaceSafeFormInterface {

  /**
   * Constructor.
   */
  public function __construct(
    protected readonly WorkspaceManagerInterface $workspaceManager,
    protected readonly EntityTypeManagerInterface $entityTypeManager,
    protected readonly PrivateTempStoreFactory $tempStoreFactory,
    protected readonly TimeInterface $time,
  ) {}

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('workspaces.manager'),
      $container->get('entity_type.manager'),
      $container->get('tempstore.private'),
      $container->get('datetime.time')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'wse_workspace_switcher_form';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $active_workspace = $this->workspaceManager->hasActiveWorkspace() ? $this->workspaceManager->getActiveWorkspace() : NULL;
    $form['workspace_id'] = [
      '#type' => 'select',
      '#title' => $this->t('Current workspace'),
      '#options' => $this->getWorkspaceOptions(),
      '#default_value' => $active_workspace ? $active_workspace->id() : '',
      '#attributes' => ['onchange' => 'this.form.submit();'],
    ];

    $operations = [];
    if ($active_workspace && $active_workspace->access('view')) {
      $operations['workspace_action'] = [
        'title' => $this->t('Manage workspace'),
        'url' => $active_workspace->toUrl(),
        'attributes' => [
          'class' => ['wse-action-link', 'wse-action-link--icon-cog'],
          'title' => $this->t('Manage workspace'),
        ],
      ];
    }
    elseif ($this->entityTypeManager->getAccessControlHandler('workspace')->createAccess()) {
      $operations['workspace_action'] = [
        'title' => $this->t('Add new workspace'),
        'url' => Url::fromRoute('entity.workspace.add_form', [], [
          'query' => $this->getRedirectDestination()->getAsArray(),
        ]),
        'attributes' => [
          'class' => ['wse-action-link', 'wse-action-link--icon-plus', 'use-ajax'],
          'title' => $this->t('Add new workspace'),
          'data-dialog-type' => 'modal',
          'data-dialog-options' => Json::encode([
            'width' => 700,
          ]),
        ],
      ];
    }

    $collection_url = Url::fromRoute('entity.workspace.collection');
    if ($collection_url->access()) {
      $operations['workspace_list'] = [
        'title' => $this->t('View all workspaces'),
        'url' => $collection_url,
        'attributes' => [
          'class' => ['wse-action-link', 'wse-action-link--icon-list'],
          'title' => $this->t('View all workspaces'),
        ],
      ];
    }
    $form['operations'] = [
      '#theme' => 'links__wse_action_links',
      '#links' => $operations,
      '#attributes' => [
        'class' => ['operations', 'clearfix', 'wse-action-links'],
      ],
    ];

    if ($active_workspace) {
      $status_label = wse_workspace_get_status($active_workspace);
    }
    else {
      $status_label = $this->t('Live');
    }
    $form['workspace_status'] = [
      '#type' => 'item',
      '#markup' => $this->t('Status: @status', [
        '@status' => $status_label,
      ]),
    ];

    $form['submit'] = [
      '#type' => 'submit',
      '#value' => $this->t('Activate'),
      '#button_type' => 'primary',
      '#attributes' => ['class' => ['js-hide']],
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    $id = $form_state->getValue('workspace_id');

    try {
      if ($id) {
        /** @var \Drupal\workspaces\WorkspaceInterface $workspace */
        $workspace = $this->entityTypeManager->getStorage('workspace')->load($id);

        $this->workspaceManager->setActiveWorkspace($workspace);
        $this->messenger()->addMessage($this->t('%workspace_label is now the active workspace.', ['%workspace_label' => $workspace->label()]));
      }
      else {
        $this->workspaceManager->switchToLive();
        $this->messenger()->addMessage($this->t('You are now viewing the live version of the site.'));
      }
    }
    catch (WorkspaceAccessException $e) {
      $this->messenger()->addError($this->t('You do not have access to activate the %workspace_label workspace.', ['%workspace_label' => $workspace->label()]));
    }
  }

  /**
   * Collects options for the workspace switcher widget.
   *
   * @return array
   *   The grouped workspace options, keyed by workspace ID.
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  public function getWorkspaceOptions() {
    $recent = (string) $this->t('Recent workspaces');
    $my_open = (string) $this->t('My open workspaces');
    $other_open = (string) $this->t('Other workspaces');
    $workspace_options = [
      '' => $this->t('Live'),
      $recent => [],
      $my_open => [],
      $other_open => [],
    ];

    $max_options = $this->config('wse.settings')->get('switcher_max_options') ?: NULL;
    $storage = $this->entityTypeManager->getStorage('workspace');

    $recent_workspaces = $this->getRecentWorkspaces($max_options);
    if ($recent_workspaces) {
      $workspace_options[$recent] = $recent_workspaces;

      // Return early if we've reached the limit of workspaces to display.
      if (count($recent_workspaces) == $max_options) {
        return array_filter($workspace_options);
      }
    }

    // Prepare a query that loads only open workspaces.
    $query = $storage->getQuery()
      ->accessCheck(TRUE)
      ->condition('status', WSE_STATUS_OPEN, '=');

    // Don't include recent workspaces in the results.
    if ($recent_workspaces) {
      $query->condition('id', array_keys($recent_workspaces), 'NOT IN');
    }

    // Limit the number of results if a maximum is set.
    if (!empty($max_options)) {
      $limit = $max_options - count($recent_workspaces);
      $query->range(0, $limit);
    }
    $result = $query->sort('changed', 'DESC')->execute();

    if ($result) {
      $workspaces = $storage->loadMultiple($result);
      foreach ($workspaces as $workspace_id => $workspace) {
        if ($workspace->getOwnerId() == $this->currentUser()->id()) {
          $workspace_options[$my_open][$workspace_id] = $workspace->label();
        }
        elseif ($workspace->access('view')) {
          $workspace_options[$other_open][$workspace_id] = $workspace->label();
        }
      }
    }

    return array_filter($workspace_options);
  }

  /**
   * Collects recently used workspaces, omitting closed ones.
   *
   * @param int $max_options
   *   (optional) The maximum number of workspace options to return. Defaults to
   *   NULL, which means all recent workspaces are returned.
   *
   * @return array
   *   An array of workspace labels, keyed by workspace ID.
   *
   * @throws \Drupal\Core\TempStore\TempStoreException
   */
  protected function getRecentWorkspaces($max_options = NULL) {
    $recent_ids = [];
    $options = [];

    // Add the user's recently opened workspaces to the list.
    $recent_workspaces = $this->tempStoreFactory->get('wse')->get('recent_workspaces');
    if ($recent_workspaces) {
      $recent_max_age = $this->config('wse.settings')->get('recent_workspaces_max_age') * 3600;
      foreach ($recent_workspaces as $id => $timestamp) {
        $expiration_time = $timestamp + $recent_max_age;
        // If a maximum time for expiration is configured and the workspace
        // wasn't accessed since the last access + expiration time, remove it.
        if ($recent_max_age > 0 && $expiration_time < $this->time->getRequestTime()) {
          unset($recent_workspaces[$id]);
        }
        else {
          $recent_ids[] = $id;
        }
      }

      if (!empty($max_options)) {
        $recent_ids = array_slice($recent_ids, 0, $max_options);
      }

      if ($recent_ids) {
        $workspaces = $this->entityTypeManager->getStorage('workspace')->loadMultiple($recent_ids);
        foreach ($workspaces as $id => $workspace) {
          if (wse_workspace_get_status($workspace) === WSE_STATUS_OPEN) {
            $options[$workspace->id()] = $workspace->label();
          }
          else {
            unset($recent_workspaces[$id]);
          }
        }
      }

      // Update the stored recent workspaces after possible removal done above.
      $this->tempStoreFactory->get('wse')->set('recent_workspaces', $recent_workspaces);
    }

    return $options;
  }

}

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

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