commerce_product_bundles-8.x-1.0/src/Plugin/Field/FieldWidget/ProductBundleVariationWidget.php
src/Plugin/Field/FieldWidget/ProductBundleVariationWidget.php
<?php
namespace Drupal\commerce_product_bundles\Plugin\Field\FieldWidget;
use Drupal\commerce_product\ProductAttributeFieldManagerInterface;
use Drupal\commerce_product\ProductVariationAttributeMapperInterface;
use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Entity\EntityRepositoryInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\commerce_product_bundles\Entity\ProductBundleVariation;
use Drupal\commerce_product_bundles\Service\ProductBundleVariationFieldManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Plugin implementation of the 'commerce_product_bundles_variation' widget.
*
* @FieldWidget(
* id = "commerce_product_bundles_variation",
* label = @Translation("Product bundle variation"),
* field_types = {
* "entity_reference"
* }
* )
*/
class ProductBundleVariationWidget extends ProductBundleVariationWidgetBase implements ContainerFactoryPluginInterface {
/**
* @var \Drupal\commerce_product_bundles\Service\ProductBundleVariationFieldRendererInterface
*/
protected $bundleVariationFieldMapper;
/**
* The product attribute field manager.
*
* @var \Drupal\commerce_product\ProductAttributeFieldManagerInterface
*/
protected $attributeFieldManager;
/**
* The product variation attribute mapper.
*
* @var \Drupal\commerce_product\ProductVariationAttributeMapperInterface
*/
protected $variationAttributeMapper;
/**
* ProductBundleVariationWidget constructor.
*
* @param $plugin_id
* @param $plugin_definition
* @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
* @param array $settings
* @param array $third_party_settings
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository
* @param \Drupal\commerce_product_bundles\Service\ProductBundleVariationFieldManagerInterface $bundle_variation_field_mapper
* @param \Drupal\commerce_product\ProductAttributeFieldManagerInterface $attribute_field_manager
* @param \Drupal\commerce_product\ProductVariationAttributeMapperInterface $variation_attribute_mapper
*
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
*/
public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings,
EntityTypeManagerInterface $entity_type_manager, EntityRepositoryInterface $entity_repository,
ProductBundleVariationFieldManagerInterface $bundle_variation_field_mapper, ProductAttributeFieldManagerInterface $attribute_field_manager, ProductVariationAttributeMapperInterface $variation_attribute_mapper) {
parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings, $entity_type_manager, $entity_repository);
$this->bundleVariationFieldMapper = $bundle_variation_field_mapper;
$this->attributeFieldManager = $attribute_field_manager;
$this->variationAttributeMapper = $variation_attribute_mapper;
}
/**
* {@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('entity_type.manager'),
$container->get('entity.repository'),
$container->get('commerce_product_bundles.bundle_variation_mapper'),
$container->get('commerce_product.attribute_field_manager'),
$container->get('commerce_product.variation_attribute_mapper')
);
}
/**
* {@inheritdoc}
*/
public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
/** @var \Drupal\commerce_product_bundles\Entity\ProductBundleInterface $product_bundle */
$product_bundle = $form_state->get('product_bundle');
$bundle_variations = $this->loadEnabledVariations($product_bundle);
// Build the full variation form.
$wrapper_id = Html::getUniqueId('commerce-product-add-to-cart-bundle-form');
$form += [
'#wrapper_id' => $wrapper_id,
'#prefix' => '<div id="' . $wrapper_id . '">',
'#suffix' => '</div>',
];
// If an operation caused the form to rebuild, select the variation from
// the user's current input.
$selected_variation = NULL;
if ($form_state->isRebuilding()) {
$parents = array_merge($element['#field_parents'], [$items->getName(), $delta, 'bundle_variations_options']);
$bundle_variation_id = (array) NestedArray::getValue($form_state->getUserInput(), $parents);
if(!empty($bundle_variation_id)){
$selected_variation = ProductBundleVariation::load(reset($bundle_variation_id));
}
}
// Otherwise fallback to the default.
if (!$selected_variation) {
/** @var \Drupal\commerce_order\Entity\OrderItemInterface $order_item */
$order_item = $items->getEntity();
if ($order_item->isNew()) {
$selected_variation = $this->getDefaultBundleVariation($product_bundle, $bundle_variations);
} else {
$selected_variation = $order_item->getPurchasedEntity();
}
}
$element['bundle_variation'] = [
'#type' => 'value',
'#value' => $selected_variation->id(),
];
// Set the selected variation in the form state for our AJAX callback.
$form_state->set('selected_bundle_variation', $selected_variation->id());
$element['bundle_variations_options'] = [
'#type' => 'container',
'#attributes' => [
'class' => ['bundle-variation-widgets'],
],
];
$options = [];
foreach ($bundle_variations as $variation_id => $bundle_variation) {
$options[$variation_id] = $bundle_variation->label();
}
// Default bundle variation will be set as default.
$bundle_variations_element = [
'#type' => 'commerce_product_bundles_rendered',
'#title' => $product_bundle->label(),
'#options' => $options,
'#required' => TRUE,
'#default_value' => $selected_variation->id(),
'#limit_validation_errors' => [],
'#ajax' => [
'callback' => [get_class($this), 'ajaxRefresh'],
'wrapper' => $form['#wrapper_id'],
// Prevent a jump to the top of the page.
'disable-refocus' => TRUE
],
];
// Convert the _none option into #empty_value.
if (isset($bundle_variations_element['#options']['_none'])) {
if (!$bundle_variations_element['#required']) {
$bundle_variations_element['#empty_value'] = '';
}
unset($bundle_variations_element['#options']['_none']);
}
if (empty($bundle_variations_element['#options'])) {
$bundle_variations_element['#access'] = FALSE;
}
$element['bundle_variations_options'] = $bundle_variations_element;
//// Referenced Variation widget /////
// Generate referenced products widget.
$element['bundle_variations_ref_options'] = [
'#type' => 'container',
'#attributes' => [
'class' => [
'bundle-variation-select--' . $product_bundle->bundle()
],
]
];
// Generate referenced products widget.
$element['quantity'] = [
'#type' => 'container'
];
// Loop through all ref. variations and display widget.
foreach ($this->bundleVariationFieldMapper->prepareBundleVariations($selected_variation) as $ref_product_id => $bundle_variation) {
$default_value = $bundle_variation->getDefaultProductVariation(TRUE);
$bundle_variation_element = [
'#type' => 'bundle_ref_default_variations_rendered',
'#theme_wrappers' => ['bundle_ref_default_select_wrapper'],
'#title' => $bundle_variation->getLabel(),
'#refItems' => $bundle_variation->getRefVariations(),
'#quantity' => $bundle_variation->getQuantity(),
'#required' => TRUE,
'#attribute_title' => NULL,
'#options' => [],
'#limit_validation_errors' => [],
'#ajax' => [
'callback' => [get_class($this), 'ajaxRefresh'],
'wrapper' => $form['#wrapper_id'],
// Prevent a jump to the top of the page.
'disable-refocus' => TRUE,
],
];
$element['bundle_variations_ref_options'][$ref_product_id] = $bundle_variation_element;
// Set quantity value.
$element['quantity'][$ref_product_id] = [
'#type' => 'hidden',
'#value' => $bundle_variation->getQuantity()
];
// Set ref. variations default value.
$element['bundle_variations_ref_options'][$ref_product_id]['#default_value'] = $default_value;
}
return $element;
}
/**
* {@inheritdoc}
*/
public function massageFormValues(array $values, array $form, FormStateInterface $form_state) {
/** @var \Drupal\commerce_product_bundles\Entity\ProductBundleInterface $product_bundle */
$product_bundle = $form_state->get('product_bundle');
$default_variation = $product_bundle->getDefaultVariation();
foreach ($values as $key => &$value) {
$bundle_variations = isset($value['bundle_variations_options']) ? $value['bundle_variations_options'] : [];
if ($bundle_variations) {
$value['bundle_variation'] = $bundle_variations;
}
else {
$value['bundle_variation'] = $default_variation->id();
}
}
return parent::massageFormValues($values, $form, $form_state);
}
}
