Creating Custom Options on a Product using the Magento API - magento

How do I add custom options to a product like you can in the backend, using the API.
Im using C# but if you know how do to this in Php, that would be helpful too.
I noticed that product has this:
var product = new catalogProductCreateEntity();
product.options_container = "blah";
And there is this:
catalogAttributeOptionEntity optionEntity = new catalogAttributeOptionEntity();
optionEntity.value = "sds";
optionEntity.label = "ere";
But I cant see a way of utilizing them, im not sure how to make a container, and the catalogAttributeOptionEntity does not have all the properties needed to make a custom option.

Look at the admin product controller. Yes it is possible.
/**
* Initialize data for configurable product
*/
if (($data = $this->getRequest()->getPost('configurable_products_data')) && !$product->getConfigurableReadonly()) {
$product->setConfigurableProductsData(Zend_Json::decode($data));
}
if (($data = $this->getRequest()->getPost('configurable_attributes_data')) && !$product->getConfigurableReadonly()) {
$product->setConfigurableAttributesData(Zend_Json::decode($data));
}
$product->setCanSaveConfigurableAttributes((bool)$this->getRequest()->getPost('affect_configurable_product_attributes') && !$product->getConfigurableReadonly());
/**
* Initialize product options
*/
if (isset($productData['options']) && !$product->getOptionsReadonly()) {
$product->setProductOptions($productData['options']);
}

This is not documented anywhere (else), but at least in Magento 1.6 one can find the appropriate API methods for product options in the source code. (I don 't know since which version that feature exists.)
The API itself is defined in: app/code/core/Mage/Catalog/etc/api.xml
<catalog_product_custom_option translate="title" module="catalog">
<title>Catalog product custom options API</title>
<model>catalog/product_option_api</model>
<acl>catalog/product/option</acl>
<methods>
<add translate="title" module="catalog">
<title>Add new custom option into product</title>
<acl>catalog/product/option/add</acl>
</add>
<update translate="title" module="catalog">
<title>Update custom option of product</title>
<acl>catalog/product/option/update</acl>
</update>
<types translate="title" module="catalog">
<title>Get list of available custom option types</title>
<acl>catalog/product/option/types</acl>
</types>
<info translate="title" module="catalog">
<title>Get full information about custom option in product</title>
<acl>catalog/product/option/info</acl>
</info>
<list translate="title" module="catalog">
<title>Retrieve list of product custom options</title>
<acl>catalog/product/option/list</acl>
<method>items</method>
</list>
<remove translate="title" module="catalog">
<title>Remove custom option</title>
<acl>catalog/product/option/remove</acl>
</remove>
</methods>
</catalog_product_custom_option>
The called functions are defined in: app/code/core/Mage/Catalog/Model/Product/Option/Api.php
class Mage_Catalog_Model_Product_Option_Api extends Mage_Catalog_Model_Api_Resource
{
/**
* Add custom option to product
*
* #param string $productId
* #param array $data
* #param int|string|null $store
* #return bool $isAdded
*/
public function add( $productId, $data, $store = null )
/**
* Update product custom option data
*
* #param string $optionId
* #param array $data
* #param int|string|null $store
* #return bool
*/
public function update( $optionId, $data, $store = null )
/**
* Read list of possible custom option types from module config
*
* #return array
*/
public function types()
/**
* Get full information about custom option in product
*
* #param int|string $optionId
* #param int|string|null $store
* #return array
*/
public function info( $optionId, $store = null )
/**
* Retrieve list of product custom options
*
* #param string $productId
* #param int|string|null $store
* #return array
*/
public function items( $productId, $store = null )
/**
* Remove product custom option
*
* #param string $optionId
* #return boolean
*/
public function remove( $optionId )
/**
* Check is type in allowed set
*
* #param string $type
* #return bool
*/
protected function _isTypeAllowed( $type )
}
The $data-array also is a bit tricky, since it's keys partly depend on the selected option type. The basic $data-array looks like:
$data = array (
'is_delete' => 0,
'title' => 'Custom Option Label',
'type' => 'text',
'is_require' => 0,
'sort_order' => 1,
'additional_fields' => array (
0 => array (
'price' => '10.0000',
'price_type' => 'fixed', // 'fixed' or 'percent'
'sku' => '',
),
),
);
The additional_fields always conatin at least one row with at least the columns price, price_type and sku. More additional fields (maf: …) may be added depending on the type. The types in the group select may have more than one row specified in additional_fields. The custom option types/type-groups are:
text (maf: 'max_characters')
field
area
file (maf: 'file_extension', 'image_size_x', 'image_size_y')
file
select (maf: 'value_id', 'title', 'sort_order')
drop_down
radio
checkbox
multiple
date
date
date_time
time
Examples for complete option data arrays:
// type-group: select, type: checkbox
$data = array (
'is_delete' => 0,
'title' => 'extra Option for that product',
'type' => 'checkbox',
'is_require' => 0,
'sort_order' => 1,
'additional_fields' => array (
0 => array (
'value_id' => '3',
'title' => 'Yes',
'price' => 10.00,
'price_type' => 'fixed',
'sku' => NULL,
'sort_order' => 1,
),
1 => array (
'value_id' => 3,
'title' => 'No',
'price' => 0.00,
'price_type' => 'fixed',
'sku' => NULL,
'sort_order' => 2,
),
),
);
// type-group: text, type: field
$data = array (
'is_delete' => 0,
'title' => 'Custom Option Label',
'type' => 'text',
'is_require' => 0,
'sort_order' => 1,
'additional_fields' => array (
0 => array (
'price' => 10.00,
'price_type' => 'fixed',
'sku' => NULL,
'max_characters' => 150,
),
),
);

In the end I decided it cant be done via the API and went to the database directly.

Related

cant update user attributes in installData

I create custom module.
After i try to add custom attribute in InstallData.php
I remove my module from setup_module to run install data however i don`t see any results nor error.
I try run setup:upgrade c:c c:f
I want to add custom attribute to user information. To update that information after user is register account. Also I want after to have ability to change it from admin area and from front settings. But for now i cant make work to see it in admin.
Should I add any additional code to run this ?
<?php
namespace Vendor\RewardPoints\Setup;
use Magento\Eav\Setup\EavSetup;
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Customer\Setup\CustomerSetupFactory;
use Magento\Customer\Model\Customer;
use Magento\Eav\Model\Entity\Attribute\SetFactory as AttributeSetFactory;
use Magento\Framework\Setup\InstallDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
/**
* #codeCoverageIgnore
*/
class InstallData implements InstallDataInterface
{
/**
* #var CustomerSetupFactory
*/
protected $customerSetupFactory;
/**
* #var AttributeSetFactory
*/
private $attributeSetFactory;
private $eavSetupFactory;
/**
* Init
*
* #param EavSetupFactory $eavSetupFactory
*/
public function __construct(EavSetupFactory $eavSetupFactory, CustomerSetupFactory $customerSetupFactory, AttributeSetFactory $attributeSetFactory)
{
$this->eavSetupFactory = $eavSetupFactory;
$this->customerSetupFactory = $customerSetupFactory;
$this->attributeSetFactory = $attributeSetFactory;
}
public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
{
/* Create customer attribute for front-end builder*/
/** #var CustomerSetup $customerSetup */
$customerSetup = $this->customerSetupFactory->create(['setup' => $setup]);
$customerEntity = $customerSetup->getEavConfig()->getEntityType('customer');
$attributeSetId = $customerEntity->getDefaultAttributeSetId();
/** #var $attributeSet AttributeSet */
$attributeSet = $this->attributeSetFactory->create();
$attributeGroupId = $attributeSet->getDefaultGroupId($attributeSetId);
$customerSetup->addAttribute(Customer::ENTITY, 'my_telephone', [
'type' => 'int',
'label' => 'My telephone',
'input' => 'text',
'required' => false,
'visible' => true,
'user_defined' => true,
'sort_order' => 1000,
'is_used_in_grid' => 1,
'is_visible_in_grid' => 1,
'is_filterable_in_grid' => 1,
'is_searchable_in_grid' => 1,
'position' => 1000,
'default' => 0,
'system' => 0,
]);
$attribute = $customerSetup->getEavConfig()->getAttribute(Customer::ENTITY, 'my_telephone')
->addData([
'attribute_set_id' => $attributeSetId,
'attribute_group_id' => $attributeGroupId,
'used_in_forms' => ['adminhtml_customer'],
]);
$attribute->save();
}
}
In the article Magento 2: How to make customer attribute? describe it step by step.
Customer attributes can be used in different forms, this example will show customer attribute at the admin customer edit page. You can also use also other forms. For example:
“used_in_forms” => [‘adminhtml_customer_address’, ‘customer_address_edit’, ‘customer_register_address’]

How to create different Magento categories for main and mobile store view on one domain name

I am looking solutions for using different categories for main and mobile Magento store view. I have configure mobile store view as new theme with user agent string and exception.
How can I do show one categories on main store view and another one categories on mobile store view. Both store views use by one domain name.
What I will suggest it create an category attribute with dropdown. Following Script will help you to do so :
SQL Setup file :
<?php
$installer = $this;
$installer->startSetup();
$installer->addAttribute("catalog_category", "wheretoshow", array(
"type" => "int",
"backend" => "",
"frontend" => "",
"label" => "Where to Show",
"input" => "select",
"class" => "",
"source" => "modulename/eav_entity_attribute_source_categoryoptions",
"global" => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_STORE,
"visible" => true,
"required" => false,
"user_defined" => false,
"default" => "Main Website",
"searchable" => false,
"filterable" => false,
"comparable" => false,
"visible_on_front" => false,
"unique" => false,
"note" => ""
));
$installer->endSetup();
Model/Categoryoptions.php
<?php
class class Packagename_Modulename_Model_Eav_Entity_Attribute_Source_Categoryoptions extends Mage_Eav_Model_Entity_Attribute_Source_Abstract
{
/**
* Retrieve all options array
*
* #return array
*/
public function getAllOptions()
{
if (is_null($this->_options)) {
$this->_options = array(
array(
"label" => Mage::helper("eav")->__("Mobile Website"),
"value" => 1
),
array(
"label" => Mage::helper("eav")->__("Main Website"),
"value" => 2
),
);
}
return $this->_options;
}
/**
* Retrieve option array
*
* #return array
*/
public function getOptionArray()
{
$_options = array();
foreach ($this->getAllOptions() as $option) {
$_options[$option["value"]] = $option["label"];
}
return $_options;
}
/**
* Get a text for option value
*
* #param string|integer $value
* #return string
*/
public function getOptionText($value)
{
$options = $this->getAllOptions();
foreach ($options as $option) {
if ($option["value"] == $value) {
return $option["label"];
}
}
return false;
}
/**
* Retrieve Column(s) for Flat
*
* #return array
*/
public function getFlatColums()
{
$columns = array();
$columns[$this->getAttribute()->getAttributeCode()] = array(
"type" => "tinyint(1)",
"unsigned" => false,
"is_null" => true,
"default" => null,
"extra" => null
);
return $columns;
}
/**
* Retrieve Indexes(s) for Flat
*
* #return array
*/
public function getFlatIndexes()
{
$indexes = array();
$index = "IDX_" . strtoupper($this->getAttribute()->getAttributeCode());
$indexes[$index] = array(
"type" => "index",
"fields" => array($this->getAttribute()->getAttributeCode())
);
return $indexes;
}
/**
* Retrieve Select For Flat Attribute update
*
* #param int $store
* #return Varien_Db_Select|null
*/
public function getFlatUpdateSelect($store)
{
return Mage::getResourceModel("eav/entity_attribute")
->getFlatUpdateSelect($this->getAttribute(), $store);
}
}
While Fetching the categories on frontend, filter those by this attribute depending on your website.

Attach Image to Product with Drupal Api

I am trying to programatically add products to my drupal commerce store. So far I have been able to add products that contain basic information ( such as sku, title, and price ). How would I be able to add field data, such as images and other field types, using drupal's api.
The code I used to add the products is derived from the commerce_examples/product_example module.
<?php
/**
* #file product_example.module
* Demonstrates pricing hooks, etc.
*/
/**
* Implements hook_menu().
*
* Simply presents a page that will explain what this module is for.
* hook_menu() has nothing to do with the checkout page functionality.
*/
function product_example_menu() {
$items['commerce_examples/product_example'] = array(
'title' => 'Product Example',
'page callback' => 'drupal_get_form',
'page arguments' => array('product_example_info_page'),
'access callback' => TRUE,
);
return $items;
}
/**
* This form provides a way to interact with some of the example functions
* provided here.
*/
function product_example_info_page($form, &$form_state) {
$form['explanation'] = array(
'#type' => 'item',
'#markup' => t('This example demonstrates product creation and manipulation.'),
);
$form['product_creation'] = array(
'#type' => 'fieldset',
'#title' => t('Please create a product for use with this example'),
);
$types = commerce_product_types();
$form['product_creation']['product_type'] = array(
'#type' => 'select',
'#title' => t('Product type for product to be created'),
'#options' => drupal_map_assoc(array_keys($types)),
);
$form['product_creation']['title'] = array(
'#title' => t('Product title'),
'#type' => 'textfield',
'#default_value' => t('A dummy product for use with product_example'),
);
$form['product_creation']['price'] = array(
'#title' => t('Product price'),
'#type' => 'textfield',
'#description' => t('A price in decimal format, without a currency symbol'),
'#default_value' => '100.00',
);
$form['product_creation']['product_creation_submit'] = array(
'#type' => 'submit',
'#value' => t('Create product'),
'#submit' => array('product_example_product_creation_submit')
);
return $form;
}
/**
* Submit handler for creating a product.
*/
function product_example_product_creation_submit($form, &$form_state) {
$extras = array(
'sku' => 'product_example_' . drupal_hash_base64(microtime()),
'status' => TRUE,
'uid' => $GLOBALS['user']->uid,
'title' => $form_state['values']['title'],
);
// Use the product example's creation function to create a product.
$product_id = product_example_create_product($form_state['values']['product_type'], $form_state['values']['price'], $extras);
drupal_set_message(t('Created sample product with title !title and sku !sku', array('!title' => l($extras['title'], 'admin/commerce/products/' . $product_id), '!sku' => $extras['sku'])));
}
/**
* Create a product programmatically.
*
* This is stolen shamelessly from commerce_bpc. Thanks for the help here!
*
* #param $product_type
* (string) The name of the product type for which products should be created.
* #param $price
* Decimal amount of price. If additional fields need to be populated they
* can be populated in exactly the same way as the commerce_price field.
* #param $extras
* An array for the values of 'extra fields' defined for the product type
* entity, or patterns for these. Recognized keys are:
* - status
* - uid
* - sku
* - title
* Note that the values do NOT come in the form of complex arrays (as they
* are not translatable, and can only have single values).
* #return
* The ID of the created product.
*/
function product_example_create_product($product_type, $price, $extras) {
$form_state = array();
$form_state['values'] = array();
$form = array();
$form['#parents'] = array();
// Generate a new product object
$new_product = commerce_product_new($product_type);
$new_product->status = $extras['status'];
$new_product->uid = $extras['uid'];
$new_product->sku = $extras['sku'];
$new_product->title = $extras['title'];
$new_product->created = $new_product->changed = time();
//commerce_price[und][0][amount]
$price = array(LANGUAGE_NONE => array(0 => array(
'amount' => $price * 100,
'currency_code' => commerce_default_currency(),
)));
$form_state['values']['commerce_price'] = $price;
// Notify field widgets to save their field data
field_attach_submit('commerce_product', $new_product, $form, $form_state);
commerce_product_save($new_product);
return $new_product->product_id;
}
Using the same format the examples uses to add price data:
//commerce_price[und][0][amount]
$price = array(LANGUAGE_NONE => array(0 => array(
'amount' => $price * 100,
'currency_code' => commerce_default_currency(),
)));
I was able to add other field data, however I am still having trouble adding data to the field_productimage field that all commerce products come with by default.
I can suggest you about other fields data such as extra info related to product. You can add these fields to the product type from the UI or if you are creating product type programmatically then also you can do the same.
Add fields in your form to collect the data e.g -
$form['product_creation']['values'] = array(
'#title' => t('Some data'),
'#type' => 'textfield',
'#description' => t('Dummy data'),
);
Get those data in your function product_example_create_product() by $form_state().
Add them to $new_product object like
$new_product->field_name['und'][0]['value'] = $extras['values'];
Save the product, just like you are doing.
For the image, you will have to follow the method of file attachment. Like -
$file_path = drupal_realpath('image/product_image.png');
$file = (object) array(
'uid' => 1,
'uri' => $file_path,
'filemime' => file_get_mimetype($file_path),
'status' => 1,
);
// We save the file to the root of the files directory.
$file = file_copy($file, 'public://');
$new_product->product_image[LANGUAGE_NONE][0] = (array)$file;

Creating attribute sets and attributes programmatically

I am using the code listed on the following link:
http://www.magentocommerce.com/wiki/5_-_modules_and_development/catalog/programmatically_adding_attributes_and_attribute_sets
Everything works until the point:
// Just add a default group.
else
{
$this->logInfo("Creating default group [{$this->groupName}] for set.");
$modelGroup = Mage::getModel('eav/entity_attribute_group');
$modelGroup->setAttributeGroupName($this->groupName);
$modelGroup->setAttributeSetId($id);
// This is optional, and just a sorting index in the case of
// multiple groups.
// $modelGroup->setSortOrder(1);
$model->setGroups(array($modelGroup));
}
I am unsure where the object reference would need to be set from - I am attempting to have this as a separate file that can be automated - I am running this file by doing a
require_once 'app/Mage.php';
Mage::app();
Any help in this would be greatly appreciated
You will need to have a block in your modules config.xml that looks like so
<resources>
<namespace_module_setup><!-- becomes folder under sql dir -->
<setup>
<module>Namespace_Module</module>
<class>Mage_Eav_Model_Entity_Setup</class>
</setup>
</namespace_module_setup>
</resources>
This will allow you to place your installer code in the directory that is in your XML. You need to make sure that the version listed on the installer file matches the <version>1.2.0</version> of your module otherwise Magento will not be able to run your installer. To add an attribute Set, you can use the following data, I have never use it, but the entityTypeId defines whether it is a customer, shipping, category, product entity, each 1, 2, 3, 4 respectively.
/**
* Add Attribute Set
*
* #param mixed $entityTypeId
* #param string $name
* #param int $sortOrder
* #return Mage_Eav_Model_Entity_Setup
*/
public function addAttributeSet($entityTypeId, $name, $sortOrder = null)
{
$data = array(
'entity_type_id' => $this->getEntityTypeId($entityTypeId),
'attribute_set_name' => $name,
'sort_order' => $this->getAttributeSetSortOrder($entityTypeId, $sortOrder),
);
$setId = $this->getAttributeSet($entityTypeId, $name, 'attribute_set_id');
if ($setId) {
$this->updateAttributeSet($entityTypeId, $setId, $data);
} else {
$this->_conn->insert($this->getTable('eav/attribute_set'), $data);
$this->addAttributeGroup($entityTypeId, $name, $this->_generalGroupName);
}
return $this;
}
This is the code for adding an attribute to a set, just change the attribute set data
//app/code/local/Namespace/Module/sql/Namespace_Module_setup/mysql4-install-1.0.0.php
$installer = $this;
/* #var $installer Mage_Eav_Model_Entity_Setup */
$installer->startSetup();
$data= array (
'attribute_set' => 'Default',
'group' => 'General',
'label' => 'Some Label',
'visible' => true,
'type' => 'varchar', // multiselect uses comma-sep storage
'input' => 'text',
'system' => true,
'required' => false,
'user_defined' => 1, //defaults to false; if true, define a group
);
$installer->addAttribute('catalog_product','attriute_code',$data)
$installer->endSetup();
The above is a working example of an attribute installation for a module.
There is an easier one-liner for this. Just extend Mage_Eav_Model_Entity_Setup for your install script and use something like this in your installer:
$installer = $this;
/* #var $installer Mage_Eav_Model_Entity_Setup */
$installer->startSetup();
$installer->addAttributeSet(Mage_Catalog_Model_Product::ENTITY, 'New Attribute Set Name');
$installer->endSetup();
You should implement this as an installer, so Magento loads it when the module is installed (or upgraded). $this, in the example, means that installer class.
You could create the module and the installer using https://bitbucket.org/alexsiri7/qbmagemoduleshell, and then adding that code there. That tool is a module creator I developed.

Magento - Sort Products by ID

I am trying to set up my Magento store to sort the products in the order that they were added to the catalog (by product ID). However, I haven't been able to find a good example of how to set this up. It seems to do this by default in most of my product categories, but not all of them.
I thought the sort by "Position" option on the frontend would do this, but it doesn't seem to work for all of my categories. I am using community edition 1.6.1.
Thanks in advance!
Copy :
app/code/core/Mage/Catalog/Block/Product/List.php
to (create the appropiate folder ):
app/code/local/Mage/Catalog/Block/Product/List.php
Find the following line in List.php :
$this->_productCollection = $layer->getProductCollection();
add the following line below :
$this->_productCollection->joinField('category_product', 'catalog/category_product', 'product_id', 'product_id=entity_id', array('store_id'=> Mage::app()->getStore()->getId()), 'left');
// Here is the explain
/*
* #param string $alias 'category_product'
* #param string $table 'catalog/category_product'
* #param string $field 'name'
* #param string $bind 'PK(product_id)=FK(entity_id)'
* #param string|array $cond
* #param string $joinType 'left'
*
* default definition
* joinField($alias, $table, $field, $bind, $cond=null, $joinType='inner')
*
*/
Copy
app/code/core/Mage/Catalog/Model/Config.php
to
app/code/local/Mage/Catalog/Model/Config.php
Find the following line in Config.php :
'position' => Mage::helper('catalog')->__('Position')
Replace with :
$options = array(
'position' => Mage::helper('catalog')->__('Position'),
'product_id' => Mage::helper('catalog')->__('Product ID')
);
PS : I am writing this article from home which I haven't got Magento installation on my machine, so I didn't test but the structure is OK. If you face of any toruble, make sure field and table name.
Just in case someone needs:
Change this:
'product_id' => Mage::helper('catalog')->__('Product ID')
to this:
'entity_id' => Mage::helper('catalog')->__('Product ID')
Copy
app/code/core/Mage/Catalog/Model/Config.php
to
app/code/local/Mage/Catalog/Model/Config.php
Find the following line in Config.php :
$options = array(
'position' => Mage::helper('catalog')->__('Position')
);
Replace with :
$options = array(
// 'position' => Mage::helper('catalog')->__('Position')
'entity_id' => Mage::helper('catalog')->__('Last')
);
then change the default sorting direction to descending:
open app/design/frontend/your theme/your layout/layout/catalog.xml
add the line
<action method="setDefaultDirection"><dir>desc</dir></action>
in block
<block type="catalog/product_list_toolbar" name="product_list_toolbar" template="catalog/product/list/toolbar.phtml">
<block type="page/html_pager" name="product_list_toolbar_pager"/>
<!-- The following code shows how to set your own pager increments -->
here
</block>
</block>

Resources