Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
RowCustomizer.php
Go to the documentation of this file.
1 <?php
7 
15 
20 {
21  const BUNDLE_PRICE_TYPE_COL = 'bundle_price_type';
22 
23  const BUNDLE_SKU_TYPE_COL = 'bundle_sku_type';
24 
25  const BUNDLE_PRICE_VIEW_COL = 'bundle_price_view';
26 
27  const BUNDLE_WEIGHT_TYPE_COL = 'bundle_weight_type';
28 
29  const BUNDLE_VALUES_COL = 'bundle_values';
30 
31  const VALUE_FIXED = 'fixed';
32 
33  const VALUE_DYNAMIC = 'dynamic';
34 
35  const VALUE_PERCENT = 'percent';
36 
37  const VALUE_PRICE_RANGE = 'Price range';
38 
39  const VALUE_AS_LOW_AS = 'As low as';
40 
46  protected $typeMapping = [
47  '0' => self::VALUE_DYNAMIC,
48  '1' => self::VALUE_FIXED
49  ];
50 
56  protected $priceViewMapping = [
59  ];
60 
66  protected $priceTypeMapping = [
67  '0' => self::VALUE_FIXED,
68  '1' => self::VALUE_PERCENT
69  ];
70 
76  protected $bundleColumns = [
82  ];
83 
89  protected $bundleData = [];
90 
96  private $shipmentTypeColumn = 'bundle_shipment_type';
97 
103  private $shipmentTypeMapping = [
104  AbstractType::SHIPMENT_TOGETHER => 'together',
105  AbstractType::SHIPMENT_SEPARATELY => 'separately',
106  ];
107 
111  private $optionCollections = [];
112 
116  private $storeIdToCode = [];
117 
121  private $optionCollectionCacheKey = '_cache_instance_options_collection';
122 
126  private $storeManager;
127 
131  public function __construct(StoreManagerInterface $storeManager)
132  {
133  $this->storeManager = $storeManager;
134  }
135 
140  private function getBundleColumns()
141  {
142  return array_merge($this->bundleColumns, [$this->shipmentTypeColumn]);
143  }
144 
153  {
155  $productCollection->addAttributeToFilter(
156  'entity_id',
157  ['in' => $productIds]
158  )->addAttributeToFilter(
159  'type_id',
160  ['eq' => \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE]
161  );
162 
163  return $this->populateBundleData($productCollection);
164  }
165 
172  public function addHeaderColumns($columns)
173  {
174  $columns = array_merge($columns, $this->getBundleColumns());
175 
176  return $columns;
177  }
178 
186  public function addData($dataRow, $productId)
187  {
188  if (!empty($this->bundleData[$productId])) {
189  $dataRow = array_merge($this->cleanNotBundleAdditionalAttributes($dataRow), $this->bundleData[$productId]);
190  }
191 
192  return $dataRow;
193  }
194 
203  public function getAdditionalRowsCount($additionalRowsCount, $productId)
204  {
205  return $additionalRowsCount;
206  }
207 
214  protected function populateBundleData($collection)
215  {
216  foreach ($collection as $product) {
217  $id = $product->getEntityId();
218  $this->bundleData[$id][self::BUNDLE_PRICE_TYPE_COL] = $this->getTypeValue($product->getPriceType());
219  $this->bundleData[$id][$this->shipmentTypeColumn] = $this->getShipmentTypeValue(
220  $product->getShipmentType()
221  );
222  $this->bundleData[$id][self::BUNDLE_SKU_TYPE_COL] = $this->getTypeValue($product->getSkuType());
223  $this->bundleData[$id][self::BUNDLE_PRICE_VIEW_COL] = $this->getPriceViewValue($product->getPriceView());
224  $this->bundleData[$id][self::BUNDLE_WEIGHT_TYPE_COL] = $this->getTypeValue($product->getWeightType());
225  $this->bundleData[$id][self::BUNDLE_VALUES_COL] = $this->getFormattedBundleOptionValues($product);
226  }
227  return $this;
228  }
229 
236  protected function getFormattedBundleOptionValues(\Magento\Catalog\Model\Product $product): string
237  {
238  $optionCollections = $this->getProductOptionCollection($product);
239  $bundleData = '';
240  $optionTitles = $this->getBundleOptionTitles($product);
241  foreach ($optionCollections->getItems() as $option) {
242  $optionValues = $this->getFormattedOptionValues($option, $optionTitles);
244  $optionValues,
245  $product->getTypeInstance()
246  ->getSelectionsCollection([$option->getId()], $product)
247  ->setOrder('position', Collection::SORT_ORDER_ASC)
248  );
249  }
250 
251  return rtrim($bundleData, ImportProductModel::PSEUDO_MULTI_LINE_SEPARATOR);
252  }
253 
261  protected function getFormattedBundleSelections($optionValues, SelectionCollection $selections)
262  {
263  $bundleData = '';
264  $selections->addAttributeToSort('position');
265  foreach ($selections as $selection) {
266  $selectionData = [
267  'sku' => $selection->getSku(),
268  'price' => $selection->getSelectionPriceValue(),
269  'default' => $selection->getIsDefault(),
270  'default_qty' => $selection->getSelectionQty(),
271  'price_type' => $this->getPriceTypeValue($selection->getSelectionPriceType()),
272  'can_change_qty' => $selection->getSelectionCanChangeQty(),
273  ];
274  $bundleData .= $optionValues
275  . ImportModel::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR
276  . implode(
277  ImportModel::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR,
278  array_map(
279  function ($value, $key) {
280  return $key . ImportProductModel::PAIR_NAME_VALUE_SEPARATOR . $value;
281  },
282  $selectionData,
283  array_keys($selectionData)
284  )
285  )
286  . ImportProductModel::PSEUDO_MULTI_LINE_SEPARATOR;
287  }
288 
289  return $bundleData;
290  }
291 
299  protected function getFormattedOptionValues(
300  \Magento\Bundle\Model\Option $option,
301  array $optionTitles = []
302  ): string {
303  $names = implode(ImportModel::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, array_map(
304  function ($title, $storeName) {
305  return $storeName . ImportProductModel::PAIR_NAME_VALUE_SEPARATOR . $title;
306  },
307  $optionTitles[$option->getOptionId()],
308  array_keys($optionTitles[$option->getOptionId()])
309  ));
310  return $names . ImportModel::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR
311  . 'type' . ImportProductModel::PAIR_NAME_VALUE_SEPARATOR
312  . $option->getType() . ImportModel::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR
313  . 'required' . ImportProductModel::PAIR_NAME_VALUE_SEPARATOR
314  . $option->getRequired();
315  }
316 
323  protected function getTypeValue($type)
324  {
325  return $this->typeMapping[$type] ?? self::VALUE_DYNAMIC;
326  }
327 
334  protected function getPriceViewValue($type)
335  {
336  return $this->priceViewMapping[$type] ?? self::VALUE_PRICE_RANGE;
337  }
338 
345  protected function getPriceTypeValue($type)
346  {
347  return $this->priceTypeMapping[$type] ?? null;
348  }
349 
356  private function getShipmentTypeValue($type)
357  {
358  return $this->shipmentTypeMapping[$type] ?? null;
359  }
360 
367  protected function cleanNotBundleAdditionalAttributes($dataRow)
368  {
369  if (!empty($dataRow['additional_attributes'])) {
370  $additionalAttributes = $this->parseAdditionalAttributes($dataRow['additional_attributes']);
371  $dataRow['additional_attributes'] = $this->getNotBundleAttributes($additionalAttributes);
372  }
373 
374  return $dataRow;
375  }
376 
383  protected function getNotBundleAttributes($additionalAttributes)
384  {
385  $filteredAttributes = [];
386  foreach ($additionalAttributes as $code => $value) {
387  if (!in_array('bundle_' . $code, $this->getBundleColumns())) {
388  $filteredAttributes[] = $code . ImportProductModel::PAIR_NAME_VALUE_SEPARATOR . $value;
389  }
390  }
391  return implode(ImportModel::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, $filteredAttributes);
392  }
393 
400  private function parseAdditionalAttributes($additionalAttributes)
401  {
402  $attributeNameValuePairs = explode(ImportModel::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, $additionalAttributes);
403  $preparedAttributes = [];
404  $code = '';
405  foreach ($attributeNameValuePairs as $attributeData) {
406  //process case when attribute has ImportModel::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR inside its value
407  if (strpos($attributeData, ImportProductModel::PAIR_NAME_VALUE_SEPARATOR) === false) {
408  if (!$code) {
409  continue;
410  }
411  $preparedAttributes[$code] .= ImportModel::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR . $attributeData;
412  continue;
413  }
414  list($code, $value) = explode(ImportProductModel::PAIR_NAME_VALUE_SEPARATOR, $attributeData, 2);
415  $preparedAttributes[$code] = $value;
416  }
417  return $preparedAttributes;
418  }
419 
434  private function getBundleOptionTitles(\Magento\Catalog\Model\Product $product): array
435  {
436  $optionCollections = $this->getProductOptionCollection($product);
437  $optionsTitles = [];
439  foreach ($optionCollections->getItems() as $option) {
440  $optionsTitles[$option->getId()]['name'] = $option->getTitle();
441  }
442  $storeIds = $product->getStoreIds();
443  if (count($storeIds) > 1) {
444  foreach ($storeIds as $storeId) {
445  $optionCollections = $this->getProductOptionCollection($product, (int)$storeId);
447  foreach ($optionCollections->getItems() as $option) {
448  $optionTitle = $option->getTitle();
449  if ($optionsTitles[$option->getId()]['name'] != $optionTitle) {
450  $optionsTitles[$option->getId()]['name_' . $this->getStoreCodeById((int)$storeId)] =
451  $optionTitle;
452  }
453  }
454  }
455  }
456  return $optionsTitles;
457  }
458 
468  private function getProductOptionCollection(
469  \Magento\Catalog\Model\Product $product,
470  int $storeId = \Magento\Store\Model\Store::DEFAULT_STORE_ID
471  ): \Magento\Bundle\Model\ResourceModel\Option\Collection {
472  $productSku = $product->getSku();
473  if (!isset($this->optionCollections[$productSku][$storeId])) {
474  $product->unsetData($this->optionCollectionCacheKey);
475  $product->setStoreId($storeId);
476  $this->optionCollections[$productSku][$storeId] = $product->getTypeInstance()
477  ->getOptionsCollection($product)
478  ->setOrder('position', Collection::SORT_ORDER_ASC);
479  }
480  return $this->optionCollections[$productSku][$storeId];
481  }
482 
491  private function getStoreCodeById(int $storeId): string
492  {
493  if (!isset($this->storeIdToCode[$storeId])) {
494  $this->storeIdToCode[$storeId] = $this->storeManager->getStore($storeId)->getCode();
495  }
496  return $this->storeIdToCode[$storeId];
497  }
498 }
$title
Definition: default.phtml:14
getFormattedBundleOptionValues(\Magento\Catalog\Model\Product $product)
$id
Definition: fieldset.phtml:14
$storeManager
getFormattedOptionValues(\Magento\Bundle\Model\Option $option, array $optionTitles=[])
getFormattedBundleSelections($optionValues, SelectionCollection $selections)
$columns
Definition: default.phtml:15
$type
Definition: item.phtml:13
$value
Definition: gender.phtml:16
__construct(StoreManagerInterface $storeManager)
$storeName
Definition: logo.phtml:13
getAdditionalRowsCount($additionalRowsCount, $productId)
$code
Definition: info.phtml:12