Blog Post

Extending the Magento REST API (part 1)


code

Back in the Spring of 2012, Magento released their REST API as part of Magento CE 1.7 and Magento Enterprise 1.12.

The REST API allows you as a developer to expose various data entities suh as customer, catalog and order information to third party applications. A good example of this would be Facebook apps.

While starting to work on my Magento and Pimcore integration I needed to be able to pull catalog information from Magento to populate data objects which will be used to display product information directly within Pimcore so the REST API seems like the obvious way to get this information into Pimcore.

However I soon found that I needed extra information that the standard REST API doesn't provide so went about extending the api so I can add my own methods.

Over the next few articles I'll be detailing how I have achieved this and hope this will be prove useful to others.

Part 1: Extending the REST API with a new REST resource

As part of the initial planning for this I decided that I didn't want to overwrite any core Magento behaviour and that my API resources would be completely separate from the core Magento resources.

To start set up your Magento module directory structure as follows:

 

As you can probably gather I am going to create a new catalog REST resource.  This is going to be an Admin accessible resource so your REST client will need to have an admin profile set up (if you aren't sure about doing this take a look at the Magento wiki at http://www.magentocommerce.com/wiki/doc/webservices-api/introduction_to_rest_api).

First thing to now do is create your module definition file in app/etc/modules (not in the above folder diagram).  For my extension this is called MagePim_Extapi.xml.  The file should contain the usual extension definition so Magento knows about your extension.

<?xml version="1.0"?>
<config>
    <modules>
        <MagePim_Extapi>
            <active>true</active>
            <codePool>community</codePool>
         </MagePim_Extapi>
    </modules>
</config>

Next we need to start setting up our extensions configuration.  We need 3 files for this in our extension's etc folder; config.xml, api.xml and api2.xml

 

config.xml

<?xml version="1.0"?>
<config>
	<modules>
		<MagePim_Extapi>
			<version>0.1.0</version>
		</MagePim_Extapi>
	</modules>
	<global>
		<models>
			<extapi>
				<class>MagePim_Extapi_Model</class>
			</extapi>
		</models>
	</global>
</config>

All config.xml does is register the extensions model.  No overwriting of core Magento is needed here as our API resources are going to be separate to the core Magento ones.

api.xml

<?xml version="1.0"?>
<config>
    <api>
        <resources>
            <extapi_catalog translate="title" module="extapi">
                <model>extapi/catalog_api2</model>
                <title>Extapi Catalog API</title>
                <acl>extcatalog</acl>
                <methods>
                    <list translate="title" module="extapi">
                        <title>Retrieve Product Count</title>
                        <method>count</method>
                        <acl>extcatalog/info</acl>
                    </list>
                </methods>
                <faults module="extapi">
                    <data_invalid>
                        <code>100</code>
                        <message>Invalid Request. Details in error message.</message>
                    </data_invalid>
                    <filters_invalid>
                        <code>101</code>
                        <message>Invalid filters specified. Details in error message.</message>
                    </filters_invalid>
                    <not_exists>
                        <code>102</code>
                        <message>No products.</message>
                    </not_exists>
                    <not_deleted>
                        <code>103</code>
                        <message>Product not deleted. Details in error message.</message>
                    </not_deleted>
                </faults>
            </extapi_catalog>
        </resources>
        <v2>
            <resources_function_prefix>
                <extapi_catalog>extapi_catalog</extapi_catalog>
            </resources_function_prefix>
        </v2> 
        <acl>
            <resources>
                <extapi_catalog translate="title" module="extapi">
                    <title>Catalog</title>
                    <sort_order>3</sort_order>
                    <info translate="title" module="extapi">
                        <title>Retrieve product count</title>
                    </info>
                </extapi_catalog>
            </resources>
        </acl>
    </api>
</config>

As you can see this is a bit more involved and is mainly to do with setting permissions for the API resource.

api2.xml

<?xml version="1.0"?>
<config>
    <api2>
        <resource_groups>
            <extapi translate="title" module="api2">
                <title>Magepim API calls</title>
                <sort_order>30</sort_order>
                <children>
                    <extapi_product translate="title" module="api2">
                        <title>Product</title>
                        <sort_order>50</sort_order>
                    </extapi_product>
                </children>
            </extapi>
        </resource_groups>
        <resources>
            <extapiproducts translate="title" module="api2">
                <group>extapi_product</group>
                <model>extapi/catalog_api2_product</model>
                <working_model>extapi/catalog_api2_product</working_model>
                <title>Catalog Product</title>
                <sort_order>10</sort_order>
                <privileges>
                    <admin>
                        <create>1</create>
                        <retrieve>1</retrieve>
                        <update>1</update>
                        <delete>1</delete>
                    </admin>
                </privileges>
                <attributes translate="product_count" module="api2">
                    <product_count>Product Count</product_count>
                    <catalog_size>Product Count</catalog_size>
                </attributes>
                <entity_only_attributes>
                    <catalog>
                        <read>
                            <has_custom_options>1</has_custom_options>
                            <tier_price>1</tier_price>
                            <total_reviews_count>1</total_reviews_count>
                            <url>1</url>
                            <buy_now_url>1</buy_now_url>
                            <has_custom_options>1</has_custom_options>
                            <is_in_stock>1</is_in_stock>
                            
                        </read>
                    </catalog>
                    </entity_only_attributes>
                <exclude_attributes>
                    <catalog>
                        <read>
                            <attribute_set_id>1</attribute_set_id>
                            <stock_data>1/</stock_data>
                            <use_config_gift_message_available>1</use_config_gift_message_available>
                            <use_config_gift_wrapping_available>1</use_config_gift_wrapping_available>
                            <url_key_create_redirect>1</url_key_create_redirect>
                            
                        </read>
                    </catalog>
                    <admin>
                        <read>
                            <product_count>1</product_count>
                        </read>
                    </admin>
                </exclude_attributes>
                <routes>
                    <route_entity_count>
                        <route>/magepim/products/count</route>
                        <action_type>entity</action_type>
                    </route_entity_count>
                </routes>
                <versions>1</versions>
            </extapiproducts>
        </resources>
    </api2>
</config>

 

We are most interested in lines 17 - 73 here as this is where we set up the majority of the configuration of the API resource.

On lines 19 & 20 we tell Magento the name of the models used in the API calls then in the <privileges> section say what our admin user can do here (we will only have a readable resouce initially but it's best to make sure and cover security bases from the start).  You will also notice I have added read permissions in for API users with a customer role.  We are not using them at the moment so they can be left out of need be.

Lines 66 - 71 set up the attributes that are to be made available in the REST response.  For the moment I only want to return  the product_count attribute which is going to tell me how many products are in the catalog.

The final part of api2.xml is the REST route.  This is basically a front controller route for the API. We won't set up any actual controller classes but Magento needs to know about the routes that API calls will try to access.  When Magento gets a REST API call it will use this and then pass requests off to the model that was definied earlier.

Ok, so that's the xml sorted.  Now all we need to do is write the API class to handle the REST request.

 

In the admin folder we created earlier we need to create a file called V1.php.  This is going to do the actual work in Magento and pass back the catalog size.

V1.php

<?php
 
/**
 * Override for Magento's Catalog REST API
 */
class Magepim_Extapi_Model_Catalog_Api2_Product_Rest_Admin_V1 extends Mage_Catalog_Model_Api2_Product_Rest {
 
    /**
     * Retrieves the catalog collection and returns it's size
     *
     * @return int
     */

    protected function _retrieve()
    {
        /** @var $collection Mage_Catalog_Model_Resource_Product_Collection */
        $collection = Mage::getResourceModel('catalog/product_collection');
        $store = $this->_getStore();
        $collection->setStoreId($store->getId());
        $collection->addAttributeToSelect(array_keys(
                $this->getAvailableAttributes($this->getUserType(), Mage_Api2_Model_Resource::OPERATION_ATTRIBUTE_READ)
        ));
        $this->_applyCategoryFilter($collection);
        $this->_applyCollectionModifiers($collection);
        $products = $collection->load()->toArray();
        $size = $collection->getSize();
        $productCount = new stdClass();
        $productCount->catalog_size=$size;
        return $productCount;
    }
}

 

That's basically it.  Now a REST API call from a client application with a configured Admin role just needs to go to https://your-magento-host/api/rest/magepim/products/count and it should receive some Json with your catalog size in it.

comments powered by Disqus