commerce_product_bundles-8.x-1.0/src/Service/ProductBundleVariationService.php
src/Service/ProductBundleVariationService.php
<?php
namespace Drupal\commerce_product_bundles\Service;
use Drupal\commerce\Context;
use Drupal\commerce_order\PriceCalculatorInterface;
use Drupal\commerce_price\Price;
use Drupal\commerce_price\Resolver\ChainPriceResolverInterface;
use Drupal\commerce_product\Entity\ProductVariation;
use Drupal\commerce_product\Entity\ProductVariationInterface;
use Drupal\commerce_store\CurrentStoreInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\commerce_product_bundles\Entity\ProductBundleVariation;
use Drupal\commerce_product_bundles\Entity\ProductBundleVariationInterface;
/**
* Class ProductBundleVariationService
*
* @package Drupal\commerce_product_bundles\Service
*/
class ProductBundleVariationService implements ProductBundleVariationServiceInterface {
/**
* The BundleVaritionFieldMapper.
*
* @var \Drupal\commerce_product_bundles\Service\ProductBundleVariationFieldRendererInterface
*/
protected $bundleVariationFieldMapper;
/**
* The current user.
*
* @var \Drupal\Core\Session\AccountInterface
*/
protected $currentUser;
/**
* The current store.
*
* @var \Drupal\commerce_store\CurrentStoreInterface
*/
protected $currentStore;
/**
* The chain base price resolver.
*
* @var \Drupal\commerce_price\Resolver\ChainPriceResolverInterface
*/
protected $chainPriceResolver;
/**
* The price calculator.
*
* @var \Drupal\commerce_order\PriceCalculatorInterface
*/
protected $priceCalculator;
/**
* ProductBundleVariationService constructor.
*
* @param \Drupal\commerce_product_bundles\Service\ProductBundleVariationFieldManagerInterface $bundle_variation_field_mapper
* @param \Drupal\commerce_store\CurrentStoreInterface $current_store
* @param \Drupal\Core\Session\AccountInterface $current_user
* @param \Drupal\commerce_price\Resolver\ChainPriceResolverInterface $chain_price_resolver
* @param \Drupal\commerce_order\PriceCalculatorInterface $price_calculator
*/
public function __construct(ProductBundleVariationFieldManagerInterface $bundle_variation_field_mapper, CurrentStoreInterface $current_store, AccountInterface $current_user,
ChainPriceResolverInterface $chain_price_resolver, PriceCalculatorInterface $price_calculator) {
$this->bundleVariationFieldMapper = $bundle_variation_field_mapper;
$this->currentStore = $current_store;
$this->currentUser = $current_user;
$this->chainPriceResolver = $chain_price_resolver;
$this->priceCalculator = $price_calculator;
}
/**
* {@inheritDoc}
*/
public function calculateSavings($form_values, $bundle_variation, $check_access = TRUE) {
$values = $this->getRefVariationsPrice($form_values, $bundle_variation, $check_access);
$price = $values['price'];
$variations_calculated_price = $values['variations_calculated_price'];
return $variations_calculated_price->subtract($price);
}
/**
* {@inheritDoc}
*/
public function calculateOriginalPrice($form_values, $bundle_variation) {
$values = $this->getRefVariationsPrice($form_values, $bundle_variation);
return $values['variations_calculated_price'];
}
/**
* Calculates referenced variations price.
*
* @param $form_values
* @param $bundle_variation
* @param bool $check_access
*
* @return array
*/
private function getRefVariationsPrice($form_values, $bundle_variation, $check_access = TRUE) {
// Set fallback price for add new eck -> this is for edit form only!
if($bundle_variation->isNew()){
$fallback_price = new Price(0, 'USD');
return [
'price' => $fallback_price,
'variations_calculated_price' => $fallback_price
];
}
$context = new Context($this->currentUser, $this->currentStore->getStore(), NULL, []);
// Get calculated price > include promotions.
$bundle_price = $this->priceCalculator->calculate($bundle_variation, 1, $context, ['promotion' => 'promotion']);
$price = $bundle_price->getCalculatedPrice();
$variations_calculated_price = new Price(0, $price->getCurrencyCode());
$bundle_ref_values = [];
$quantities = [];
if(isset($form_values[0]['bundle_variations_ref_options'])) {
$bundle_ref_values = $form_values[0]['bundle_variations_ref_options'];
$quantities = $form_values[0]['quantity'];
} elseif (isset($form_values[0]['bundle_variations_options'])) {
$bundle_var = ProductBundleVariation::load($form_values[0]['bundle_variations_options']);
if($bundle_var instanceof ProductBundleVariationInterface) {
$bundle_var_ref = $this->bundleVariationFieldMapper->prepareBundleVariations($bundle_variation);
// Loop through all ref product to get correct price.
if(!empty($bundle_var_ref)) {
foreach ($bundle_var_ref as $ref_key => $product_ref){
$variations_ref = $product_ref->getRefVariations();
// Select only first variation.
if(!empty($variations_ref)){
$variation_ref = reset($variations_ref);
$bundle_ref_values[$ref_key] = $variation_ref;
$quantities[$ref_key] = $product_ref->getQuantity();
}
}
}
}
} else {
$bundle_var_ref = $this->bundleVariationFieldMapper->prepareBundleVariations($bundle_variation, $check_access);
// Loop through all ref product to get correct price.
if(!empty($bundle_var_ref)) {
foreach ($bundle_var_ref as $ref_key => $product_ref) {
$variations_ref = $product_ref->getRefVariations($check_access);
// Select only first variation.
if(!empty($variations_ref)) {
$variation_ref = reset($variations_ref);
$bundle_ref_values[$ref_key] = $variation_ref;
$quantities[$ref_key] = $product_ref->getQuantity();
}
}
}
}
// Loop through selected variations.
foreach ($bundle_ref_values as $product_id => $variation_id) {
$variation = NULL;
if(is_numeric($variation_id)){
$variation = ProductVariation::load($variation_id);
} elseif($variation_id instanceof ProductVariationInterface){
// Use only first variation for calculation.
$variation = $variation_id;
}
// Double check if variation is loaded.
if($variation instanceof ProductVariationInterface) {
$variation_price = $variation->getPrice();
// Resolve price.
if ($variation_price->getCurrencyCode() !== $price->getCurrencyCode()) {
$context = new Context($this->currentUser, $this->currentStore->getStore(), NULL, []);
$variation_price = $this->chainPriceResolver->resolve($variation, 1, $context);
}
// Defaults to one.
$multiply = 1;
if (isset($quantities[$product_id])) {
$multiply = $quantities[$product_id];
}
$multiplied = $variation_price->multiply($multiply);
$variations_calculated_price = $variations_calculated_price->add($multiplied);
}
}
return [
'price' => $price,
'variations_calculated_price' => $variations_calculated_price
];
}
}
