customers_canvas-8.x-1.0-rc4/modules/commerce/src/Controller/Builder.php
modules/commerce/src/Controller/Builder.php
<?php
namespace Drupal\customers_canvas_commerce\Controller;
use Drupal\commerce_cart\CartSession;
use Drupal\commerce_cart\CartSessionInterface;
use Drupal\commerce_order\Entity\OrderItem;
use Drupal\Component\Serialization\Json;
use Drupal\Component\Utility\Html;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Session\AccountInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Component\Utility\Crypt;
use Drupal\Core\TempStore\PrivateTempStoreFactory;
/**
* Controller for Commerce-based builder.
*
* @package Drupal\customers_canvas_commerce\Controller
*/
class Builder extends ControllerBase {
/**
* The order item used to track this product.
*
* @var \Drupal\commerce_order\Entity\OrderItem
*/
protected $orderItem;
/**
* The product variation.
*
* @var \Drupal\commerce_product\Entity\ProductVariation
*/
protected $cc_entity;
/**
* The product Json.
*
* @var string
*/
protected $productJson;
/**
* The product Json.
*
* @var string
*/
protected $productJsonMulti;
/**
* The user entity.
*
* @var \Drupal\User\Entity\User
*/
protected $user;
/**
* The Customer's Canvas user ID.
*
* @var int
*/
protected $cc_user_id;
/**
* The Customer's Canvas state ID.
* @var string
*/
protected $state_id;
/**
* The cart session.
*
* @var \Drupal\commerce_cart\CartSessionInterface
*/
protected $cartSession;
/**
* The tempstore factory.
*
* @var \Drupal\user\PrivateTempStore
*/
protected $tempStore;
/**
* Constructs a new CheckoutController object.
*
* @param \Drupal\commerce_cart\CartSessionInterface $cart_session
* The cart session.
*/
public function __construct(CartSessionInterface $cart_session, PrivateTempStoreFactory $temp_store_factory) {
$this->cartSession = $cart_session;
$this->tempStore = $temp_store_factory->get('anonymous_private_temp_store');
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('commerce_cart.cart_session'),
$container->get('tempstore.private')
);
}
/**
* Display the builder for a particular user and entity.
*
* @param \Drupal\commerce_order\Entity\OrderItem $commerce_order_item
* The order item used to track this product.
*
* @return array
* Return markup render array.
*/
public function content(OrderItem $commerce_order_item) {
$this->orderItem = $commerce_order_item;
/** @var \Drupal\commerce_product\Entity\ProductVariation $cc_entity */
$this->cc_entity = $this->orderItem->getPurchasedEntity();
$product_json = $this->cc_entity->get('cc_product_json');
if (!$product_json) {
return [];
}
// Fetch the order item details.
/** @var \Drupal\commerce_order\Entity\Order $order */
$order = $this->orderItem->getOrder();
$this->user = $order->getCustomer();
$this->cc_user_id = $this->user->id();
if ($cc_result = $this->orderItem->getData('cc_result')) {
$cc_result = Json::decode($cc_result);
if (isset($cc_result['userId'])) {
$this->cc_user_id = $cc_result['userId'];
}
}
// We need to allow anonymous users to have their own unique galleries,
// so let's create a one-time id if we didn't already have one as a result.
if ($order->getCustomer()->isAnonymous() && $this->cc_user_id === $this->user->id()) {
// We need a persistent id across page loads for a single session.
// The private temp store gives us that.
$this->cc_user_id = $this->tempStore->get('cc_user_id');
if ($this->cc_user_id === NULL) {
$this->cc_user_id = Crypt::randomBytesBase64(4);
$this->tempStore->set('cc_user_id', $this->cc_user_id);
}
}
$this->state_id = $this->orderItem->get('cc_state_id')->getString();
$this->productJson = $product_json->getValue()[0]['value'];
$cc_editor_type = $this->cc_entity->get('cc_editor_type')->getValue()[0]['value'];
// Load the correct definition based on the selected color.
if ($cc_editor_type === 'multi_editor') {
$expandedProdJSON = Json::decode($this->productJson);
// @todo - Decouple business logic from module.
$key_to_use = (int) $this->orderItem->get('field_colorways')->getValue()[0]['value'];
if (!$key_to_use) {
$key_to_use = 0;
}
$this->productJson = Json::encode($expandedProdJSON[$key_to_use]);
}
if ($this->state_id !== '') {
$this->productJson = HTML::escape($this->state_id);
}
$product_json_multi = $this->cc_entity->get('cc_product_json_multi');
if ($product_json_multi && $product_json_multi->getValue()) {
$this->productJsonMulti = $product_json_multi->getValue()[0]['value'];
}
// Build the editor depending on the editor type for this product.
if (!$this->state_id && $cc_editor_type === 'multi_editor') {
return $this->returnMultiEditor();
}
return $this->returnBasicEditor();
}
/**
* Returns the necessary build info for building the basic editor content.
*
* @return array
* The build array.
*/
protected function returnMultiEditor() {
// Fetch the builder json.
$builder_json = $this->config('customers_canvas.settings')->get('multi_editor_builder_json');
// Form the product Json to add to the drupalSettings.
$product_info = [
'id' => $this->cc_entity->id(),
'sku' => $this->cc_entity->getSku(),
'name' => $this->cc_entity->getTitle(),
'description' => $this->cc_entity->getProduct()->get('body')->getValue()[0]['value'] ?: '',
'options' => [],
'price' => $this->cc_entity->getPrice()->getNumber(),
'attributes' => [
[
'id' => $this->cc_entity->id(),
'name' => 'Product Variation Type',
'value' => $this->cc_entity->bundle(),
],
],
];
// Combine the product and builder Jsons to form the config to pass to the
// drupalSettings.
$config = JSON::decode($builder_json);
foreach ($config['widgets'] as $key => $value) {
if ($value['name'] !== 'cc') {
continue;
}
$config['vars']['designs'] = Json::decode($this->productJsonMulti);
}
// Inject settings for user id.
$config['userId'] = $this->user->id();
$config = JSON::encode($config);
// Form the drupalSettings array.
$drupal_settings = [
'customersCanvas' => [
'user' => Json::encode(['id' => $this->user->id()]),
'quantity' => $this->orderItem->getQuantity(),
'url' => $this->config('customers_canvas.settings')->get('customers_canvas_url'),
'product' => JSON::encode($product_info),
'config' => $config,
],
];
return $this->returnBuild(
'customers_canvas_multi_editor_builder',
'customers_canvas/multi_editor.builder',
$drupal_settings
);
}
/**
* Returns the necessary build info for building the basic editor content.
*
* @return array
* The build array.
*/
protected function returnBasicEditor() {
// Fetch the builder json.
$builder_json = $this->config('customers_canvas.settings')->get('builder_json');
// Inject settings for user id.
$builder_json = JSON::decode($builder_json);
$builder_json['userId'] = $this->cc_user_id;
$builder_json = JSON::encode($builder_json);
// Form the drupalSettings array.
$drupal_settings = [
'customersCanvas' => [
'productJson' => $this->productJson,
'builderJson' => $builder_json,
],
];
return $this->returnBuild(
'customers_canvas_builder',
'customers_canvas/builder',
$drupal_settings
);
}
/**
* Returns a build array depending on the theme/library/settings.
*
* @param string $theme
* The theme template to use.
* @param string $library
* The library to attach.
* @param array $drupal_settings
* An array of drupalSettings to pass the library.
*
* @return array
* An array of build info.
*/
protected function returnBuild($theme, $library, $drupal_settings) {
return [
'#theme' => $theme,
'#owner' => $this->user,
'#entity' => $this->cc_entity,
'#finish_form' => $this->formBuilder()->getForm('Drupal\customers_canvas\Form\Builder', [
'cc_entity' => $this->cc_entity,
'owner' => $this->user,
'state_id' => $this->state_id,
'order_item_id' => $this->orderItem->id(),
]),
'#attached' => [
'library' => $library,
'drupalSettings' => $drupal_settings,
],
];
}
/**
* Checks access for the customer canvas page.
*
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The route match.
* @param \Drupal\Core\Session\AccountInterface $account
* The current user account.
*
* @return \Drupal\Core\Access\AccessResult
* The access result.
*
* @see \Drupal\commerce_checkout\Controller\CheckoutController::checkAccess
*/
public function checkAccess(RouteMatchInterface $route_match, AccountInterface $account) {
/** @var \Drupal\commerce_order\Entity\OrderItemInterface $order_item */
$order_item = $route_match->getParameter('commerce_order_item');
$order = $order_item->getOrder();
if ($order->getState()->getId() == 'canceled') {
return AccessResult::forbidden()->addCacheableDependency($order);
}
// The user can use customer canvas on their own non-empty orders.
if ($account->isAuthenticated()) {
$customer_check = $account->id() == $order->getCustomerId();
}
else {
$active_cart = $this->cartSession->hasCartId($order->id(), CartSession::ACTIVE);
$completed_cart = $this->cartSession->hasCartId($order->id(), CartSession::COMPLETED);
$customer_check = $active_cart || $completed_cart;
}
if (AccessResult::allowedIfHasPermission($account, 'access all customers canvas builder')->isAllowed()) {
return AccessResult::allowed();
}
$access = AccessResult::allowedIf($customer_check)
->andIf(AccessResult::allowedIf($order->hasItems()))
->andIf(AccessResult::allowedIfHasPermission($account, 'access checkout'))
->addCacheableDependency($order);
// If the user has 'access all customers canvas builder' then regardless of
// whether they have access to the order then they should be able to access
// the canvas.
return $access;
}
}
