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