commerce_product_bundles-8.x-1.0/src/Plugin/Field/FieldWidget/BundleVariationPriceWidget.php
src/Plugin/Field/FieldWidget/BundleVariationPriceWidget.php
<?php
namespace Drupal\commerce_product_bundles\Plugin\Field\FieldWidget;
use CommerceGuys\Intl\Formatter\CurrencyFormatterInterface;
use Drupal\commerce\Context;
use Drupal\commerce_order\AdjustmentTypeManager;
use Drupal\commerce_order\PriceCalculatorInterface;
use Drupal\commerce_order\PriceCalculatorResult;
use Drupal\commerce_store\CurrentStoreInterface;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Field\EntityReferenceFieldItemList;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\WidgetBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\commerce_product_bundles\Entity\ProductBundleVariation;
use Drupal\commerce_product_bundles\Service\ProductBundleVariationServiceInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RequestStack;
/**
* Plugin implementation of the 'bundle_variation_price' widget.
*
* This is not widget but 'Formatter' to display bundle price in bundle variation form.
*
* @FieldWidget(
* id = "bundle_variation_price",
* label = @Translation("Bundle variation price"),
* field_types = {
* "commerce_price",
* }
* )
*/
class BundleVariationPriceWidget extends WidgetBase implements ContainerFactoryPluginInterface {
/**
* The adjustment type manager.
*
* @var \Drupal\commerce_order\AdjustmentTypeManager
*/
protected $adjustmentTypeManager;
/**
* The current user.
*
* @var \Drupal\Core\Session\AccountInterface
*/
protected $currentUser;
/**
* The current store.
*
* @var \Drupal\commerce_store\CurrentStoreInterface
*/
protected $currentStore;
/**
* The price calculator.
*
* @var \Drupal\commerce_order\PriceCalculatorInterface
*/
protected $priceCalculator;
/**
* The currency formatter.
*
* @var \CommerceGuys\Intl\Formatter\CurrencyFormatterInterface
*/
protected $currencyFormatter;
/**
* The commerce product bundle service.
*
* @var \Drupal\commerce_product_bundles\service\ProductBundleVariationServiceInterface
*/
protected $commerceProductBundleService;
/**
* The module handler.
*
* @var \Drupal\Core\Extension\ModuleHandlerInterface
*/
protected $moduleHandler;
/**
* @var \Drupal\Core\Entity\EntityTypeManager|\Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* Request stack service.
*
* @var RequestStack
*/
protected $requestStack;
/**
* BundleVariationPriceWidget constructor.
*
* @param $plugin_id
* @param $plugin_definition
* @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
* @param array $settings
* @param array $third_party_settings
* @param \CommerceGuys\Intl\Formatter\CurrencyFormatterInterface $currency_formatter
* @param \Drupal\commerce_order\AdjustmentTypeManager $adjustment_type_manager
* @param \Drupal\commerce_store\CurrentStoreInterface $current_store
* @param \Drupal\Core\Session\AccountInterface $current_user
* @param \Drupal\commerce_order\PriceCalculatorInterface $price_calculator
* @param \Drupal\commerce_product_bundles\Service\ProductBundleVariationServiceInterface $commerce_product_bundles_service
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
*/
public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings,
CurrencyFormatterInterface $currency_formatter, AdjustmentTypeManager $adjustment_type_manager,
CurrentStoreInterface $current_store, AccountInterface $current_user, PriceCalculatorInterface $price_calculator,
ProductBundleVariationServiceInterface $commerce_product_bundles_service, ModuleHandlerInterface $module_handler,
EntityTypeManagerInterface $entity_type_manager, RequestStack $request_stack) {
parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings);
$this->currencyFormatter = $currency_formatter;
$this->adjustmentTypeManager = $adjustment_type_manager;
$this->currentStore = $current_store;
$this->currentUser = $current_user;
$this->priceCalculator = $price_calculator;
$this->commerceProductBundleService = $commerce_product_bundles_service;
$this->moduleHandler = $module_handler;
$this->entityTypeManager = $entity_type_manager;
$this->requestStack = $request_stack;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$plugin_id,
$plugin_definition,
$configuration['field_definition'],
$configuration['settings'],
$configuration['third_party_settings'],
$container->get('commerce_price.currency_formatter'),
$container->get('plugin.manager.commerce_adjustment_type'),
$container->get('commerce_store.current_store'),
$container->get('current_user'),
$container->get('commerce_order.price_calculator'),
$container->get('commerce_product_bundles.bundle_variation_service'),
$container->get('module_handler'),
$container->get('entity_type.manager'),
$container->get('request_stack')
);
}
/**
* {@inheritdoc}
*/
public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
$element = [];
/** @var \Drupal\commerce_order\Entity\OrderItemInterface $order_item */
$order_item = $items[$delta]->getEntity();
// Get storage.
$storage = $form_state->getStorage();
if (!$items[$delta]->isEmpty()) {
if ($order_item->getFields()['purchased_entity'] instanceof EntityReferenceFieldItemList) {
$variation_id = $storage['selected_bundle_variation'] ?? '';
// Get all data.
$bundle_variation_id = !empty($variation_id) ? $variation_id : $order_item->getFields()['purchased_entity']->getString();
$bundle_variation = ProductBundleVariation::load($bundle_variation_id);
$context = new Context($this->currentUser, $this->currentStore->getStore(), NULL, []);
/** @var \Drupal\commerce\PurchasableEntityInterface $purchasable_entity */
$purchasable_entity = $bundle_variation;
// Get calculated price > include promotions.
$result = $this->priceCalculator->calculate($purchasable_entity, 1, $context, ['promotion' => 'promotion']);
$calculated_price = $result->getCalculatedPrice();
$base_price = $result->getBasePrice();
$number = $calculated_price->getNumber();
$base_number = $result->getBasePrice()->getNumber();
$currency_code = $calculated_price->getCurrencyCode();
$options = $this->getFormattingOptions();
$markup = [
'#theme' => 'commerce_bundle_bundle_price_calculated',
'#result' => $result,
'#calculated_price' => $this->currencyFormatter->format($number, $currency_code, $options),
'#base_price' => $this->currencyFormatter->format($base_number, $currency_code, $options),
'#adjustments' => $result->getAdjustments(),
'#cache' => [
'tags' => $purchasable_entity->getCacheTags(),
'contexts' => Cache::mergeContexts($purchasable_entity->getCacheContexts(), [
'languages:' . LanguageInterface::TYPE_INTERFACE,
'country',
]),
],
];
// Set bundle price tpl..
$element = [
'#theme' => 'commerce_bundle_price_calculated',
'#bundle_price' => $markup,
'#original_price' => NULL,
'#savings_price' => NULL
];
// Get original price.
$purchased_entity = [];
$selected_vars = $form_state->getValue('purchased_entity');
if(empty($selected_vars)) {
$user_input = $form_state->getUserInput();
$selected_vars = isset($user_input['purchased_entity']) ? $user_input['purchased_entity'] : NULL;
}
if(isset($selected_vars[0]['bundle_variations_ref_options']) && !empty($selected_vars[0]['bundle_variations_ref_options'])){
$purchased_entity[0]['bundle_variations_ref_options'] = $selected_vars[0]['bundle_variations_ref_options'] ?? '';
}
if(isset($selected_vars[0]['quantity']) && !empty($selected_vars[0]['quantity'])){
$purchased_entity[0]['quantity'] = $selected_vars[0]['quantity'] ?? '';
}
// Show original price only if we do not have discount on bundle.
if(!$base_price->greaterThan($calculated_price)){
$calculated_original_value = $this->commerceProductBundleService->calculateOriginalPrice($purchased_entity, $bundle_variation);
// Show original price only if it is greater than bundle price.
if($calculated_original_value->greaterThan($calculated_price)){
$calculated_price_result = new PriceCalculatorResult($calculated_original_value, $calculated_original_value);
$cal_original_price = $calculated_price_result->getCalculatedPrice();
$cal_original_number = $cal_original_price->getNumber();
$calc_base_number = $calculated_price_result->getBasePrice()->getNumber();
$calc_currency_code = $cal_original_price->getCurrencyCode();
$original_price_markup = [
'#theme' => 'commerce_original_price_calculated',
'#result' => $calculated_price_result,
'#calculated_price' => $this->currencyFormatter->format($cal_original_number, $calc_currency_code, $options),
'#base_price' => $this->currencyFormatter->format($calc_base_number, $calc_currency_code, $options),
'#adjustments' => $calculated_price_result->getAdjustments(),
'#cache' => [
'tags' => $purchasable_entity->getCacheTags(),
'contexts' => Cache::mergeContexts($purchasable_entity->getCacheContexts(), [
'languages:' . LanguageInterface::TYPE_INTERFACE,
'country',
]),
],
];
$element['#original_price'] = $original_price_markup;
}
}
// Calculate savings price.
$savings = $this->commerceProductBundleService->calculateSavings($selected_vars, $bundle_variation);
// Show savings only if it is higher that 0.
if($savings->isPositive() && !$savings->isZero()) {
$calculated_savings_result = new PriceCalculatorResult($savings, $savings);
$cal_savings_price = $calculated_savings_result->getCalculatedPrice();
$cal_savings_original_number = $cal_savings_price->getNumber();
$calc_savings_base_number = $calculated_savings_result->getBasePrice()->getNumber();
$calc_savings_currency_code = $cal_savings_price->getCurrencyCode();
$savings_price_markup = [
'#theme' => 'commerce_savings_price_calculated',
'#result' => $calculated_savings_result,
'#calculated_price' => $this->currencyFormatter->format($cal_savings_original_number, $calc_savings_currency_code, $options),
'#base_price' => $this->currencyFormatter->format($calc_savings_base_number, $calc_savings_currency_code, $options),
'#adjustments' => $calculated_savings_result->getAdjustments(),
'#cache' => [
'tags' => $purchasable_entity->getCacheTags(),
'contexts' => Cache::mergeContexts($purchasable_entity->getCacheContexts(), [
'languages:' . LanguageInterface::TYPE_INTERFACE,
'country',
]),
],
];
$element['#savings_price'] = $savings_price_markup;
}
}
}
return $element;
}
/**
* Gets the formatting options for the currency formatter.
*
* @return array
* The formatting options.
*/
protected function getFormattingOptions() {
return [
'currency_display' => 'symbol',
'minimum_fraction_digits' => 0,
];
}
/**
* {@inheritdoc}
*/
public static function isApplicable(FieldDefinitionInterface $field_definition) {
$entity_type = $field_definition->getTargetEntityTypeId();
$field_name = $field_definition->getName();
return $entity_type === 'commerce_order_item' && $field_name === 'unit_price';
}
}
