diff --git a/readme.md b/readme.md index 98511e5..cb93442 100644 --- a/readme.md +++ b/readme.md @@ -214,10 +214,14 @@ We can also specify product options for select type attributes as so: - Yellow - Blue - Purple - - Pink + - Pink|default - Orange ``` +Use the marker `|default` to specify the default option. + +Note that the order of the options in the config file determines the sort order of the options. + Please note, certain attribute configurations follow certain rules so do ensure you're familiar with how Magento product attributes work in order to make best use of this component. An attribute's configuration elements are simply fields in the `catalog_eav_attribute` table with a few exceptions. ### Attribute Sets diff --git a/samples/components/attributes.yaml b/samples/components/attributes.yaml index b0c70aa..1a1015e 100644 --- a/samples/components/attributes.yaml +++ b/samples/components/attributes.yaml @@ -16,7 +16,7 @@ - Yellow - Blue - Purple - - Pink + - Pink|default - Orange - Brown - rrp: diff --git a/src/app/code/community/Cti/Configurator/Helper/Components/Attributes.php b/src/app/code/community/Cti/Configurator/Helper/Components/Attributes.php index 701f299..da2b40b 100644 --- a/src/app/code/community/Cti/Configurator/Helper/Components/Attributes.php +++ b/src/app/code/community/Cti/Configurator/Helper/Components/Attributes.php @@ -1,6 +1,9 @@ _componentName = 'attributes'; $this->_filePath1 = Mage::getBaseDir().DS.'app'.DS.'etc'.DS.'components'.DS.'attributes.yaml'; @@ -73,10 +76,12 @@ private function _createOrUpdateAttribute($code,$data) { }; unset($key); unset($value); + if (!$attribute->getEntityTypeId()) { $attribute->setEntityTypeId(Mage::getModel('eav/entity')->setType('catalog_product')->getTypeId()); $attribute->setIsUserDefined(1); } + try { if ($canSave) { $attribute->save(); @@ -90,7 +95,6 @@ private function _createOrUpdateAttribute($code,$data) { } } - /** * Gets a particular attribute otherwise * returns false if it doesn't exist @@ -125,64 +129,69 @@ private function _getAttribute($code) { * @param $attribute * @param $options */ - private function _maintainAttributeOptions($attribute,$options) { - - $currentOptions = $attribute->getSource()->getAllOptions(); + private function _maintainAttributeOptions($attribute, $options) + { + $currentOptions = array_filter($attribute->getSource()->getAllOptions(), function ($option) { return $option["label"] !== ""; }); + + // Make label => id map of currentOptions + $currentOptions = array_combine( + array_map(function ($keys) { return $keys['label']; }, $currentOptions), + array_map(function ($keys) { return $keys['value']; }, $currentOptions) + ); - $currentOptionFormat = array(); - foreach ($currentOptions as $option) { - if ($option['label'] != '') { - $currentOptionFormat[] = $option['label']; + // Look for default marker + $default = null; + $options = array_map(function ($option) use (&$default, $currentOptions) { + if ($this->isDefault($option)) { + $default = $this->getOptionId($option, $currentOptions); + } + return $this->trimDefault($option); + }, $options); + + // Ordered by position in YAML + $optionsPosition = array_flip($options); + + $toCreate = array_values(array_diff($options, array_keys($currentOptions))); + $toDelete = array_values(array_diff(array_keys($currentOptions), $options)); + + // Placeholders + $value = []; + $order = []; + $delete = []; + + // All properties (value, order, delete) are set no matter the operation + $allOptions = array_unique(array_merge($options, array_keys($currentOptions))); + foreach ($allOptions as $option) { + $option_id = null; + if (in_array($option, $toCreate)) { + $option_id = is_numeric($option) ? self::NUMBER_MARKER . $option : $option; + } else { + $option_id = $currentOptions[$option]; } - } - - $attributeId = $attribute->getId(); - $optionsToAdd = array_diff($options,$currentOptionFormat); - $optionsToRemove = array_diff($currentOptionFormat,$options); - $eav_entity_setup = new Mage_Eav_Model_Entity_Setup('core_setup'); - - // Create new attributes - foreach ($optionsToAdd as $option) { - unset($new_option); + $value[$option_id] = [ 0 => $option ]; + $order[$option_id] = "" . isset($optionsPosition[$option]) ? $optionsPosition[$option] : "0"; + $delete[$option_id] = ""; - // Check if the option already exists - if ($attribute->getSource()->getOptionId($option)) { - $this->log($this->__("Exsting attribute option %s for %s",$option,$attribute->getAttributeCode())); + if (in_array($option, $toDelete, true)) { + $delete[$option_id] = "1"; // value of "1" means delete } - $new_option['attribute_id'] = $attributeId; - $new_option['value']['_custom_'.$option][0] = $option; - $eav_entity_setup->addAttributeOption($new_option); - - /* - $attribute->setData( - 'option', - array( - 'value'=>array( - 'option'=>array( - $option - ) - ) - ) - ); - $attribute->save(); - */ - - $this->log($this->__("Created attribute option %s for %s",$option,$attribute->getAttributeCode())); } - // Remove old attributes - foreach ($optionsToRemove as $option) { - $optionId = $attribute->getSource()->getOptionId($option); - $toDelete['delete'][$optionId] = true; - $toDelete['value'][$optionId] = true; - $setup = new Mage_Eav_Model_Entity_Setup('core_setup'); - $setup->addAttributeOption($toDelete); - $this->log($this->__("Deleted attribute option %s for %s",$option,$attribute->getAttributeCode())); - } + // Data-structure derrived from saveAction in Mage_Adminhtml_Catalog_Product_AttributeController + $data = [ + "option" => [ + "value" => $value, + "order" => $order, + "delete" => $delete + ], + "default" => [ (in_array($default, $toCreate) && is_numeric($default) ? self::NUMBER_MARKER . $default : $default) ] + ]; + + $attribute->addData($data); + $attribute->save(); } - /** * @return array */ @@ -216,4 +225,18 @@ private function _getAttributeDefaultSettings() { 'search_weight' => 1 // EE only ); } -} \ No newline at end of file + + private function isDefault($option) + { + return strpos($option, "|" . self::DEFAULT_MARKER) !== false; + } + private function trimDefault($option) + { + return $this->isDefault($option) ? substr($option, 0, strpos($option, "|" . self::DEFAULT_MARKER)) : $option; + } + private function getOptionId($option, $currentOptions = []) + { + $option = $this->trimDefault($option); + return isset($currentOptions[$option]) ? $currentOptions[$option] : $option; + } +}