Assume product custom attribute called “country_price”
1. Create a new text field type attribute country_price.
2. Make Used in Product Listing to yes and scope global.
3. \app\code\Vendor\Module\etc\di.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<virtualType name="Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\Pool">
<arguments>
<argument name="modifiers" xsi:type="array">
<item name="countryPrice" xsi:type="array">
<item name="class" xsi:type="string">Vendor\Module\Ui\DataProvider\Product\Form\Modifier\CountryPrice</item>
<item name="sortOrder" xsi:type="number">10</item>
</item>
</argument>
</arguments>
</virtualType>
</config>
4. \app\code\Vendor\Module\Ui\DataProvider\Product\Form\Modifier\CountryPrice.php
<?php
namespace Vendor\Module\Ui\DataProvider\Product\Form\Modifier;
use Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\AbstractModifier;
use Magento\Catalog\Controller\Adminhtml\Product\Initialization\StockDataFilter;
use Magento\Catalog\Model\Locator\LocatorInterface;
use Magento\CatalogInventory\Api\StockRegistryInterface;
use Magento\Framework\Stdlib\ArrayManager;
use Magento\CatalogInventory\Api\Data\StockItemInterface;
use Magento\CatalogInventory\Api\StockConfigurationInterface;
use Magento\Directory\Model\AllowedCountries;
use Magento\Ui\Component\Container;
use Magento\Ui\Component\Form\Element\DataType\Number;
use Magento\Ui\Component\Form\Element\DataType\Text;
use Magento\Ui\Component\Form\Element\Textarea;
use Magento\Ui\Component\Form\Element\Input;
use Magento\Ui\Component\Form\Field;
use Magento\Ui\Component\Form\Element\Select;
use Magento\Ui\Component\Modal;
/**
* Data provider for country price field
*/
class CountryPrice extends AbstractModifier {
const COUNTRY_PRICE_FIELD = 'country_price';
const FIELD_NAME_COUNTRY = 'country';
/**
* @var LocatorInterface
*/
private $locator;
/**
* @var ArrayManager
*/
private $arrayManager;
/**
* @var array
*/
private $meta = [];
/**
* @var string
*/
protected $scopeName;
/**
* @var \Magento\Directory\Model\AllowedCountries
*/
protected $allowedCountries;
/**
* @param LocatorInterface $locator
* @param ArrayManager $arrayManager
*/
public function __construct(
AllowedCountries $allowedCountries,
LocatorInterface $locator,
ArrayManager $arrayManager,
$scopeName = ''
) {
$this->allowedCountries = $allowedCountries;
$this->locator = $locator;
$this->arrayManager = $arrayManager;
$this->scopeName = $scopeName;
}
/**
* {@inheritdoc}
*/
public function modifyData(array $data) {
$fieldCode = self::COUNTRY_PRICE_FIELD;
$model = $this->locator->getProduct();
$modelId = $model->getId();
$countryPriceData = $model->getCountryPrice();
if ($countryPriceData) {
$countryPriceData = json_decode($countryPriceData, true);
$path = $modelId . '/' . self::DATA_SOURCE_DEFAULT . '/'. self::COUNTRY_PRICE_FIELD;
$data = $this->arrayManager->set($path, $data, $countryPriceData);
}
return $data;
}
/**
* {@inheritdoc}
*/
public function modifyMeta(array $meta) {
$this->meta = $meta;
$this -> initCountryPriceFields();
return $this->meta;
}
/**
* Customize country price field
*
* @return $this
*/
protected function initCountryPriceFields() {
$countryPricePath = $this->arrayManager->findPath(
self::COUNTRY_PRICE_FIELD,
$this->meta,
null,
'children'
);
if ($countryPricePath) {
$this->meta = $this->arrayManager->merge(
$countryPricePath,
$this->meta,
$this->initCountryPriceFieldStructure($countryPricePath)
);
$this->meta = $this->arrayManager->set(
$this->arrayManager->slicePath($countryPricePath, 0, -3)
. '/' . self::COUNTRY_PRICE_FIELD,
$this->meta,
$this->arrayManager->get($countryPricePath, $this->meta)
);
$this->meta = $this->arrayManager->remove(
$this->arrayManager->slicePath($countryPricePath, 0, -2),
$this->meta
);
}
return $this;
}
/**
* Get country price dynamic rows structure
*
* @param string $countryPricePath
* @return array
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
protected function initCountryPriceFieldStructure($countryPricePath)
{
return [
'arguments' => [
'data' => [
'config' => [
'componentType' => 'dynamicRows',
'label' => __('Country Price'),
'renderDefaultRecord' => false,
'recordTemplate' => 'record',
'dataScope' => '',
'dndConfig' => [
'enabled' => false,
],
'disabled' => false,
'sortOrder' =>
$this->arrayManager->get($countryPricePath . '/arguments/data/config/sortOrder', $this->meta),
],
],
],
'children' => [
'record' => [
'arguments' => [
'data' => [
'config' => [
'componentType' => Container::NAME,
'isTemplate' => true,
'is_collection' => true,
'component' => 'Magento_Ui/js/dynamic-rows/record',
'dataScope' => '',
],
],
],
'children' => [
static::FIELD_NAME_COUNTRY => $this->getCountryFieldConfig(2),
'price' => [
'arguments' => [
'data' => [
'config' => [
'formElement' => Input::NAME,
'componentType' => Field::NAME,
'dataType' => Text::NAME,
'label' => __('Price'),
'dataScope' => 'price',
'require' => '1',
],
],
],
],
'actionDelete' => [
'arguments' => [
'data' => [
'config' => [
'componentType' => 'actionDelete',
'dataType' => Text::NAME,
'label' => '',
],
],
],
],
],
],
],
];
}
protected function getCountryFieldConfig($sortOrder) {
return [
'arguments' => [
'data' => [
'config' => [
'dataType' => Text::NAME,
'formElement' => Select::NAME,
'componentType' => Field::NAME,
'dataScope' => static::FIELD_NAME_COUNTRY,
'label' => __('Select Country'),
'options' => $this->_getCountryOptions(),
'value' => 1,
'visible' => true,
'disabled' => false,
'sortOrder' => $sortOrder,
],
],
],
];
}
protected function _getCountryOptions() {
$countries = $this->allowedCountries->getAllowedCountries();
foreach($countries as $country){
$options[$country] = array("label"=> $this->getCustomerIdByCountryId($country), "value"=> $country);
}
return $options;
}
public function getCustomerIdByCountryId($countryId = null){
$customerIdArray = array(
"AT" => "WAUT00", "BE" => "WBEL00", "BG" => "WBGR00", "HR" => "WHRV00", "CY" => "WCYP00", "CZ" => "WCZE00",
"DK" => "WDNK00", "EE" => "WEST00", "FI" => "WFIN00", "FR" => "WFRA00", "DE" => "WDEU00", "GR" => "WGRC00",
"HU" => "WHUN00", "IE" => "WIRL00", "IT" => "WITA00", "LV" => "WLVA00", "LT" => "WLTU00", "LU" => "WLUX00",
"MT" => "WMLT00", "NL" => "WNLD00", "PL" => "WPOL00", "PT" => "WPRT00", "RO" => "WROU00", "SK" => "WSVK00",
"SI" => "WSVN00", "ES" => "WESP00", "SE" => "WSWE00", "GB" => "WGBR00", "IS" => "WISL00", "LI" => "WLIE00",
"NO" => "WNOR00", "CH" => "WCHE00",
);
return array_key_exists($countryId, $customerIdArray) ? $customerIdArray[$countryId] : "";
}
}
5. \app\code\Vendor\Module\etc\adminhtml\events.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
<event name="catalog_product_save_before">
<observer name="country_price_save_before" instance="Vendor\Module\Observer\SerializedCountryPrice" />
</event>
</config>
6. \app\code\Vendor\Module\Observer/SerializedCountryPrice.php
<?php
namespace Vendor\Module\Observer;
use \Magento\Framework\Event\Observer;
use \Magento\Framework\Event\ObserverInterface;
class SerializedCountryPrice implements ObserverInterface {
const ATTR_COUNTRY_PRICE_CODE = 'country_price';
/**
* @var \Magento\Framework\App\RequestInterface
*/
protected $request;
/**
* Constructor
*/
public function __construct(
\Magento\Framework\App\RequestInterface $request
)
{
$this->request = $request;
}
public function execute(Observer $observer) {
/** @var $product \Magento\Catalog\Model\Product */
$product = $observer->getEvent()->getDataObject();
$post = $this->request->getPost();
$post = $post['product'];
$countryPrice = isset($post[self::ATTR_COUNTRY_PRICE_CODE]) ? $post[self::ATTR_COUNTRY_PRICE_CODE] : '';
$product->setCountryPrice($countryPrice);
$requiredParams = ['country', 'price'];
if (is_array($countryPrice)) {
$countryPrice = $this->removeEmptyArray($countryPrice, $requiredParams);
$product->setCountryPrice(json_encode($countryPrice));
}
}
/**
* Function to remove empty array from the multidimensional array
*
* @return Array
*/
private function removeEmptyArray($countryPrice, $requiredParams){
$requiredParams = array_combine($requiredParams, $requiredParams);
$reqCount = count($requiredParams);
foreach ($countryPrice as $key => $values) {
$values = array_filter($values);
$inersectCount = count(array_intersect_key($values, $requiredParams));
if ($reqCount != $inersectCount) {
unset($countryPrice[$key]);
}
}
return $countryPrice;
}
}
![]()
0 Comments