Pages

Tuesday, November 25, 2014

How to delete orders

Usually you have after a certain time of developing some test orders that you want go get rid of. this is a small script to delete them


// if you run this code in a shell, see comment below, you have to set this flag
Mage::register('isSecureArea', true);

// select all orders
$orders = Mage::getModel('sales/order')->getCollection();

// select defined orders listed in $orderIds  
$orders = Mage::getModel('sales/order')->getCollection()
    ->addFieldToFilter('entity_id', (array) $orderIds);

foreach ($orders as $order) { 
    $order->delete(); 
}

you can run code snippet like above with a php shell as provided in Magento PHP Developer's Guide (p.58)

Sunday, November 23, 2014

Bulk update products to be in/out of stock programatically

This is an example to set all (filtered) products to be in stock with quantity of 1.

$products = Mage::getModel('catalog/product')->getCollection();
// filter your product list
$products = $products->addFieldToFilter($attribute_code, $attribute_value)->load();

foreach($products as $product){
 $stockItem = Mage::getModel('cataloginventory/stock_item')->loadByProduct($product); 
 $stockItem->setData('is_in_stock', 1);
 $stockItem->setData('qty',1);
 $stockItem->save();
}


Friday, November 21, 2014

Converting wav files to flac with python and audiotools

This is not about Magento programming ;-)

I was looking for a (free) tools to convert all my wav files to flac. As such, not a special task, there are many tools around. But all the GUI tools I found, had big issues to run in batch mode with thousands of files to convert. 

Eventually I found track2track from audiotools. The only problem was here, I couldn't get it working in batch mode with setting the right params for the output (converted) file names. So I decided to wrap my own script around audiotools. 

Certainly not really performant, but it does the job.
Here my first try:


from Queue import Queue
import logging
import os
from threading import Thread
import audiotools
from audiotools.wav import InvalidWave

"""
Wave 2 Flac converter script
using audiotools
"""
class W2F:

    logger = ''

    def __init__(self):
        global logger
        # create logger
        logger = logging.getLogger(__name__)
        logger.setLevel(logging.DEBUG)

        # create a file handler
        handler = logging.FileHandler('converter.log')
        handler.setLevel(logging.INFO)

        # create a logging format
        formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
        handler.setFormatter(formatter)

        # add the handlers to the logger
        logger.addHandler(handler)

    def convert(self):
        global logger
        file_queue = Queue()
        num_converter_threads = 5

        # collect files to be converted
        for root, dirs, files in os.walk("/Volumes/music"):

            for file in files:
                if file.endswith(".wav"):
                    file_wav = os.path.join(root, file)
                    file_flac = file_wav.replace(".wav", ".flac")

                    if (os.path.exists(file_flac)):
                        logger.debug(''.join(["File ",file_flac, " already exists."]))
                    else:
                        file_queue.put(file_wav)

        logger.info("Start converting:  %s files", str(file_queue.qsize()))

        # Set up some threads to convert files
        for i in range(num_converter_threads):
            worker = Thread(target=self.process, args=(file_queue,))
            worker.setDaemon(True)
            worker.start()

        file_queue.join()

    def process(self, q):
        """This is the worker thread function.
        It processes files in the queue one after
        another.  These daemon threads go into an
        infinite loop, and only exit when
        the main thread ends.
        """
        while True:
            global logger
            compression_quality = '0' #min compression
            file_wav = q.get()
            file_flac = file_wav.replace(".wav", ".flac")

            try:
                audiotools.open(file_wav).convert(file_flac,audiotools.FlacAudio, compression_quality)
                logger.info(''.join(["Converted ", file_wav, " to: ", file_flac]))
                q.task_done()
            except InvalidWave:
                logger.error(''.join(["Failed to open file ", file_wav, " to: ", file_flac," failed."]), exc_info=True)
            except Exception, e:
                logger.error('ExFailed to open file', exc_info=True)




As you can see, there is a bit of multithreading implemented. Looks like it works a bit faster than my first try. Anyway, it's only a dummy example, improve it as you like!

Wednesday, November 5, 2014

How to get Magento's attribute names and values

For my own reference, quick and dirty:
$product = Mage::getModel('catalog/product')->load($productId);
$attribute_value = $product->getData($attribute_code);

The attribute code used below is 'attribute_code'.

/**
 * get attribute collection
 */
$attribute = $_product->getResource()->getAttribute('attribute_code');

/**
 * get attribute type
 */
$attribute->getAttributeType();

/**
 * get attribute label
 */
$attribute->getFrontendLabel();

/**
 * get attribute default value
 */
$attribute->getDefaultValue();

/**
 * check if the attribute is visible
 */
$attribute->getIsVisible();

/**
 * check if the attribute is required
 */
$attribute->getIsRequired();

/**
 * get attribute value
 */
$attributeValue = Mage::getModel('catalog/product')->load($_product->getId())->getAttributeCode();

//or without loading the product
$attributeValue = Mage::getResourceModel('catalog/product')->getAttributeRawValue($productId, 'attribute_code', $storeId);

/**
* get attribute option code/value list 
*/
$attribute = Mage::getSingleton('eav/config')->getAttribute('catalog_product', 'attribute_code');
$options = $attribute->getSource()->getAllOptions(false);


in a view.php or similar, you can access the attribute text related to a product like:
<?php echo $_product->getAttributeText('attribute_code'); ?>

Thursday, October 9, 2014

"Undefined Index" error importing products over cvs file

If you happened to get one of the following error during import of products over a cvs file,
  • Notice: Undefined index: _media_attribute_id
  • Notice: Undefined index: _media_lablel
  • Notice: Undefined index: _media_position
  • Notice: Undefined index: _media_image
  • Notice: Undefined index: _media_is_disabled
  • Notice: Undefined index: _attribute_set

make sure, to fill each field with a meaningful value. These errors occur if you import several images / categories per product.

Sunday, September 28, 2014

Magento REST API

Not really easy to extend the REST API,  here some info which might help.

Mapping REST Operation to Magento:


// Map HTTP methods to classic CRUD verbs
$operationByMethod = array(
    'GET'    => Mage_Api2_Model_Resource::OPERATION_RETRIEVE,
    'POST'   => Mage_Api2_Model_Resource::OPERATION_CREATE,
    'PUT'    => Mage_Api2_Model_Resource::OPERATION_UPDATE,
    'DELETE' => Mage_Api2_Model_Resource::OPERATION_DELETE
);

Important insight to understand how magento decides where to route your request,
see core/Mage/Api2/Model/Mage_Api2_Model_Resource. If you don't get the desired results, check if ACTION_TYPE_xxx is set right, i.e only ACTION_TYPE_COLLECTION is allowed for OPERATION_CREATE.


public function dispatch()
{
    switch ($this->getActionType() . $this->getOperation()) {
        /* Create */
        case self::ACTION_TYPE_ENTITY . self::OPERATION_CREATE:
            // Creation of objects is possible only when working with collection
            $this->_critical(self::RESOURCE_METHOD_NOT_IMPLEMENTED);
            break;
        case self::ACTION_TYPE_COLLECTION . self::OPERATION_CREATE:
            // If no of the methods(multi or single) is implemented, request body is not checked
            if (!$this->_checkMethodExist('_create') && !$this->_checkMethodExist('_multiCreate')) {
                $this->_critical(self::RESOURCE_METHOD_NOT_IMPLEMENTED);
            }
            // If one of the methods(multi or single) is implemented, request body must not be empty
            $requestData = $this->getRequest()->getBodyParams();
            if (empty($requestData)) {
                $this->_critical(self::RESOURCE_REQUEST_DATA_INVALID);
            }
            // The create action has the dynamic type which depends on data in the request body
            if ($this->getRequest()->isAssocArrayInRequestBody()) {
                $this->_errorIfMethodNotExist('_create');
                $filteredData = $this->getFilter()->in($requestData);
                if (empty($filteredData)) {
                    $this->_critical(self::RESOURCE_REQUEST_DATA_INVALID);
                }
                $newItemLocation = $this->_create($filteredData);
                $this->getResponse()->setHeader('Location', $newItemLocation);
            } else {
                $this->_errorIfMethodNotExist('_multiCreate');
                $filteredData = $this->getFilter()->collectionIn($requestData);
                $this->_multiCreate($filteredData);
                $this->_render($this->getResponse()->getMessages());
                $this->getResponse()->setHttpResponseCode(Mage_Api2_Model_Server::HTTP_MULTI_STATUS);
            }
            break;
        /* Retrieve */
        case self::ACTION_TYPE_ENTITY . self::OPERATION_RETRIEVE:
            $this->_errorIfMethodNotExist('_retrieve');
            $retrievedData = $this->_retrieve();
            $filteredData  = $this->getFilter()->out($retrievedData);
            $this->_render($filteredData);
            break;
        case self::ACTION_TYPE_COLLECTION . self::OPERATION_RETRIEVE:
            $this->_errorIfMethodNotExist('_retrieveCollection');
            $retrievedData = $this->_retrieveCollection();
            $filteredData  = $this->getFilter()->collectionOut($retrievedData);
            $this->_render($filteredData);
            break;
        /* Update */
        case self::ACTION_TYPE_ENTITY . self::OPERATION_UPDATE:
            $this->_errorIfMethodNotExist('_update');
            $requestData = $this->getRequest()->getBodyParams();
            if (empty($requestData)) {
                $this->_critical(self::RESOURCE_REQUEST_DATA_INVALID);
            }
            $filteredData = $this->getFilter()->in($requestData);
            if (empty($filteredData)) {
                $this->_critical(self::RESOURCE_REQUEST_DATA_INVALID);
            }
            $this->_update($filteredData);
            break;
        case self::ACTION_TYPE_COLLECTION . self::OPERATION_UPDATE:
            $this->_errorIfMethodNotExist('_multiUpdate');
            $requestData = $this->getRequest()->getBodyParams();
            if (empty($requestData)) {
                $this->_critical(self::RESOURCE_REQUEST_DATA_INVALID);
            }
            $filteredData = $this->getFilter()->collectionIn($requestData);
            $this->_multiUpdate($filteredData);
            $this->_render($this->getResponse()->getMessages());
            $this->getResponse()->setHttpResponseCode(Mage_Api2_Model_Server::HTTP_MULTI_STATUS);
            break;
        /* Delete */
        case self::ACTION_TYPE_ENTITY . self::OPERATION_DELETE:
            $this->_errorIfMethodNotExist('_delete');
            $this->_delete();
            break;
        case self::ACTION_TYPE_COLLECTION . self::OPERATION_DELETE:
            $this->_errorIfMethodNotExist('_multiDelete');
            $requestData = $this->getRequest()->getBodyParams();
            if (empty($requestData)) {
                $this->_critical(self::RESOURCE_REQUEST_DATA_INVALID);
            }
            $this->_multiDelete($requestData);
            $this->getResponse()->setHttpResponseCode(Mage_Api2_Model_Server::HTTP_MULTI_STATUS);
            break;
        default:
            $this->_critical(self::RESOURCE_METHOD_NOT_IMPLEMENTED);
            break;
    }
}

Sunday, September 14, 2014

How to get Magento Urls

(for my own reference)

Base Url , Skin Url , Media Url , Js Url , Store Url and Current Url Get Url in phtml files

  • Base Url : Mage::getBaseUrl(); 
  • Skin Url : Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_SKIN); 
  • Unsecure Skin Url : $this->getSkinUrl('images/image_name.jpg'); 
  • Secure Skin Url : $this->getSkinUrl('images/image_name.gif', array('_secure'=>true)); 
  • Media Url : Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_MEDIA); 
  • Js Url : Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_JS); 
  • Store Url : Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB); 
  • Current Url Mage::helper('core/url')->getCurrentUrl(); 

Urls in cms pages or static blocks

  • Base Url : {{store url=""}} 
  • Skin Url : {{skin url='images/image_name.jpg'}} 
  • Media Url : {{media url='/image_name.jpg'}} 
  • Store Url : {{store url='somepage.html'}}