commerce_inventory-8.x-1.0-alpha6/src/Controller/InventoryRemoteIdAutocompleteController.php

src/Controller/InventoryRemoteIdAutocompleteController.php
<?php

namespace Drupal\commerce_inventory\Controller;

use Drupal\commerce_inventory\Entity\InventoryItemInterface;
use Drupal\commerce_inventory\Entity\InventoryLocationInterface;
use Drupal\commerce_inventory\InventoryHelper;
use Drupal\commerce_inventory\InventoryProviderManager;
use Drupal\Component\Utility\Crypt;
use Drupal\Component\Utility\Tags;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\KeyValueStore\KeyValueStoreInterface;
use Drupal\Core\Site\Settings;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;

/**
 * Defines a route controller for Inventory Remote ID autocomplete elements.
 */
class InventoryRemoteIdAutocompleteController extends ControllerBase implements ContainerInjectionInterface {

  /**
   * The Inventory Item entity storage.
   *
   * @var \Drupal\commerce_inventory\Entity\Storage\InventoryItemStorageInterface
   */
  protected $inventoryItemStorage;

  /**
   * The Inventory Location entity storage.
   *
   * @var \Drupal\commerce_inventory\Entity\Storage\InventoryLocationStorageInterface
   */
  protected $inventoryLocationStorage;

  /**
   * The inventory provider manager.
   *
   * @var \Drupal\commerce_inventory\InventoryProviderManager
   */
  protected $inventoryProviderManager;

  /**
   * Loaded inventory provider instances, keyed by bundle.
   *
   * @var \Drupal\commerce_inventory\Plugin\Commerce\InventoryProvider\InventoryProviderInterface[]
   */
  protected $inventoryProviders = [];

  /**
   * The key value store.
   *
   * @var \Drupal\Core\KeyValueStore\KeyValueStoreInterface
   */
  protected $keyValue;

  /**
   * Constructs a InventoryRemoteIdAutocompleteController object.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager.
   * @param \Drupal\commerce_inventory\InventoryProviderManager $inventory_provider_manager
   *   The inventory provider manager.
   * @param \Drupal\Core\KeyValueStore\KeyValueStoreInterface $key_value
   *   The key value factory.
   */
  public function __construct(EntityTypeManagerInterface $entity_type_manager, InventoryProviderManager $inventory_provider_manager, KeyValueStoreInterface $key_value) {
    $this->inventoryItemStorage = $entity_type_manager->getStorage('commerce_inventory_item');
    $this->inventoryLocationStorage = $entity_type_manager->getStorage('commerce_inventory_location');
    $this->inventoryProviderManager = $inventory_provider_manager;
    $this->keyValue = $key_value;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('entity_type.manager'),
      $container->get('plugin.manager.commerce_inventory_provider'),
      $container->get('keyvalue')->get('commerce_inventory_remote_id_autocomplete')
    );
  }

  /**
   * Loads a provider by bundle ID.
   *
   * @param string $bundle
   *   An entity's bundle ID.
   *
   * @return \Drupal\commerce_inventory\Plugin\Commerce\InventoryProvider\InventoryProviderInterface
   *   The bundle's inventory provider instance.
   */
  protected function getProvider($bundle) {
    if (!array_key_exists($bundle, $this->inventoryProviders)) {
      $this->inventoryProviders[$bundle] = $this->inventoryProviderManager->createInstance($bundle);
    }
    return $this->inventoryProviders[$bundle];
  }

  /**
   * Autocomplete the label of an entity.
   *
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   The request object that contains the typed tags.
   * @param string $provider
   *   The ID of the provider type.
   * @param string $provider_settings_key
   *   The hashed key of the key/value entry that holds the provider handler
   *   settings.
   *
   * @return \Symfony\Component\HttpFoundation\JsonResponse
   *   The matched entity labels as a JSON response.
   *
   * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
   *   Thrown if the selection settings key is not found in the key/value store
   *   or if it does not match the stored data.
   */
  public function handleAutocomplete(Request $request, $provider, $provider_settings_key) {
    $options = [];

    // Get the typed string from the URL, if it exists.
    if ($input = $request->query->get('q')) {
      $typed_string = Tags::explode($input);
      $typed_string = Unicode::strtolower(array_pop($typed_string));

      // Provider settings are passed in as a hashed key of a serialized array
      // stored in the key/value store.
      $provider_settings = $this->keyValue->get($provider_settings_key, FALSE);
      if ($provider_settings !== FALSE) {
        $provider_settings_hash = Crypt::hmacBase64(serialize($provider_settings) . $provider, Settings::getHashSalt());
        if ($provider_settings_hash !== $provider_settings_key) {
          // Disallow access when the provider settings hash does not match the
          // passed-in key.
          throw new AccessDeniedHttpException('Invalid provider settings key.');
        }
      }
      else {
        // Disallow access when the provider settings key is not found in the
        // key/value store.
        throw new AccessDeniedHttpException();
      }

      // Disallow access when host entity not passed in the provider settings.
      if (empty($provider_settings['entity'])) {
        throw new AccessDeniedHttpException('Parent entity required.');
      }

      /** @var \Drupal\Core\Entity\EntityInterface $entity */
      $entity = $provider_settings['entity'];
      unset($provider_settings['entity']);

      if ($this->inventoryProviderManager->hasDefinition($entity->bundle())) {
        $contexts = InventoryHelper::buildContexts([$entity->getEntityTypeId() => $entity]);
        $provider_options = $this->getProvider($entity->bundle())->getRemoteIdOptions($typed_string, $entity->getEntityTypeId(), $contexts);

        $remote_ids = [];
        if ($entity instanceof InventoryLocationInterface) {
          /** @var \Drupal\commerce_inventory\Entity\InventoryLocationInterface $entity */
          $remote_ids = $this->inventoryLocationStorage->getIdsByRemoteIds($entity->bundle(), array_keys($provider_options));
        }
        elseif ($entity instanceof InventoryItemInterface && $entity->getLocation() && $location_id = $entity->getLocation()->getRemoteId()) {
          $remote_ids = $this->inventoryItemStorage->getItemIdsByRemoteIds($entity->bundle(), $location_id, array_keys($provider_options));
        }

        // Don't filter the current ID.
        unset($remote_ids[$entity->getRemoteId()]);
        // Filter by IDs that haven't been used.
        $options = array_diff_key($provider_options, $remote_ids);

        array_walk($options, function (&$value, $id) {
          $value = ['value' => $id, 'label' => "$value"];
        });
        sort($options);
      }
    }

    return new JsonResponse($options);
  }

}

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

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