contacts_events-8.x-1.x-dev/src/Commands/PriceDebugCommands.php

src/Commands/PriceDebugCommands.php
<?php

namespace Drupal\contacts_events\Commands;

use CommerceGuys\Intl\Formatter\CurrencyFormatterInterface;
use Drupal\commerce_order\Entity\OrderItemInterface;
use Drupal\contacts_events\Entity\EventClassInterface;
use Drupal\contacts_events\Entity\SingleUsePurchasableEntityInterface;
use Drupal\contacts_events\PriceCalculator;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drush\Commands\DrushCommands;
use Symfony\Component\Console\Helper\Table;

/**
 * Contacts Events debugging command file.
 */
class PriceDebugCommands extends DrushCommands {

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

  /**
   * The price calculator.
   *
   * @var \Drupal\contacts_events\PriceCalculator
   */
  protected $calculator;

  /**
   * The currency formatter.
   *
   * @var \CommerceGuys\Intl\Formatter\CurrencyFormatterInterface
   */
  protected $formatter;

  /**
   * DebugCommands constructor.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager.
   * @param \Drupal\contacts_events\PriceCalculator $calculator
   *   The price calculator.
   * @param \CommerceGuys\Intl\Formatter\CurrencyFormatterInterface $formatter
   *   The currency formatter.
   */
  public function __construct(EntityTypeManagerInterface $entity_type_manager, PriceCalculator $calculator, CurrencyFormatterInterface $formatter) {
    parent::__construct();
    $this->entityTypeManager = $entity_type_manager;
    $this->calculator = $calculator;
    $this->formatter = $formatter;
  }

  /**
   * Debug price recalculation for a booking.
   *
   * @param int $order_id
   *   The Order ID.
   * @param array $options
   *   An associative array of options whose values come from cli, aliases,
   *   config, etc.
   *
   * @usage contacts_events-commandName 50
   *   Debug the price recalculation for booking 50.
   *
   * @command events:debug:recalc
   *
   * @return int
   *   Exit code.
   */
  public function recalculate(int $order_id, array $options = ['option-name' => 'default']): int {
    /** @var \Drupal\commerce_order\Entity\OrderInterface|null $order */
    $order = $this->entityTypeManager
      ->getStorage('commerce_order')
      ->load($order_id);

    if (!$order) {
      $this->io()->error("Unable to load order {$order_id}.");
      return 1;
    }

    $this->io()->title("Debugging price recalculation for {$order->label()} [$order_id]");

    // Get the class and window labels.
    $classes = array_map(function (EventClassInterface $class) {
      return $class->label();
    }, $this->entityTypeManager->getStorage('contacts_events_class')->loadMultiple());

    $windows = [];
    foreach ($order->get('event')->entity->get('booking_windows') as $window) {
      $windows[$window->id] = $window->label;
    }

    // Build our table.
    $table = new Table($this->io());
    $table->setHeaders([
      'Item ID',
      'Type',
      'Purchased Entity',
      'Label',
      'Status',
      'Class before',
      'Window before',
      'Price before',
      'Class after',
      'Window after',
      'Price after',
    ]);

    // Loop over the items and add to the table.
    foreach ($order->getItems() as $item) {
      $row = [
        'id' => $item->id(),
        'type' => $item->bundle(),
        'purchased' => $item->getPurchasedEntityId(),
        'label' => $item->label(),
        'state' => $item->hasField('state') ? $item->get('state')->first()->getLabel() : '',
        'class_before' => '',
        'window_before' => '',
        'price_before' => '',
        'class_after' => '',
        'window_after' => '',
        'price_after' => '',
      ];
      $this->addItemMappingInfo($row, $item, 'before', $classes, $windows);

      // Recalculate the item for the 'after' version.
      $this->calculator->calculatePrice($item);
      $this->addItemMappingInfo($row, $item, 'after', $classes, $windows);

      $table->addRow($row);
    }
    $table->render();

    return 0;
  }

  /**
   * Add the mapping and price info for an item.
   *
   * @param array $row
   *   The row to add to.
   * @param \Drupal\commerce_order\Entity\OrderItemInterface $item
   *   The order item.
   * @param string $col_suffix
   *   The column suffix, either 'before' or 'after'.
   * @param array $classes
   *   The map of class IDs to labels.
   * @param array $windows
   *   The map of window IDs to labels.
   */
  protected function addItemMappingInfo(array &$row, OrderItemInterface $item, string $col_suffix, array $classes, array $windows) {
    // Get the mapping.
    if ($purchased_entity = $item->get('purchased_entity')->entity) {
      if ($purchased_entity instanceof SingleUsePurchasableEntityInterface) {
        $mapping = $purchased_entity->getMappedPrice();
      }
    }
    // Otherwise see if we can get it from the order item.
    if (!isset($mapping) && $item->hasField('mapped_price')) {
      $mapped_price_items = $item->get('mapped_price');
      if ($mapped_price_items->count()) {
        $mapping = $mapped_price_items->first()->getValue();
      }
    }

    // If we have mapping, add the details.
    if (isset($mapping)) {
      $row["class_{$col_suffix}"] = $classes[$mapping['class']] ?? $mapping['class'];
      if ($mapping['class_overridden']) {
        $row["class_{$col_suffix}"] .= '*';
      }

      $row["window_{$col_suffix}"] = $windows[$mapping['booking_window']] ?? $mapping['booking_window'];
      if ($mapping['booking_window_overridden']) {
        $row["window_{$col_suffix}"] .= '*';
      }
    }

    // If we have a price, add it to the row.
    if ($price = $item->getTotalPrice()) {
      $row["price_{$col_suffix}"] = $this->formatter->format($price->getNumber(), $price->getCurrencyCode());
    }
  }

}

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

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