arch-8.x-1.x-dev/modules/checkout/src/Controller/CheckoutController.php

modules/checkout/src/Controller/CheckoutController.php
<?php

namespace Drupal\arch_checkout\Controller;

use Drupal\arch_cart\Cart\CartHandlerInterface;
use Drupal\arch_checkout\CheckoutType\CheckoutTypeManagerInterface;
use Drupal\arch_checkout\CheckoutType\CheckoutTypePluginInterface;
use Drupal\arch_checkout\CheckoutType\Exception\CheckoutTypeException;
use Drupal\arch_checkout\Services\CheckoutCompletePageAccess;
use Drupal\arch_order\Entity\OrderInterface;
use Drupal\arch_order\Services\OrderStatusService;
use Drupal\arch_payment\PaymentMethodManagerInterface;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\PageCache\ResponsePolicy\KillSwitch;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Theme\ThemeManagerInterface;
use Drupal\Core\Url;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;

/**
 * Checkout page controller.
 *
 * @package Drupal\arch_checkout\Controller
 */
class CheckoutController extends ControllerBase implements ContainerInjectionInterface {

  /**
   * Checkout Type manager.
   *
   * @var \Drupal\arch_checkout\CheckoutType\CheckoutTypeManagerInterface
   */
  protected $checkoutTypeManager;

  /**
   * Payment method manager.
   *
   * @var \Drupal\arch_payment\PaymentMethodManagerInterface
   */
  protected $paymentMethodManager;

  /**
   * The page cache kill switch service.
   *
   * @var \Drupal\Core\PageCache\ResponsePolicy\KillSwitch
   */
  protected $pageCacheKillSwitch;

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

  /**
   * Theme manager.
   *
   * @var \Drupal\Core\Theme\ThemeManagerInterface
   */
  protected $themeManager;

  /**
   * Cart.
   *
   * @var \Drupal\arch_cart\Cart\CartInterface
   */
  protected $cart;

  /**
   * Order status service.
   *
   * @var \Drupal\arch_order\Services\OrderStatusService
   */
  protected $orderStatus;

  /**
   * Checkout complete page access checker service.
   *
   * @var \Drupal\arch_checkout\Services\CheckoutCompletePageAccess
   */
  protected $checkoutCompletePageAccess;

  /**
   * CheckoutController constructor.
   *
   * @param \Drupal\arch_cart\Cart\CartHandlerInterface $cart_handler
   *   Cart handler.
   * @param \Drupal\arch_checkout\CheckoutType\CheckoutTypeManagerInterface $checkout_type_manager
   *   The checkout type manager.
   * @param \Drupal\arch_payment\PaymentMethodManagerInterface $payment_method_manager
   *   Payment manager.
   * @param \Drupal\Core\PageCache\ResponsePolicy\KillSwitch $kill_switch
   *   Page cache kill switch service.
   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
   *   Module handler.
   * @param \Drupal\Core\Theme\ThemeManagerInterface $theme_manager
   *   Theme manager.
   * @param \Drupal\arch_order\Services\OrderStatusService $order_status
   *   Order status service.
   * @param \Drupal\arch_checkout\Services\CheckoutCompletePageAccess $checkoutCompletePageAccess
   *   Checkout complete page access checker service.
   */
  public function __construct(
    CartHandlerInterface $cart_handler,
    CheckoutTypeManagerInterface $checkout_type_manager,
    PaymentMethodManagerInterface $payment_method_manager,
    KillSwitch $kill_switch,
    ModuleHandlerInterface $module_handler,
    ThemeManagerInterface $theme_manager,
    OrderStatusService $order_status,
    CheckoutCompletePageAccess $checkoutCompletePageAccess,
  ) {
    $this->cart = $cart_handler->getCart();
    $this->checkoutTypeManager = $checkout_type_manager;
    $this->paymentMethodManager = $payment_method_manager;
    $this->pageCacheKillSwitch = $kill_switch;
    $this->moduleHandler = $module_handler;
    $this->themeManager = $theme_manager;
    $this->orderStatus = $order_status;
    $this->checkoutCompletePageAccess = $checkoutCompletePageAccess;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('arch_cart_handler'),
      $container->get('plugin.manager.checkout_type'),
      $container->get('plugin.manager.payment_method'),
      $container->get('page_cache_kill_switch'),
      $container->get('module_handler'),
      $container->get('theme.manager'),
      $container->get('order.statuses'),
      $container->get('arch_checkout.checkout_complete_page.access')
    );
  }

  /**
   * Access callback.
   *
   * @param \Drupal\Core\Session\AccountInterface $account
   *   Run access checks for this account.
   *
   * @return \Drupal\Core\Access\AccessResult
   *   Result.
   */
  public function checkoutAccess(AccountInterface $account) {
    if (
      $account->isAnonymous()
      && !$this->checkoutTypeManager->isAnonymousCheckoutAllowed()
    ) {
      $reason = $this->t(
        'Please <a href="@register_url">create an account</a> or <a href="@login_url">sign in</a> to checkout!',
        [
          '@register_url' => Url::fromRoute('user.register')->toString(),
          '@login_url' => Url::fromRoute('user.login')->toString(),
        ],
        ['context' => 'arch_checkout']
      );
      $this->messenger()->addError($reason);
      return AccessResult::forbidden((string) $reason);
    }

    return AccessResult::allowedIfHasPermission($account, 'access content');
  }

  /**
   * Checkout page handler.
   *
   * @return array|\Symfony\Component\HttpFoundation\RedirectResponse
   *   Redirect response or render array.
   *
   * @throws \Drupal\Component\Plugin\Exception\PluginException
   */
  public function checkout() {
    if (
      !$this->cart->hasProduct()
      && $this->checkoutTypeManager->shouldRedirectIfCartEmpty()
    ) {
      return $this->redirect('arch_cart.content');
    }

    try {
      $default_plugin = $this->checkoutTypeManager->getDefaultCheckoutType();

      // Let other modules alterate the selected plugin for checkout page.
      $this->moduleHandler->alter('checkout_plugin', $default_plugin, $this->checkoutTypeManager);
    }
    catch (CheckoutTypeException $ce) {
      $this->getLogger('Checkout')->error($ce->getMessage());
      $this->messenger()->addError('Sorry, something went wrong during processing your request. Please contact site admin if it is persist.');
      return $this->redirect('<front>');
    }

    if (empty($default_plugin)) {
      $this->getLogger('Checkout')->error('No default checkout type is set.');
      $this->messenger()->addError('Sorry, something went wrong during processing your request. Please contact site admin if it is persist.');
      return $this->redirect('<front>');
    }

    /** @var \Drupal\arch_checkout\CheckoutType\CheckoutTypePluginInterface $plugin */
    $plugin = $this->checkoutTypeManager->createInstance($default_plugin['id'], []);
    if (!($plugin instanceof CheckoutTypePluginInterface)) {
      $this->getLogger('Checkout')->error('The default checkout type which is set is not implements the required interface.');
      $this->messenger()->addError('Sorry, something went wrong during processing your request. Please contact site admin if it is persist.');
      return $this->redirect('<front>');
    }

    $form = $plugin->build();
    $form['#cache']['contexts'][] = 'user';
    $form['#cache']['contexts'][] = 'session';
    $form['#cache']['max-age'] = 0;

    // Let modules alterate the output.
    $this->moduleHandler->alter('checkout_page', $form, $plugin);
    $this->themeManager->alter('checkout_page', $form, $plugin);

    return $form;
  }

  /**
   * Page title callback for complete page.
   *
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   Request object.
   *
   * @return \Drupal\Core\StringTranslation\TranslatableMarkup
   *   Page title.
   */
  public function completeTitle(Request $request) {
    /** @var \Drupal\arch_order\Entity\Order $order */
    $order = $request->get('order_id');
    $title = $this->t('Thank you for your purchase!', [], ['context' => 'arch_checkout']);

    // Let modules alterate the title.
    $this->moduleHandler->alter('checkout_complete_page_title', $title, $order);

    return $title;
  }

  /**
   * Checkout complete action.
   *
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   Request object.
   *
   * @return array|\Symfony\Component\HttpFoundation\RedirectResponse
   *   Complete page content.
   *
   * @throws \Drupal\Component\Plugin\Exception\PluginException
   * @throws \Drupal\Core\Entity\EntityStorageException
   */
  public function complete(Request $request) {
    /** @var \Drupal\arch_order\Entity\Order $order */
    $order = $request->get('order_id');

    if ($order->getOwner()->getEmail() !== $this->currentUser()->getEmail()) {
      if ($this->currentUser()->isAuthenticated()) {
        throw new AccessDeniedHttpException();
      }
      elseif (!$this->checkoutTypeManager->isAnonymousCheckoutAllowed()) {
        throw new AccessDeniedHttpException();
      }
    }

    if (!$this->checkoutCompletePageAccess->canAccess($order)) {
      return $this->redirect('<front>');
    }

    // Make sure we will not see a cached checkout complete page.
    $this->pageCacheKillSwitch->trigger();

    $payment_method = NULL;
    $payment_method_id = $order->get('payment_method')->getString();
    if (!empty($payment_method_id)) {
      /** @var \Drupal\arch_payment\PaymentMethodInterface $payment_method */
      $payment_method = $this->paymentMethodManager->createInstance($payment_method_id);
    }

    // Make it possible to Payment Methods alterate the output.
    $checkout_complete_info = NULL;
    if ($payment_method instanceof CheckoutCompleteInterface) {
      $checkout_complete_info = $payment_method->checkoutCompleteInfo($order);
    }

    $output = [
      '#theme' => 'arch_checkout_complete',
      '#order' => $order,
      '#message' => $this->t('We have received your order, and we are getting it ready.', [], ['context' => 'arch_checkout']),
      '#message_extra' => $this->t('You will receive a confirmation e-mail shortly.', [], ['context' => 'arch_checkout']),
      '#checkout_complete_info' => $checkout_complete_info,
    ];

    // Let modules alterate the output.
    $this->moduleHandler->alter('checkout_complete_page', $output, $order);
    $this->themeManager->alter('checkout_complete_page', $output, $order);

    /** @var \Drupal\arch_order\Entity\OrderStatusInterface[] $orderStatuses */
    $orderStatuses = $this->orderStatus->getOrderStatuses();

    $new_status = 'completed';
    $this->moduleHandler->alter('checkout_complete_order_status', $new_status, $order);
    if (!in_array($new_status, array_keys($orderStatuses))) {
      $new_status = 'completed';
    }

    if (
      $order->get('status')->getString() != 'completed'
      && $this->shouldChangeOrderStatusToCompleted($order)
    ) {
      $order->setNewRevision();
      $order->setRevisionUserId($this->currentUser()->id());
      $order->setRevisionLogMessage('Order status has changed from "' . $order->get('status')->getString() . '" to "' . $new_status . '".');
      $order->setRevisionCreationTime(time());

      // Complete order.
      $order->set('status', $new_status);

      // Update order.
      $order->save();

      $this->moduleHandler->invokeAll('checkout_completed', [$order]);
      $this->moduleHandler->alter('checkout_completed_page', $output, $order);
      $this->themeManager->alter('checkout_completed_page', $output, $order);
    }

    // Reset cart.
    $this->cart->resetStore();

    return $output;
  }

  /**
   * Check we should update order status to "complete".
   *
   * @param \Drupal\arch_order\Entity\OrderInterface $order
   *   Order to change.
   *
   * @return bool
   *   Return TRUE of order status change is not disallowed.
   */
  protected function shouldChangeOrderStatusToCompleted(OrderInterface $order) {
    $result = $this->moduleHandler->invokeAll('checkout_complete_page_should_update_order_status', [
      $order,
    ]);
    return !in_array(FALSE, $result, TRUE);
  }

}

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

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