acquia_commercemanager-8.x-1.122/modules/acm_checkout/src/Controller/CheckoutController.php
modules/acm_checkout/src/Controller/CheckoutController.php
<?php
namespace Drupal\acm_checkout\Controller;
use Drupal\acm\Response\NeedsRedirectException;
use Drupal\acm_cart\CartStorageInterface;
use Drupal\acm_checkout\Ajax\PaneFormCommand;
use Drupal\acm_checkout\Ajax\PaneFormRedirectCommand;
use Drupal\acm_checkout\Ajax\PaneFormSavedCommand;
use Drupal\acm_checkout\Ajax\PaneFormValidationErrorsCommand;
use Drupal\acm_checkout\Ajax\PaneFormValidationErrorsFieldsCommand;
use Drupal\Component\Plugin\PluginManagerInterface;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\Core\Form\FormState;
use Drupal\Core\Render\RendererInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Url;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
/**
* Provides the checkout form page.
*
* @todo: Redirect to cart if cart is empty.
*/
class CheckoutController extends ControllerBase {
/**
* The form builder.
*
* @var \Drupal\Core\Form\FormBuilderInterface
*/
protected $formBuilder;
/**
* The form builder.
*
* @var \Drupal\Core\Render\RendererInterface
*/
protected $renderer;
/**
* The config object.
*
* @var \Drupal\Core\Config\ConfigFactoryInterface
*/
protected $config;
/**
* The checkout flow plugin manager.
*
* @var \Drupal\Component\Plugin\PluginManagerInterface
*/
protected $acmCheckoutFlowManager;
/**
* The cart session.
*
* @var \Drupal\acm_cart\CartStorageInterface
*/
protected $cartStorage;
/**
* Constructs a new CheckoutController object.
*
* @param \Drupal\Core\Form\FormBuilderInterface $form_builder
* The form builder.
* @param \Drupal\Core\Render\RendererInterface $renderer
* The renderer.
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* The factory for configuration objects.
* @param \Drupal\Component\Plugin\PluginManagerInterface $acm_checkout_flow_manager
* The checkout flow manager.
* @param \Drupal\acm_cart\CartStorageInterface $cart_storage
* The cart session.
*/
public function __construct(FormBuilderInterface $form_builder, RendererInterface $renderer, ConfigFactoryInterface $config_factory, PluginManagerInterface $acm_checkout_flow_manager, CartStorageInterface $cart_storage) {
$this->formBuilder = $form_builder;
$this->renderer = $renderer;
$this->config = $config_factory->get('acm_checkout.settings');
$this->acmCheckoutFlowManager = $acm_checkout_flow_manager;
$this->cartStorage = $cart_storage;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('form_builder'),
$container->get('renderer'),
$container->get('config.factory'),
$container->get('plugin.manager.acm_checkout_flow'),
$container->get('acm_cart.cart_storage')
);
}
/**
* Builds and processes the form provided by the order's checkout flow.
*
* @param \Symfony\Component\HttpFoundation\Request $request
* The current request object.
*
* @return array
* The render form.
*/
public function formPage(Request $request) {
if (!$this->config->get('use_ajax')) {
$form_state = new FormState();
$plugin = $this->loadCheckoutFlowPlugin();
$form = $this->formBuilder->buildForm($plugin, $form_state);
return $form;
}
return [
'#attributes' => ['id' => 'acm_checkout_wrapper'],
'#attached' => [
'library' => ['acm_checkout/single_page_checkout'],
'drupalSettings' => [
'acm_checkout' => [
'cartPath' => Url::fromRoute('acm_checkout.form')->toString(),
'ajaxCartPath' => Url::fromRoute('acm_checkout.ajax_form')->toString(),
],
],
],
];
}
/**
* Builds and processes the form provided by the order's checkout flow.
*
* @param \Symfony\Component\HttpFoundation\Request $request
* The current request object.
*
* @return Drupal\Core\Ajax\AjaxResponse
* The form.
*/
public function ajaxFormPage(Request $request) {
$response = new AjaxResponse();
try {
$plugin = $this->loadCheckoutFlowPlugin();
}
catch (NeedsRedirectException $e) {
// If someone tries access a step that isn't available yet, they get
// redirected to the last available step. So catch the exception and tell
// the Javascript app where to go.
$response->addCommand(new PaneFormRedirectCommand($e->getRedirectUrl()));
return $response;
}
$form_state = (new FormState())
->disableRedirect();
$form = $this->formBuilder->buildForm($plugin, $form_state);
if ($form_state->isExecuted()) {
// Form is saved without errors, so return the url of the next checkout
// step.
$next_page = Url::fromRoute('acm_checkout.form', [
'step' => $plugin->getNextStepId(),
])->toString();
$response->addCommand(new PaneFormSavedCommand($next_page));
}
else {
$output = $this->renderer->renderRoot($form);
if ($request->request->get('nocssjs') !== 'true') {
$response->setAttachments($form['#attached']);
}
else {
// Libraries we always want attached.
$attached = [];
$attached['library'] = [
'core/drupal.states',
'core/drupal.ajax',
];
$attached['drupalSettings'] = $form['#attached']['drupalSettings'];
$response->setAttachments($attached);
}
$response->addCommand(new PaneFormCommand($output));
$errors = $form_state->getErrors();
if (count($errors)) {
$status_messages = [
'#type' => 'status_messages',
];
$response->addCommand(new PaneFormValidationErrorsCommand($this->renderer->renderRoot($status_messages)));
$response->addCommand(new PaneFormValidationErrorsFieldsCommand(array_keys($errors)));
}
}
return $response;
}
/**
* Checks access for the form page.
*
* @param \Drupal\Core\Session\AccountInterface $account
* The current user account.
*
* @return \Drupal\Core\Access\AccessResult
* The access result.
*/
public function checkAccess(AccountInterface $account) {
$cart = $this->cartStorage;
if (empty($cart) || $cart->isEmpty()) {
return AccessResult::forbidden('Invalid cart');
}
return AccessResult::allowedIfHasPermission($account, 'access checkout');
}
/**
* Loads the configured CheckoutFlow plugin.
*
* @return object
* An instance of the CheckoutFlow plugin.
*/
protected function loadCheckoutFlowPlugin() {
$checkoutFlowPlugin = $this->config->get('checkout_flow_plugin') ?: 'multistep_default';
return $this->acmCheckoutFlowManager->createInstance($checkoutFlowPlugin, ['validate_current_step' => TRUE]);
}
}
