383 lines
14 KiB
PHP
Executable File
383 lines
14 KiB
PHP
Executable File
<?php
|
|
|
|
namespace JR\NetSuite\Service;
|
|
|
|
class AttributesSyncService
|
|
{
|
|
|
|
protected $productAttributeRepositoryInterface;
|
|
protected $productAttributeInterfaceFactory;
|
|
protected $tableFactory;
|
|
protected $attributeOptionManagement;
|
|
protected $optionLabelFactory;
|
|
protected $attributeOptionInterfaceFactory;
|
|
protected $productResource;
|
|
protected $optionsFactory;
|
|
protected $attributeFactory;
|
|
protected $attributeGroupInterfaceFactory;
|
|
protected $attributeGroupInterface;
|
|
protected $entityType;
|
|
protected $entityTypeCode;
|
|
protected $entityTypeId;
|
|
protected $attributeSetId;
|
|
|
|
protected $helper;
|
|
protected $sqquidGroup;
|
|
protected $groupCode;
|
|
protected $cacheAttributeData;
|
|
protected $cacheAttributeValueData;
|
|
protected $productAttributeData;
|
|
|
|
protected $groupName;
|
|
|
|
public function __construct(
|
|
\JR\NetSuite\Helper\Data $helper,
|
|
\Magento\Eav\Model\Entity\Attribute\Source\TableFactory $tableFactory,
|
|
\Magento\Eav\Api\AttributeOptionManagementInterface $attributeOptionManagement,
|
|
\Magento\Eav\Api\Data\AttributeOptionLabelInterfaceFactory $optionLabelFactory,
|
|
\Magento\Eav\Api\Data\AttributeOptionInterfaceFactory $attributeOptionInterfaceFactory,
|
|
\Magento\Catalog\Api\ProductAttributeRepositoryInterface $productAttributeRepositoryInterface,
|
|
\Magento\Catalog\Api\Data\ProductAttributeInterfaceFactory $productAttributeInterfaceFactory,
|
|
\Magento\Catalog\Model\ResourceModel\Product $productResource,
|
|
\Magento\ConfigurableProduct\Helper\Product\Options\Factory $optionsFactory,
|
|
\Magento\Catalog\Model\ProductFactory $productFactory,
|
|
\Magento\Eav\Api\Data\AttributeGroupInterfaceFactory $attributeGroupInterfaceFactory,
|
|
\Magento\Eav\Api\Data\AttributeGroupInterface $attributeGroupInterface,
|
|
\Magento\Eav\Model\Entity\AttributeFactory $attributeFactory
|
|
) {
|
|
|
|
$this->attributeGroupInterfaceFactory = $attributeGroupInterfaceFactory;
|
|
$this->attributeGroupInterface = $attributeGroupInterface;
|
|
$this->attributeFactory = $attributeFactory;
|
|
|
|
$this->helper = $helper;
|
|
|
|
$this->productResource = $productResource;
|
|
$this->productAttributeRepositoryInterface = $productAttributeRepositoryInterface;
|
|
$this->productAttributeInterfaceFactory = $productAttributeInterfaceFactory;
|
|
$this->tableFactory = $tableFactory;
|
|
$this->attributeOptionManagement = $attributeOptionManagement;
|
|
$this->optionLabelFactory = $optionLabelFactory;
|
|
$this->attributeOptionInterfaceFactory = $attributeOptionInterfaceFactory;
|
|
$this->optionsFactory = $optionsFactory;
|
|
|
|
$this->cacheAttributeData = [];
|
|
$this->cacheAttributeValueData = [];
|
|
|
|
// /*
|
|
// * We need to check if our group is on the default attribute set.. if not we should create
|
|
// */
|
|
// $this->groupName = "Sqquid";
|
|
// $this->groupCode = $this->helper->convertStringToCode($this->groupName);
|
|
// // maybe use something like \Magento\Catalog\Model\Product::ENTITY
|
|
// $this->entityTypeId = 4;
|
|
// $this->attributeSetId = $productFactory->create()->getDefaultAttributeSetId();
|
|
|
|
// $this->sqquidGroup = $this->attributeGroupInterface->load($this->groupName, 'attribute_group_name');
|
|
|
|
// if (!$this->sqquidGroup->itemExists()) {
|
|
// $group = $this->attributeGroupInterfaceFactory->create();
|
|
// $group->setAttributeSetId($this->attributeSetId)
|
|
// ->setAttributeGroupName($this->groupName)
|
|
// ->setSortOrder(100)
|
|
// ->setAttributeGroupCode($this->groupCode);
|
|
|
|
// $group->save();
|
|
|
|
// $this->sqquidGroup = $group;
|
|
// }
|
|
|
|
// $this->setIncludeAttribute();
|
|
}
|
|
|
|
// private function setIncludeAttribute()
|
|
// {
|
|
// $this->findOrCreateAttribute('Include', 'boolean', 'Magento\Eav\Model\Entity\Attribute\Source\Boolean');
|
|
// }
|
|
|
|
/**
|
|
* @param \Magento\Catalog\Model\Product $product
|
|
* @param array $data
|
|
* @return array|bool
|
|
*/
|
|
public function processAttributes(\Magento\Catalog\Model\Product $product, $data)
|
|
{
|
|
|
|
// if ($product->getSqquidInclude() != true) {
|
|
// $product->setData('sqquid_include', true);
|
|
// $this->productResource->saveAttribute($product, 'sqquid_include');
|
|
// }
|
|
|
|
if (!isset($data['Attributes'])) {
|
|
return false;
|
|
}
|
|
|
|
$productAttributeData = [];
|
|
|
|
foreach ($data['Attributes'] as $attribute) {
|
|
if ($attribute['value'] === null || $attribute['value'] === '') {
|
|
continue;
|
|
}
|
|
|
|
$type = null;
|
|
|
|
if (isset($attribute['type'])) {
|
|
$type = $attribute['type'];
|
|
}
|
|
|
|
if ($result = $this->setAttributeData($product, $attribute['label'], $attribute['value'], $type)) {
|
|
$productAttributeData[] = $result;
|
|
}
|
|
}
|
|
|
|
return $productAttributeData;
|
|
}
|
|
|
|
private function setAttributeData(\Magento\Catalog\Model\Product $product, $label, $value, $type = 'select')
|
|
{
|
|
$createType = $type == 'configurable_select' ? 'select' : $type;
|
|
$attribute = $this->findOrCreateAttribute($label, $createType);
|
|
|
|
if ($type == 'text') {
|
|
if ($product->getData($attribute->getAttributeCode()) != $value) {
|
|
$product->setData($attribute->getAttributeCode(), $value);
|
|
$this->productResource->saveAttribute($product, $attribute->getAttributeCode());
|
|
}
|
|
}
|
|
|
|
if ($type == 'select' || $type == 'configurable_select') {
|
|
$valueId = $this->findOrCreateValue($attribute, $value);
|
|
|
|
if ($product->getAttributeText($attribute->getAttributeCode()) != $value) {
|
|
$product->setData($attribute->getAttributeCode(), $valueId);
|
|
$this->productResource->saveAttribute($product, $attribute->getAttributeCode());
|
|
}
|
|
|
|
if ($type == 'configurable_select') {
|
|
$configurationData = [
|
|
'label' => $attribute->getStoreLabel(),
|
|
'attribute_id' => $attribute->getId(),
|
|
'attribute_code' => $attribute->getAttributeCode(),
|
|
'value_index' => $valueId,
|
|
'value_label' => $value,
|
|
'pricing_value' => $product->getPrice()
|
|
];
|
|
|
|
return $configurationData;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public function findOrCreateValue($attribute, $value)
|
|
{
|
|
if (!isset($this->cacheAttributeValueData[$attribute->getId()])) {
|
|
$this->cacheAttributeValueData[$attribute->getId()] = []; // just to set it up
|
|
}
|
|
|
|
if (isset($this->cacheAttributeValueData[$attribute->getId()][$value])) {
|
|
return $this->cacheAttributeValueData[$attribute->getId()][$value];
|
|
}
|
|
|
|
$valueId = $this->findOrCreateValueFromDatabase($attribute, $value);
|
|
|
|
$this->cacheAttributeValueData[$attribute->getId()][$value] = $valueId;
|
|
|
|
return $valueId;
|
|
}
|
|
|
|
public function findOrCreateValueFromDatabase($attribute, $label)
|
|
{
|
|
if (strlen($label) < 1) {
|
|
throw new \Magento\Framework\Exception\LocalizedException(
|
|
__('Label for %1 must not be empty.', $attribute->getId())
|
|
);
|
|
}
|
|
|
|
if ($optionId = $this->getOptionId($attribute, $label)) {
|
|
return $optionId;
|
|
}
|
|
|
|
/** @var \Magento\Eav\Model\Entity\Attribute\OptionLabel $optionLabel */
|
|
$optionLabel = $this->optionLabelFactory->create();
|
|
$optionLabel->setStoreId(0);
|
|
$optionLabel->setLabel($label);
|
|
|
|
$option = $this->attributeOptionInterfaceFactory->create();
|
|
$option->setLabel($optionLabel);
|
|
$option->setStoreLabels([$optionLabel]);
|
|
$option->setSortOrder(0);
|
|
$option->setIsDefault(false);
|
|
|
|
$this->attributeOptionManagement->add(
|
|
\Magento\Catalog\Model\Product::ENTITY,
|
|
$attribute->getId(),
|
|
$option
|
|
);
|
|
|
|
// Get the inserted ID. Should be returned from the installer, but it isn't.
|
|
$optionId = $this->getOptionId($attribute, $label);
|
|
|
|
return $optionId;
|
|
}
|
|
|
|
public function getOptionId($attribute, $label)
|
|
{
|
|
|
|
// We have to generate a new sourceModel instance each time through to prevent it from
|
|
// referencing its _options cache. No other way to get it to pick up newly-added values.
|
|
|
|
/** @var \Magento\Eav\Model\Entity\Attribute\Source\Table $sourceModel */
|
|
$sourceModel = $this->tableFactory->create();
|
|
$sourceModel->setAttribute($attribute);
|
|
|
|
foreach ($sourceModel->getAllOptions() as $option) {
|
|
$this->cacheAttributeValueData[$attribute->getAttributeId()][$option['label']] = $option['value'];
|
|
}
|
|
|
|
// Return option ID if exists
|
|
if (isset($this->cacheAttributeValueData[$attribute->getAttributeId()][$label])) {
|
|
return $this->cacheAttributeValueData[$attribute->getAttributeId()][$label];
|
|
}
|
|
|
|
// Return false if does not exist
|
|
return false;
|
|
}
|
|
|
|
private function findOrCreateAttribute($label, $type, $source = null)
|
|
{
|
|
$code = $label . '-' . $type;
|
|
if (isset($this->cacheAttributeData[$code])) {
|
|
return $this->cacheAttributeData[$code];
|
|
}
|
|
|
|
$attribute = $this->findOrCreateAttributeFromDatabase($label, $type, $source);
|
|
$this->cacheAttributeData[$code] = $attribute;
|
|
return $attribute;
|
|
}
|
|
|
|
public function findOrCreateAttributeFromDatabase($label, $attribute_type, $source = null)
|
|
{
|
|
|
|
$code = $this->helper->convertStringToCode($label);
|
|
|
|
$attribute_code = 'netsuite_' . $code;
|
|
|
|
$mustCreateAttribute = false;
|
|
|
|
try {
|
|
$attribute = $this->productAttributeRepositoryInterface->get($attribute_code);
|
|
} catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
|
|
// Yes, if there is a NoSuchEntityException, it means that the attributes does not exist
|
|
$mustCreateAttribute = true;
|
|
}
|
|
|
|
if (!$mustCreateAttribute) {
|
|
return $attribute;
|
|
}
|
|
|
|
$attribute = $this->productAttributeInterfaceFactory->create();
|
|
$attribute->setEntityTypeId($this->entityTypeId);
|
|
|
|
$data = [
|
|
'group' => $this->groupName,
|
|
'attribute_code' => $attribute_code,
|
|
'frontend_label' => $label,
|
|
'backend_type' => '',
|
|
'frontend_input' => $attribute_type,
|
|
'is_required' => false,
|
|
'is_unique' => false,
|
|
'is_user_defined' => true,
|
|
'sort_order' => 100,
|
|
'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL,
|
|
'used_in_product_listing' => false,
|
|
'searchable' => true,
|
|
'comparable' => true,
|
|
'visible_on_front' => true,
|
|
'visible' => true
|
|
];
|
|
|
|
if ($source) {
|
|
$data['source'] = $source;
|
|
}
|
|
|
|
$attribute->setData($data);
|
|
|
|
$this->productAttributeRepositoryInterface->save($attribute);
|
|
|
|
$attributeEntity = $this->attributeFactory->create();
|
|
$attributeEntity->setAttributeSetId($this->attributeSetId)
|
|
->setEntityTypeId($this->entityTypeId)
|
|
->setAttributeGroupId($this->sqquidGroup->getId())
|
|
->setAttributeId($attribute->getId())
|
|
->setSortOrder(0);
|
|
|
|
$attributeEntity->save();
|
|
|
|
return $attribute;
|
|
}
|
|
|
|
public function attachAttributesFromChildData($product, $configurableProductsData)
|
|
{
|
|
|
|
if (!$configurableProductsData) {
|
|
return $product;
|
|
}
|
|
$associatedProductIds = array_keys($configurableProductsData);
|
|
|
|
$tempValueArray = [];
|
|
$usedValueArray = [];
|
|
|
|
$attributeValueData = [];
|
|
$usedAttributeArray = [];
|
|
|
|
foreach ($configurableProductsData as $item) { // get unique attribute IDs
|
|
|
|
foreach ($item as $data) {
|
|
if (!isset($tempValueArray[$data['attribute_id']])) {
|
|
$tempValueArray[$data['attribute_id']] = [];
|
|
}
|
|
|
|
if (in_array($data['value_index'], $usedValueArray)) {
|
|
continue;
|
|
}
|
|
|
|
$tempValueArray[$data['attribute_id']][] = [
|
|
'attribute_id' => $data['attribute_id'],
|
|
'label' => $data['value_label'],
|
|
'value_index' => $data['value_index'],
|
|
];
|
|
|
|
$usedValueArray[] = $data['value_index'];
|
|
}
|
|
}
|
|
|
|
foreach ($configurableProductsData as $item) { // get unique attribute IDs
|
|
foreach ($item as $data) {
|
|
if (in_array($data['attribute_id'], $usedAttributeArray)) {
|
|
continue;
|
|
}
|
|
|
|
$attributeValueData[] = [
|
|
'attribute_id' => $data['attribute_id'],
|
|
'code' => $data['attribute_code'],
|
|
'label' => $data['label'],
|
|
'position' => '0',
|
|
'values' => $tempValueArray[$data['attribute_id']],
|
|
];
|
|
|
|
$usedAttributeArray[] = $data['attribute_id'];
|
|
}
|
|
}
|
|
|
|
$configurableOptions = $this->optionsFactory->create($attributeValueData);
|
|
$extensionConfigurableAttributes = $product->getExtensionAttributes();
|
|
$extensionConfigurableAttributes->setConfigurableProductOptions($configurableOptions);
|
|
$extensionConfigurableAttributes->setConfigurableProductLinks($associatedProductIds); // associated product IDs
|
|
$product->setExtensionAttributes($extensionConfigurableAttributes);
|
|
|
|
return $product;
|
|
}
|
|
}
|