Set Product Custom Options From Observer Magento 1.9 - magento

I am trying to add custom options to products on save. I want to add or update custom options (not additional options) on before_product save. I am able to access the observer and it is working on save as well but unable to update the custom options. Create option code is working if run from standalone script but not from observer only.
This is my observer code
`class Company_Module_Model_Observer{
public function updateOptions($observer){
$product = $observer->getEvent()->getProduct();
$categories= $product->getCategoryIds();
$currentCategory = '';
foreach ($categories as $cat_id){
$cat = Mage::getModel('catalog/category')->load($cat_id);
$currentCategory = $cat->getName();
}
$skuList =['LAPTOP_','DESKTOP_'];
$upgrades = $optionValues = [];
if($currentCategory=='Laptops'){
$_productCollection = Mage::getModel('catalog/product')
->getCollection()
->addAttributeToFilter('sku', array('like' => 'LAPTOP_%'));
$upgrades = $_productCollection;
}
$meta = "6 this is product meta with custom plugin ".$product->getName();
foreach ($upgrades as $products) {
$_product = Mage::getModel('catalog/product')->load($products->getId());
$optionValues = array(
'title' => $_product->getName(),
'price' => $_product->getPrice(),
'price_type' => 'fixed',
'sku' => $_product->getSku(),
'sort_order' => 0,
);
}
$options = array(
'title' => 'Upgrades',
'type' => 'drop_down',
'is_required' => 0,
'sort_order' => 0,
'values' => $optionValues
);
$product->setMetaDescription($meta);
$product->setProductOptions(array($options));
$product->setCanSaveCustomOptions(true);
//if uncomment this then save loop continues and site hangs
//$product->save();
}
}`
No error in logs or anything else. Please guide me how I can achieve this.

You are in an infinite loop because the observer relaunches the same function each time, so when you run the save product function ( $product->save(); ), your function is rerun, and so on.
If you use the event catalog_product_save_before observer, you don't have to run the save function.
otherwise here:
foreach ($categories as $cat_id){
$cat = Mage::getModel('catalog/category')->load($cat_id);
$currentCategory = $cat->getName();
}
You get the last category in the collection, is that correct?

I know this is a bit late, but I had a similar issue like this a while back...
You are calling $product->setProductOptions() which without knowing your code I can only guess is setting it on the $product's _data array, which is probably not what you want. You need to stick it on the $product's option instance which will be used during the $product->_afterSave() call (You can see where the custom options are being saved in Mage_Catalog_Model_Product _afterSave() (~line 554 as of 1.9.4.5)). You can get the option instance like this: $optionInstance = $product->getOptionInstance() and set your options like this: $optionInstance->addOption($options). After you do that you should be able to allow the save to continue and your custom options should be created.

Related

Save TCA changes in TYPO3 on select box

I created I new field in my TCA. I want to list all articles and select one, to set the article as top-article.
The articles have a UID and the database a column called istoparticle.
tx_vendor_domain_model_article is the table with all infos of the article.
I added a TCAcolumn.
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTCAcolumns('tt_content', array(
'tx_test_istoparticle' => array(
'exclude' => 1,
'onChange' => 'reload',
'label' => 'Top Article',
'l10n_mode' => 'exclude',
'config' => array(
'type' => 'select',
'itemsProcFunc' => \Vendor\MyArticles\Hooks\Backend\Preview\ArticleRenderer::class . '->getArticleTitle',
)
),
));
With a userfunction
public function getTopArticles($param){
$pid = $param['row']['pid'];
$articles = $this->getArticles($pid);
foreach ($articles as $article) {
$record = BackendUtility::getRecord('tx_vendor_domain_model_article', $article->getUid());
$title = $record['header'];
$param['items'][][] = $title;
}
}
BTW:$record has all infos that I need, UID, bodytext and so on. But I can only store the header in the array!?
Now I got all the titles listed in my selectbox in the backend.
What do I have to do, to save my toparticle If I select an article in the backend?
Is there a onChange method for the TCA? And how can I get the infos like the Uid if I select one?
Items in TCA configuration should have at least two elements - first one is the label and second is the value. There are more options, but I think not needed in your case. You can read about them here: https://docs.typo3.org/typo3cms/TCAReference/8.7/ColumnsConfig/Type/Select.html#items
It means your usefFunc should look like that:
public function getTopArticles(&$param){
$pid = $param['row']['pid'];
$teasers = $this->getArticles($pid);
foreach ($articles as $article) {
$record = BackendUtility::getRecord('tx_vendor_domain_model_article', $article->getUid());
$param['items'][] = [
$record['header'],
$record['uid'],
]
}
}
And yes, there is onChange functionality in TCA:
https://docs.typo3.org/typo3cms/TCAReference/8.7/Columns/Index.html?highlight=onchange#onchange
If you are using older TYPO3 than 8.6 you would need to look for requestUpdate according to: https://docs.typo3.org/typo3cms/extensions/core/8.7/Changelog/8.6/Deprecation-78899-TCACtrlFieldRequestUpdateDropped.html

Magento - add to cart a product with advanced custom options setting option QTY

I am running Magento 1.9 with Advanced Custom Options by MageWorx. I am creating a module that needs to add a product with custom options to the cart. With the code below I can add the product to the cart with 1 option. Yet I can't figure out how to add a certain quantity for the custom option.
$product = $this->getProduct();
$product_id = $product->getId();
$product = Mage::getModel('catalog/product')->load($product_id);
$cart = Mage::getModel('checkout/cart');
$cart->init();
$params = array(
'product' => $product_id,
'qty' => 1,
'options' => array(
'1' => 1,
)
);
try {
$cart->addProduct($product, $params);
Mage::getSingleton('checkout/session')->setCartWasUpdated(true);
$cart->save();
echo '<div class="shiptext">Your order has been add to your cart.</div><br clear="all">';
}
catch (Exception $ex) {
echo $ex->getMessage();
}
Maybe I can't increase the QTY this way as Magento core doesn't support QTY for custom options? Which case I am guessing I may need to use some class inside of the Advanced Custom Options module but I am not sure how I would do that. If anyone has experience with Advanced Custom Options, it would be greatly appreciated as to how one might do this.
Found the answer. You need to add the to the prams options_groupid_qty.
$params = array(
'product' => $product_id,
'qty' => 1,
'options' => array(
'1' => 1,
),
'options_1_qty' => 30
);

update the frontend label of an attribute in magento programmatically?

I have an attribute with some attribute front end label.But I want to change frontendlabel for the product.Is there any function provided in magento to do this programmatically.
If yes,How can this be done???
Thank you,
The safest way to do that is to load the existing labels and then add your new store specific labels:
1 - retrieve the existing labels for all the stores
Mage::getModel('eav/entity_attribute')->getResource()
->getStoreLabelsByAttributeId($attributeId);
or
$attribute = Mage::getModel('catalog/resource_eav_attribute')->load($attributeId);
$labels= $attribute->getStoreLabels();
2 - Add your custom labels
$labels[$storeId] = 'My new label for a specific store';
$attribute->setStoreLabels($labels)->save();
If you want to set up frontend store labels for each store views, you can do it next way(This code for custemer attribute, but you can set frontend labels this way for all type of EAV-attributes.):
$installer->startSetup();
$attribute = array(
'entity_type' => 'customer',
'code' => 'customer_type_id',
'translations' => array(
'store_code_en_en' => 'english name',
'store_code_at_de' => 'german name',
'store_code_fr_fr' => 'franch name'
)
);
$storeLabels = array();
foreach ($attribute['translations'] as $storeViewCode => $text) {
$storeViewId = Mage::getModel('core/store')->load($storeViewCode, 'code')->getId();
$storeLabels[$storeViewId] = $text;
}
$attributeId = $installer->getAttributeId($attribute['entity_type'], $attribute['code']);
Mage::getSingleton('eav/config')->getAttribute($attribute['entity_type'], $attributeId)
->setData('store_labels', $storeLabels)
->save();
$installer->endSetup();
I found the more simpler solution to my question...
$attributeId = Mage::getModel('eav/entity_attribute')->getIdByCode('catalog_product', 'ATTRIBUTE_CODE');
$attribute = Mage::getModel('catalog/resource_eav_attribute')->load($attributeId);
$attribute->setFrontendLabel($displayName)->save();
setFrontendLabel(string $str) is the function which best suits here.

Magento: add configurable products to cart programmatically

How to add the child product to cart programmatically?
I've a child product SKU, I want to
Fetch the supper attributes like size and color id and values from the products,
Then fetch the parent product id,
Pass the super attributes on param with quantity, to add to function cart.
//$cart->addProduct($product1, $options);
Here, how to pass the supper attributes on the $option variable? Please help me!!!!
Try this. I think it may need some improvements but it works good in simple cases.
$_product = $this->getProduct();
$parentIds = Mage::getResourceSingleton('catalog/product_type_configurable')->getParentIdsByChild($_product->getId());
// check if something is returned
if (!empty(array_filter($parentIds))) {
$pid = $parentIds[0];
// Collect options applicable to the configurable product
$configurableProduct = Mage::getModel('catalog/product')->load($pid);
$productAttributeOptions = $configurableProduct->getTypeInstance(true)->getConfigurableAttributesAsArray($configurableProduct);
$options = array();
foreach ($productAttributeOptions as $productAttribute) {
$allValues = array_column($productAttribute['values'], 'value_index');
$currentProductValue = $_product->getData($productAttribute['attribute_code']);
if (in_array($currentProductValue, $allValues)) {
$options[$productAttribute['attribute_id']] = $currentProductValue;
}
}
// Get cart instance
$cart = Mage::getSingleton('checkout/cart');
$cart->init();
// Add a product with custom options
$params = array(
'product' => $configurableProduct->getId(),
'qty' => 1,
'super_attribute' => $options
);
$request = new Varien_Object();
$request->setData($params);
$cart->addProduct($configurableProduct, $request);
$session = Mage::getSingleton('customer/session');
$session->setCartWasUpdated(true);
$cart->save();
}
U can try.
$cart = Mage::getModel('checkout/cart');
$cart->init();
$productCollection = Mage::getModel('catalog/product')->load($productId);
$cart->addProduct($productCollection ,
array( 'product_id' => $productId,
'qty' => 1,
'options' => array( $optionId => $optionValue));
$cart->save();

How do I use setPage() in an non-EAV model in Magento for pagination/limiting?

I need to get $collection->setPage(0, 10); to work on my non-EAV model and it doesn't work. I've tried and $matches->getSelect()->setPage(0, 10); and it doesn't help.
The setPage() method only works for EAV based collection in Magento because it is defined in Mage_Eav_Model_Entity_Collection_Abstract class...
public function setPage($pageNum, $pageSize)
{
$this->setCurPage($pageNum)
->setPageSize($pageSize);
return $this;
}
As you can see, its a nice shorthand utility that is available to EAV based collections. For your non EAV based collection you can create your own version of this in your collection class or use the more verbose syntax for setting the page number and size in your client code when initialising the collection:
$collection->setCurPage($pageNum)
->setPageSize($pageSize)
;
public function updateIndex()
{
$productsCollection = Mage::getModel('catalog/product')->getCollection()
->addAttributeToSelect(array('name', 'image', 'url_key', 'price', 'visibility'));
$productsCollection->setPageSize(100);
$pages = $productsCollection->getLastPageNumber();
$currentPage = 1;
do {
$productsCollection->setCurPage($currentPage);
$productsCollection->load();
foreach ($productsCollection as $_product) {
$insertData = array(
'entity_id' => $_product->getId(),
'title' => $_product->getName(),
'image' => $_product->getImage(),
'url' => $_product->getUrlKey(),
'price' => $_product->getFinalPrice(),
);
$this->_getWriteAdapter()->insertOnDuplicate(
$this->getTable('atwix_sonar/suggestions'),
$insertData,
array('title', 'image', 'url', 'price')
);
}
$currentPage++;
//clear collection and free memory
$productsCollection->clear();
} while ($currentPage <= $pages);
}
See this complete example, it illustrates exactly how to use magento collection pager functions.
Source : http://www.atwix.com/magento/working-with-large-collections/

Resources