arch-8.x-1.x-dev/modules/price/src/Negotiation/PriceNegotiation.php

modules/price/src/Negotiation/PriceNegotiation.php
<?php

namespace Drupal\arch_price\Negotiation;

use Drupal\arch_price\Plugin\Field\FieldType\PriceItemInterface;
use Drupal\arch_price\Price\PriceFactoryInterface;
use Drupal\arch_product\Entity\ProductInterface;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Session\AccountInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Price negotiation.
 *
 * @package Drupal\arch_price\Negotiation
 */
class PriceNegotiation implements PriceNegotiationInterface, ContainerInjectionInterface {

  /**
   * Current user.
   *
   * @var \Drupal\Core\Session\AccountInterface
   */
  protected $currentUser;

  /**
   * Module handler.
   *
   * @var \Drupal\Core\Extension\ModuleHandlerInterface
   */
  protected $moduleHandler;

  /**
   * Price factory.
   *
   * @var \Drupal\arch_price\Price\PriceFactoryInterface
   */
  protected $priceFactory;

  /**
   * PriceNegotiation constructor.
   *
   * @param \Drupal\Core\Session\AccountInterface $current_user
   *   Current user.
   * @param \Drupal\arch_price\Price\PriceFactoryInterface $price_factory
   *   Price factory.
   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
   *   Module handler.
   */
  public function __construct(
    AccountInterface $current_user,
    PriceFactoryInterface $price_factory,
    ModuleHandlerInterface $module_handler,
  ) {
    $this->currentUser = $current_user;
    $this->moduleHandler = $module_handler;
    $this->priceFactory = $price_factory;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('current_user'),
      $container->get('price_factory'),
      $container->get('module_handler')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function getProductPrices(ProductInterface $product) {
    /** @var \Drupal\arch_price\Plugin\Field\FieldType\PriceFieldItemList $price_field */
    $price_field = $product->get('price');
    return $price_field->getPriceList();
  }

  /**
   * {@inheritdoc}
   */
  public function getAvailablePrices(ProductInterface $product, AccountInterface $account = NULL) {
    if (!isset($account)) {
      $account = $this->currentUser;
    }

    $prices = array_filter($this->getProductPrices($product), function (PriceItemInterface $item) use ($product, $account) {
      return $this->filterAvailablePrices($item, $product, $account);
    });
    $this->moduleHandler->alter('product_available_prices', $prices, $product, $account);

    return $prices;
  }

  /**
   * {@inheritdoc}
   */
  public function getActivePrice(ProductInterface $product, AccountInterface $account = NULL) {
    if (!isset($account)) {
      $account = $this->currentUser;
    }

    $price_list = $this->getPriceList($product, $account);
    $prices = array_map(function ($item) {
      /** @var \Drupal\arch_price\Plugin\Field\FieldType\PriceItemInterface $item */
      return $item->toPrice();
    }, $price_list);

    if (empty($prices)) {
      $prices = $this->getDefaultPrices($product, $account);
    }

    /** @var \Drupal\arch_price\Price\PriceInterface $price */
    $price = current($prices);
    $context = [
      'account' => $account,
      'product' => $product,
      'prices' => $prices,
    ];
    $this->moduleHandler->alter('product_active_price', $price, $context);
    return $price;
  }

  /**
   * {@inheritdoc}
   */
  public function getOriginalPrice(ProductInterface $product, AccountInterface $account = NULL) {
    if (!isset($account)) {
      $account = $this->currentUser;
    }

    $price_list = [];

    $available_prices = array_filter($this->getProductPrices($product), function (PriceItemInterface $item) use ($product, $account) {
      return $this->filterAvailablePrices($item, $product, $account);
    });
    $price_list[] = current($available_prices);
    $prices = array_map(function ($item) {
      /** @var \Drupal\arch_price\Plugin\Field\FieldType\PriceItemInterface $item */
      return $item->toPrice();
    }, $price_list);

    if (empty($prices)) {
      $prices = $this->getDefaultPrices($product, $account);
    }

    /** @var \Drupal\arch_price\Price\PriceInterface $price */
    $price = current($prices);
    $context = [
      'account' => $account,
      'product' => $product,
      'prices' => $available_prices,
    ];
    $this->moduleHandler->alter('product_original_price', $price, $context);
    return $price;
  }

  /**
   * Get price list.
   *
   * @param \Drupal\arch_product\Entity\ProductInterface $product
   *   Product entity.
   * @param \Drupal\Core\Session\AccountInterface $account
   *   Customer.
   *
   * @return \Drupal\arch_price\Plugin\Field\FieldType\PriceItemInterface[]
   *   List of available prices.
   */
  protected function getPriceList(ProductInterface $product, AccountInterface $account) {
    // Group prices by type.
    $prices_by_type = [];
    $available_prices = $this->getAvailablePrices($product, $account);
    foreach ($available_prices as $delta => $item) {
      /** @var \Drupal\arch_price\Plugin\Field\FieldType\PriceItem $item */
      $prices_by_type[$item->getPriceTypeId()][$delta] = $item;
    }

    // Filter multiple prices by type.
    $price_list = [];
    foreach ($prices_by_type as $price_items) {
      if (count($price_items) > 1) {
        uasort($price_items, [$this, 'comparePriceItems']);
        reset($price_items);
      }
      $key = key($price_items);
      $price_list[$key] = $price_items[$key];
    }
    ksort($price_list);

    $this->moduleHandler->alter('price_negotiation_prices', $price_list, $product, $account);
    return $price_list;
  }

  /**
   * Get default prices.
   *
   * @param \Drupal\arch_product\Entity\ProductInterface $product
   *   Product entity.
   * @param \Drupal\Core\Session\AccountInterface $account
   *   Account.
   *
   * @return \Drupal\arch_price\Price\PriceInterface[]
   *   Price list.
   */
  protected function getDefaultPrices(ProductInterface $product, AccountInterface $account) {
    $prices = [
      $this->priceFactory->getMissingPriceInstance(),
    ];
    $this->moduleHandler->alter('price_negotiation_empty_price_list', $prices, $product, $account);
    return $prices;
  }

  /**
   * List filter callback.
   *
   * @param \Drupal\arch_price\Plugin\Field\FieldType\PriceItemInterface $item
   *   Price item.
   * @param \Drupal\arch_product\Entity\ProductInterface $product
   *   Product.
   * @param \Drupal\Core\Session\AccountInterface $account
   *   User.
   *
   * @return bool
   *   Return TRUE if given price is available for given user.
   */
  protected function filterAvailablePrices(PriceItemInterface $item, ProductInterface $product, AccountInterface $account) {
    // Exclude if price is not available at this time.
    if (!$item->isAvailable()) {
      return FALSE;
    }

    $priceType = $item->getPriceType();
    if (empty($priceType)) {
      return FALSE;
    }

    // Exclude if type of price is not available.
    $type_access = $priceType->access('view', $account, TRUE);
    if ($type_access->isForbidden()) {
      return FALSE;
    }

    // Get modules response.
    $result = AccessResult::allowedIf($item->isAvailable());
    $access_results = $this->moduleHandler->invokeAll('price_access', [
      $item,
      $product,
      $account,
    ]);
    foreach ($access_results as $access) {
      $result->andIf($access);
    }

    // Allow only if not forbidden.
    return !$result->isForbidden();
  }

  /**
   * Uasort callback.
   *
   * @param \Drupal\arch_price\Plugin\Field\FieldType\PriceItemInterface $a
   *   Price A.
   * @param \Drupal\arch_price\Plugin\Field\FieldType\PriceItemInterface $b
   *   Price B.
   *
   * @return int
   *   Compare result.
   */
  protected static function comparePriceItems(PriceItemInterface $a, PriceItemInterface $b) {
    $a_full_limit = $a->getAvailableFrom() && $a->getAvailableTo();
    $b_full_limit = $b->getAvailableFrom() && $b->getAvailableTo();
    if ($a_full_limit && !$b_full_limit) {
      return -1;
    }
    if (!$a_full_limit && $b_full_limit) {
      return 1;
    }

    $a_default = !$a->getAvailableFrom() && !$a->getAvailableTo();
    $b_default = !$b->getAvailableFrom() && !$b->getAvailableTo();
    if ($a_default && !$b_default) {
      return 1;
    }
    if (!$a_default && $b_default) {
      return -1;
    }

    if ($a->getAvailableFrom() !== $b->getAvailableFrom()) {
      return $a->getAvailableFrom() < $b->getAvailableFrom() ? -1 : 1;
    }
    if ($a->getAvailableTo() !== $b->getAvailableTo()) {
      return $a->getAvailableTo() < $b->getAvailableTo() ? -1 : 1;
    }

    return 0;
  }

}

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

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