contacts-8.x-1.x-dev/src/ContactsTabManager.php

src/ContactsTabManager.php
<?php

namespace Drupal\contacts;

use Drupal\Component\Plugin\Exception\ContextException;
use Drupal\Core\Block\BlockManager;
use Drupal\Core\Block\BlockPluginInterface;
use Drupal\Core\Entity\EntityTypeManager;
use Drupal\Core\Plugin\Context\Context;
use Drupal\Core\Plugin\Context\ContextDefinition;
use Drupal\Core\Plugin\Context\ContextHandlerInterface;
use Drupal\Core\Plugin\Context\EntityContextDefinition;
use Drupal\Core\Plugin\ContextAwarePluginInterface;
use Drupal\Core\Session\AccountProxy;
use Drupal\Core\TempStore\PrivateTempStoreFactory;
use Drupal\contacts\Entity\ContactTabInterface;
use Drupal\ctools\Plugin\RelationshipManagerInterface;
use Drupal\user\UserInterface;
use Symfony\Component\HttpFoundation\RequestStack;

/**
 * The contact tabs manager.
 */
class ContactsTabManager implements ContactsTabManagerInterface {

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManager
   */
  protected $entityTypeManager;

  /**
   * The block plugin manager.
   *
   * @var \Drupal\Core\Block\BlockManager
   */
  protected $blockManager;

  /**
   * The context handler.
   *
   * @var \Drupal\Core\Plugin\Context\ContextHandlerInterface
   */
  protected $contextHandler;

  /**
   * The relationship manager.
   *
   * @var \Drupal\ctools\Plugin\RelationshipManagerInterface
   */
  protected $relationshipManager;

  /**
   * The current user.
   *
   * @var \Drupal\Core\Session\AccountProxy
   */
  protected $currentUser;

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

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

  /**
   * Array of verified block IDs.
   *
   * @var array
   */
  protected array $verifiedBlocks = [];

  /**
   * Construct the tabs manager service.
   *
   * @param \Drupal\Core\Entity\EntityTypeManager $entity_type_manager
   *   The entity type manager.
   * @param \Drupal\Core\Block\BlockManager $block_manager
   *   The block plugin manager.
   * @param \Drupal\Core\Plugin\Context\ContextHandlerInterface $context_handler
   *   The context handler.
   * @param \Drupal\ctools\Plugin\RelationshipManagerInterface $relationship_manager
   *   The relationship manager.
   * @param \Drupal\Core\Session\AccountProxy $current_user
   *   The current user.
   * @param \Drupal\Core\TempStore\PrivateTempStoreFactory $tempstore
   *   The private tempstore.
   * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
   *   The request statck.
   */
  public function __construct(EntityTypeManager $entity_type_manager, BlockManager $block_manager, ContextHandlerInterface $context_handler, RelationshipManagerInterface $relationship_manager, AccountProxy $current_user, PrivateTempStoreFactory $tempstore, RequestStack $request_stack) {
    $this->entityTypeManager = $entity_type_manager;
    $this->blockManager = $block_manager;
    $this->contextHandler = $context_handler;
    $this->relationshipManager = $relationship_manager;
    $this->currentUser = $current_user;
    $this->tempstore = $tempstore;
    $this->requestStack = $request_stack;
  }

  /**
   * {@inheritdoc}
   */
  public function getTab($id) {
    return $this->entityTypeManager->getStorage('contact_tab')->load($id);
  }

  /**
   * {@inheritdoc}
   */
  public function getTabByPath($path) {
    $tabs = $this->entityTypeManager->getStorage('contact_tab')->loadByProperties(['path' => $path]);

    if (!empty($tabs)) {
      $tab = reset($tabs);
      return $tab;
    }

    return NULL;
  }

  /**
   * {@inheritdoc}
   */
  public function getTabs(?UserInterface $contact = NULL) {
    // Load all our active tabs.
    /** @var \Drupal\contacts\Entity\ContactTabInterface[] $tabs */
    $tabs = $this->entityTypeManager->getStorage('contact_tab')->loadByProperties(['status' => TRUE]);
    if (empty($tabs)) {
      return [];
    }

    // If provided verify tabs against user.
    if ($contact !== NULL) {
      foreach ($tabs as $key => $tab) {
        if (!$this->verifyTab($tab, $contact)) {
          unset($tabs[$key]);
        }
      }
    }

    // Sort our tabs by weight.
    $entity_type = $this->entityTypeManager->getDefinition('contact_tab');
    uasort($tabs, [$entity_type->getClass(), 'sort']);

    // Return our tabs.
    return $tabs;
  }

  /**
   * {@inheritdoc}
   */
  public function getBlocks(ContactTabInterface $tab, ?UserInterface $contact = NULL) {
    $blocks = $tab->getBlockPlugins();
    if (empty($blocks)) {
      // Get our block plugin, applying context if relevant..
      $block_configurations = $tab->getBlocks() ?: [];

      $blocks = [];
      foreach ($block_configurations as $key => $block_configuration) {
        /** @var \Drupal\Core\Block\BlockPluginInterface $block */
        $block = $this->blockManager->createInstance($block_configuration['id'], $block_configuration);
        $blocks[$key] = $block;
      }
    }

    if ($contact !== NULL) {
      $this->applyBlockContext($tab, $blocks, $contact);
    }

    $tab->setBlockPlugins($blocks);

    return $blocks;
  }

  /**
   * Apply block plugin context requirements.
   *
   * Where contexts are not able to be matched, blocks will be removed from tab.
   *
   * @param \Drupal\contacts\Entity\ContactTabInterface $tab
   *   The tab entity the blocks are on.
   * @param \Drupal\Core\Block\BlockPluginInterface[] $blocks
   *   Blocks to apply the contexts to.
   * @param \Drupal\user\UserInterface $contact
   *   The contact we are applying contexts for.
   */
  protected function applyBlockContext(ContactTabInterface $tab, array &$blocks, UserInterface $contact) {
    // Apply context to our block plugins if relevant.
    foreach ($blocks as $key => &$block) {
      /** @var \Drupal\Core\Block\BlockPluginInterface $block */
      if ($block instanceof ContextAwarePluginInterface) {
        try {
          $contexts = $this->getContexts($tab, $contact);

          // Apply the mappings.
          $this->contextHandler->applyContextMapping($block, $contexts);
        }
        catch (ContextException $exception) {
          unset($blocks[$key]);
          continue;
        }
      }
    }
  }

  /**
   * Apply context mapping to block configuration.
   *
   * @param \Drupal\contacts\Entity\ContactTabInterface $tab
   *   The tab entity the blocks are on.
   * @param \Drupal\Core\Block\BlockPluginInterface $block
   *   Blocks to apply the contexts to.
   */
  public function buildBlockContextMapping(ContactTabInterface $tab, BlockPluginInterface $block) {
    $relationships = $tab->getRelationships();

    $definition = $block->getPluginDefinition();
    $conf = $block->getConfiguration();

    if (empty($definition['_tab_relationships'])) {
      return;
    }

    foreach ($definition['_tab_relationships'] as $source => $contexts) {
      foreach ($contexts as $label => $context) {
        if (!isset($relationships[$context])) {
          $relationships[$context] = [
            'id' => "typed_data_entity_relationship:entity:{$source}:{$context}",
            'name' => $context,
            'source' => $source,
          ];
        }

        $conf['context_mapping'][$label] = $context;
      }
    }

    // @todo Check if it needs user.
    $conf['context_mapping']['user'] = 'user';

    $tab->setRelationships($relationships);
    $block->setConfiguration($conf);
  }

  /**
   * Gets a list of tabs that have a block in them.
   *
   * @param string $block_id
   *   The id of the block being searched for.
   *
   * @return array
   *   Array of tab labels keyed by tab id.
   */
  public function getTabsWithBlock($block_id) {
    $tabs = $this->getTabs();

    $found = [];
    foreach ($tabs as $id => $tab) {
      $blocks = $this->getBlocks($tab);

      foreach ($blocks as $block) {
        if ($block->getPluginId() == $block_id) {
          $found[$id] = $tab->label();
        }
      }
    }

    return $found;
  }

  /**
   * {@inheritdoc}
   */
  public function verifyTab(ContactTabInterface $tab, UserInterface $contact) {
    // Check if tab should be shown for contact roles.
    if (!empty($tab_roles = $tab->getRoles())) {
      $contact_roles = $contact->getRoles();
      if (empty(array_intersect($tab_roles, $contact_roles))) {
        return FALSE;
      }
    }

    $blocks = $this->getBlocks($tab, $contact);

    if (empty($blocks)) {
      return FALSE;
    }

    // Make sure each block is verified and capture if any have.
    foreach ($blocks as $block) {
      /** @var \Drupal\Core\Block\BlockPluginInterface $block */

      if (!isset($this->verifiedBlocks[$block->getPluginId()])) {
        // Check access on the block.
        if (!$block->access($this->currentUser)) {
          $this->verifiedBlocks[$block->getPluginId()] = FALSE;
          continue;
        }

        // @todo Add additional checks...
        $this->verifiedBlocks[$block->getPluginId()] = TRUE;
      }
    }

    // Once verified, only store verified blocks on tab.
    $blocks = array_filter($blocks, function ($block) {
      return $this->verifiedBlocks[$block->getPluginId()] ?? FALSE;
    });
    $tab->setBlockPlugins($blocks);

    return !empty($blocks);
  }

  /**
   * {@inheritdoc}
   */
  public function getContexts(ContactTabInterface $tab, ?UserInterface $contact = NULL): array {
    // Build our contexts.
    $contexts = [
      'user' => new Context(EntityContextDefinition::fromEntityTypeId('user'), $contact),
      'subpage' => new Context(new ContextDefinition('string'), $tab->getPath()),
    ];

    // Gather any relationships.
    foreach ($tab->getRelationships() as $relationship) {
      if (isset($contexts[$relationship['source']])) {
        /** @var \Drupal\ctools\Plugin\RelationshipInterface $plugin */
        $plugin = $this->relationshipManager->createInstance($relationship['id']);
        $plugin->setContext('base', $contexts[$relationship['source']]);
        $contexts[$relationship['name']] = $plugin->getRelationship();
      }
    }
    return $contexts;
  }

}

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

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