├── .gitignore
├── src
└── app
│ ├── locale
│ ├── en_US
│ │ └── TS
│ │ │ └── ApiPlus
│ │ │ ├── Adminhtml.csv
│ │ │ └── Frontend.csv
│ └── pt_BR
│ │ └── TS
│ │ └── ApiPlus
│ │ ├── Adminhtml.csv
│ │ └── Frontend.csv
│ ├── code
│ └── community
│ │ └── TS
│ │ └── ApiPlus
│ │ ├── Exception.php
│ │ ├── Helper
│ │ └── Data.php
│ │ ├── Controller
│ │ └── Front
│ │ │ └── Action.php
│ │ ├── controllers
│ │ └── JsonController.php
│ │ ├── etc
│ │ ├── api.xml
│ │ ├── adminhtml.xml
│ │ ├── config.xml
│ │ └── system.xml
│ │ ├── Model
│ │ ├── Config.php
│ │ ├── Http
│ │ │ ├── Response.php
│ │ │ └── Request.php
│ │ └── Server
│ │ │ └── Handler.php
│ │ └── Trait
│ │ ├── Config.php
│ │ ├── Http.php
│ │ └── Data.php
│ └── etc
│ └── modules
│ └── TS_ApiPlus.xml
├── modman
├── dev
└── tests
│ └── apiplus
│ ├── tests
│ ├── DataTest.php
│ └── AliasTest.php
│ ├── AbstractTest.php
│ ├── phpunit.xml.dist
│ └── bootstrap.php
├── setup
└── run.sh
├── LICENSE.txt
├── .travis.yml
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/app/locale/en_US/TS/ApiPlus/Adminhtml.csv:
--------------------------------------------------------------------------------
1 | "API Plus","API Plus"
2 | "Configuration","Configuration"
3 | "API Plus Settings","API Plus Settings"
4 | "Enabled","Enabled"
5 | "Enable Result Caching","Enable Result Caching"
6 | "Result Caching Lifetime","Result Caching Lifetime"
7 |
--------------------------------------------------------------------------------
/modman:
--------------------------------------------------------------------------------
1 | src/app/code/community/TS/ApiPlus app/code/community/TS/ApiPlus
2 | src/app/etc/modules/TS_ApiPlus.xml app/etc/modules/TS_ApiPlus.xml
3 | src/app/locale/en_US/TS/ApiPlus app/locale/en_US/TS/ApiPlus
4 | src/app/locale/pt_BR/TS/ApiPlus app/locale/pt_BR/TS/ApiPlus
5 |
--------------------------------------------------------------------------------
/src/app/locale/pt_BR/TS/ApiPlus/Adminhtml.csv:
--------------------------------------------------------------------------------
1 | "API Plus","API Plus"
2 | "Configuration","Configuração"
3 | "API Plus Settings","Configurações API Plus"
4 | "Enabled","Habilitado"
5 | "Enable Result Caching","Habilitar Cache de Resultado"
6 | "Result Caching Lifetime","Tempo de Vida do Cache de Resultado"
7 |
--------------------------------------------------------------------------------
/dev/tests/apiplus/tests/DataTest.php:
--------------------------------------------------------------------------------
1 | getFaults();
11 |
12 | $this->assertInternalType('array', $faults, 'Faults must be an array.');
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/dev/tests/apiplus/AbstractTest.php:
--------------------------------------------------------------------------------
1 |
14 | */
15 | class TS_ApiPlus_Exception extends Mage_Core_Exception
16 | {
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/app/code/community/TS/ApiPlus/Helper/Data.php:
--------------------------------------------------------------------------------
1 |
14 | */
15 | class TS_ApiPlus_Helper_Data extends Mage_Core_Helper_Data
16 | {
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/dev/tests/apiplus/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 | tests
14 |
15 |
--------------------------------------------------------------------------------
/src/app/locale/pt_BR/TS/ApiPlus/Frontend.csv:
--------------------------------------------------------------------------------
1 | "There was a problem in the request.","Houve um problema na sua requisição."
2 | "Your account has been deactivated.","Sua conta foi desativada."
3 | "Access denied.","Acesso negado."
4 | "Unable to login.","Não foi possível logar."
5 | "There is no resource method defined in your request. Please check it and try again.","Não existe um método de recurso definido na sua requisição. Por favor, verifique-a e tente novamente."
6 | "Your credentials are incorrect. Please verify the username and password.","Suas credenciais estão incorretas. Por favor, verifique o nome de usuário e senha."
7 |
--------------------------------------------------------------------------------
/src/app/locale/en_US/TS/ApiPlus/Frontend.csv:
--------------------------------------------------------------------------------
1 | "There was a problem in the request.","There was a problem in the request."
2 | "Your account has been deactivated.","Your account has been deactivated."
3 | "Access denied.","Access denied.","Access denied.","Access denied."
4 | "Unable to login.","Unable to login."
5 | "There is no resource method defined in your request. Please check it and try again.","There is no resource method defined in your request. Please check it and try again."
6 | "Your credentials are incorrect. Please verify the username and password.","Your credentials are incorrect. Please verify the username and password."
7 |
--------------------------------------------------------------------------------
/src/app/code/community/TS/ApiPlus/Controller/Front/Action.php:
--------------------------------------------------------------------------------
1 |
14 | */
15 | class TS_ApiPlus_Controller_Front_Action extends Mage_Core_Controller_Front_Action
16 | {
17 |
18 | use TS_ApiPlus_Trait_Data,
19 | TS_ApiPlus_Trait_Http;
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/src/app/code/community/TS/ApiPlus/controllers/JsonController.php:
--------------------------------------------------------------------------------
1 |
14 | */
15 | class TS_ApiPlus_JsonController extends TS_ApiPlus_Controller_Front_Action
16 | {
17 |
18 | public function indexAction()
19 | {
20 | $apiRequest = $this->getApiRequest();
21 | $apiRequest->dispatch();
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/src/app/etc/modules/TS_ApiPlus.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
20 | true
21 | community
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/dev/tests/apiplus/bootstrap.php:
--------------------------------------------------------------------------------
1 | assertInstanceOf('TS_ApiPlus_Helper_Data', $helper);
10 | }
11 |
12 |
13 | public function testModelConfig()
14 | {
15 | $model = Mage::getModel('ts_apiplus/config');
16 | $this->assertInstanceOf('TS_ApiPlus_Model_Config', $model);
17 | }
18 |
19 |
20 | public function testModelServerHandler()
21 | {
22 | $model = Mage::getModel('ts_apiplus/server_handler');
23 | $this->assertInstanceOf('TS_ApiPlus_Model_Server_Handler', $model);
24 | }
25 |
26 |
27 | public function testModelHttpRequest()
28 | {
29 | $model = Mage::getConfig()->getModelClassName('ts_apiplus/http_request');
30 | $this->assertEquals('TS_ApiPlus_Model_Http_Request', $model);
31 | }
32 |
33 |
34 | public function testModelHttpResponse()
35 | {
36 | $model = Mage::getModel('ts_apiplus/http_response');
37 | $this->assertInstanceOf('TS_ApiPlus_Model_Http_Response', $model);
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 | php:
3 | - 5.3
4 | - 5.4
5 | - 5.5
6 | - 5.6
7 | - 7.0
8 |
9 | matrix:
10 | allow_failures:
11 | - php: 5.3
12 | - php: 7.0
13 | fast_finish: true
14 |
15 | env:
16 | global:
17 | - MAGENTO_DB_ALLOWSAME=1
18 | - SKIP_CLEANUP=1
19 | - TEST_BASEDIR=.modman/ApiPlus/dev/tests/apiplus
20 | matrix:
21 | - MAGENTO_VERSION=magento-mirror-1.9.2.4
22 | - MAGENTO_VERSION=magento-mirror-1.9.2.3
23 | - MAGENTO_VERSION=magento-mirror-1.9.2.2
24 | - MAGENTO_VERSION=magento-mirror-1.9.2.1
25 | - MAGENTO_VERSION=magento-mirror-1.9.2.0
26 | - MAGENTO_VERSION=magento-mirror-1.9.1.1
27 | - MAGENTO_VERSION=magento-mirror-1.9.1.0
28 | - MAGENTO_VERSION=magento-mirror-1.9.0.1
29 | - MAGENTO_VERSION=magento-mirror-1.9.0.0
30 | - MAGENTO_VERSION=magento-mirror-1.8.1.0
31 | - MAGENTO_VERSION=magento-mirror-1.8.0.0
32 | - MAGENTO_VERSION=magento-mirror-1.7.0.2
33 |
34 | mysql:
35 | database: magento
36 | username: root
37 | encoding: utf8
38 |
39 | script:
40 | - bash ./setup/run.sh
41 |
42 | notifications:
43 | email:
44 | recipients:
45 | - tiago@tiagosampaio.com
46 | on_success: always
47 | on_failure: always
48 |
--------------------------------------------------------------------------------
/src/app/code/community/TS/ApiPlus/etc/api.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
20 |
21 | 500
22 |
23 |
24 | 500
25 |
26 |
27 | 401
28 |
29 |
30 | 405
31 |
32 |
33 | 405
34 |
35 |
36 | 410
37 |
38 |
39 | 400
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/src/app/code/community/TS/ApiPlus/Model/Config.php:
--------------------------------------------------------------------------------
1 |
14 | */
15 | class TS_ApiPlus_Model_Config extends Mage_Api_Model_Config
16 | {
17 |
18 | use TS_ApiPlus_Trait_Data;
19 |
20 | /** @var string */
21 | const CACHE_TAG = 'API_PLUS_RESULTS';
22 |
23 |
24 | /**
25 | * @param string|null $resourceName
26 | *
27 | * @return array
28 | */
29 | public function getFaults($resourceName = null)
30 | {
31 | if (is_null($resourceName)
32 | || !isset($this->getResources()->$resourceName)
33 | || !isset($this->getResources()->$resourceName->faults)) {
34 | $faultsNode = $this->getNode('faults');
35 | } else {
36 | $faultsNode = $this->getResources()->$resourceName->faults;
37 | }
38 | /* @var $faultsNode Varien_Simplexml_Element */
39 |
40 | $translateModule = 'api';
41 |
42 | if (isset($faultsNode['module'])) {
43 | $translateModule = (string) $faultsNode['module'];
44 | }
45 |
46 | $faults = array();
47 |
48 | foreach ($faultsNode->children() as $faultName => $fault) {
49 | $faults[$faultName] = array(
50 | 'code' => (string) $fault->code,
51 | 'http_code' => (int) $fault->http_code,
52 | 'message' => Mage::helper($translateModule)->__((string)$fault->message)
53 | );
54 | }
55 |
56 | return $faults;
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/src/app/code/community/TS/ApiPlus/Trait/Config.php:
--------------------------------------------------------------------------------
1 |
14 | */
15 | trait TS_ApiPlus_Trait_Config
16 | {
17 |
18 | /**
19 | * @param string $section
20 | * @param string $group
21 | * @param string $field
22 | * @param int|Mage_Core_Model_Store $store
23 | *
24 | * @return mixed
25 | */
26 | protected function getGlobalConfig($section, $group, $field, $store = null)
27 | {
28 | $configPath = implode('/', array($section, $group, $field));
29 | return Mage::getStoreConfig($configPath, $store);
30 | }
31 |
32 |
33 | /**
34 | * @param string $field
35 | * @param int|Mage_Core_Model_Store $store
36 | *
37 | * @return mixed
38 | */
39 | protected function getApiPlusConfig($field, $store = null)
40 | {
41 | return $this->getGlobalConfig('api', 'api_plus', $field, $store);
42 | }
43 |
44 |
45 | /**
46 | * @param Mage_Core_Model_Store $store
47 | *
48 | * @return bool
49 | */
50 | protected function isEnabled($store = null)
51 | {
52 | return (bool) $this->getApiPlusConfig('enabled', $store);
53 | }
54 |
55 |
56 | /**
57 | * @param Mage_Core_Model_Store $store
58 | *
59 | * @return bool
60 | */
61 | protected function isResultCacheEnabled($store = null)
62 | {
63 | return (bool) $this->getApiPlusConfig('cache_enabled', $store);
64 | }
65 |
66 |
67 | /**
68 | * @param Mage_Core_Model_Store $store
69 | *
70 | * @return int
71 | */
72 | protected function getResultCacheLifetime($store = null)
73 | {
74 | return (int) $this->getApiPlusConfig('cache_lifetime', $store);
75 | }
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/src/app/code/community/TS/ApiPlus/etc/adminhtml.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | API Plus
28 | 1000
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
59 |
60 |
--------------------------------------------------------------------------------
/src/app/code/community/TS/ApiPlus/Trait/Http.php:
--------------------------------------------------------------------------------
1 |
14 | */
15 | trait TS_ApiPlus_Trait_Http
16 | {
17 |
18 | /**
19 | * @param int $code
20 | * @param null $message
21 | *
22 | * @return void
23 | *
24 | * @throws Zend_Controller_Response_Exception
25 | */
26 | protected function sendHttpSuccessResponse($code, $message = null, $additionalData = array())
27 | {
28 | $data = array(
29 | 'error' => false,
30 | 'message' => $message
31 | );
32 |
33 | if (!empty($additionalData) && is_array($additionalData)) {
34 | foreach ((array) $additionalData as $key => $value) {
35 | $data[$key] = $value;
36 | }
37 | }
38 |
39 | $this->sendHttpResponse($code, $data);
40 | }
41 |
42 | /**
43 | * @param int $code
44 | * @param null $message
45 | *
46 | * @return void
47 | *
48 | * @throws Zend_Controller_Response_Exception
49 | */
50 | protected function sendHttpErrorResponse($code, $message = null, $additionalData = array())
51 | {
52 | $data = array(
53 | 'error' => true,
54 | 'message' => $message
55 | );
56 |
57 | if (!empty($additionalData) && is_array($additionalData)) {
58 | foreach ((array) $additionalData as $key => $value) {
59 | $data[$key] = $value;
60 | }
61 | }
62 |
63 | $this->sendHttpResponse($code, $data);
64 | }
65 |
66 |
67 | /**
68 | * @param string $code
69 | * @param array $data
70 | *
71 | * @throws Zend_Controller_Response_Exception
72 | */
73 | protected function sendHttpResponse($code, $data = array())
74 | {
75 | $this->getHttpResponse()->setHttpResponseCode($code);
76 | $this->getHttpResponse()->setBody(Zend_Json_Encoder::encode($data));
77 | $this->getHttpResponse()->sendResponse();
78 |
79 | die();
80 | }
81 |
82 |
83 | /**
84 | * @return Mage_Core_Controller_Response_Http
85 | */
86 | protected function getHttpResponse()
87 | {
88 | return Mage::app()->getResponse();
89 | }
90 |
91 |
92 | /**
93 | * @return Mage_Core_Controller_Request_Http
94 | */
95 | protected function getHttpRequest()
96 | {
97 | return Mage::app()->getRequest();
98 | }
99 |
100 | }
101 |
--------------------------------------------------------------------------------
/src/app/code/community/TS/ApiPlus/etc/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
20 | 0.1.0.0
21 |
22 |
23 |
24 |
25 |
26 | TS_ApiPlus_Model
27 |
28 |
29 |
30 |
31 | TS_ApiPlus_Block
32 |
33 |
34 |
35 |
36 | TS_ApiPlus_Helper
37 |
38 |
39 |
40 |
41 |
42 |
43 | API Plus Results will be cached if this option and API Plus config are enabled (System > Configuration > Api > API Plus Settings).
44 | API_PLUS_RESULTS
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | TS/ApiPlus/Frontend.csv
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 | TS_ApiPlus
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | TS/ApiPlus/Adminhtml.csv
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 | 1
84 | 1
85 | 7200
86 |
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/src/app/code/community/TS/ApiPlus/Model/Http/Response.php:
--------------------------------------------------------------------------------
1 |
15 | */
16 | class TS_ApiPlus_Model_Http_Response
17 | {
18 |
19 | /** 2XX Codes - Successful */
20 | const HTTP_OK = 200;
21 | const HTTP_CREATED = 201;
22 | const HTTP_ACCEPTED = 202;
23 | const HTTP_NON_AUTHORITATIVE_INFORMATION = 203;
24 | const HTTP_NO_CONTENT = 204;
25 | const HTTP_RESET_CONTENT = 205;
26 | const HTTP_PARTIAL_CONTENT = 206;
27 |
28 | /** 3XX Codes - Redirection */
29 | const HTTP_MULTIPLE_CHOICES = 300;
30 | const HTTP_MOVED_PERMANENTLY = 301;
31 | const HTTP_FOUND = 302;
32 | const HTTP_SEE_OTHER = 303;
33 | const HTTP_NOT_MODIFIED = 304;
34 | const HTTP_USED_PROXY = 305;
35 | const HTTP_TEMPORARY_REDIRECT = 307;
36 |
37 | /** 4XX Codes - Client Error*/
38 | const HTTP_BAD_REQUEST = 400;
39 | const HTTP_UNAUTHORIZED = 401;
40 | const HTTP_PAYMENT_REQUIRED = 402;
41 | const HTTP_FORBIDDEN = 403;
42 | const HTTP_NOT_FOUND = 404;
43 | const HTTP_METHOD_NOT_ALLOWED = 405;
44 | const HTTP_NOT_ACCEPTABLE = 406;
45 | const HTTP_PROXY_AUTHENTICATION_REQUIRED = 407;
46 | const HTTP_REQUEST_TIMEOUT = 408;
47 | const HTTP_CONFLICT = 409;
48 | const HTTP_GONE = 410;
49 | const HTTP_LENGTH_REQUIRED = 411;
50 | const HTTP_PRECONDITION_FAILED = 412;
51 | const HTTP_REQUEST_ENTITY_TOO_LARGE = 413;
52 | const HTTP_REQUEST_URI_TOO_LONG = 414;
53 | const HTTP_UNSUPPORTED_MEDIA_TYPE = 415;
54 | const HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
55 | const HTTP_EXPECTATION_FAILED = 417;
56 |
57 | /** 5XX Codes - Server Error */
58 | const HTTP_INTERNAL_SERVER_ERROR = 500;
59 | const HTTP_NOT_IMPLEMENTED = 501;
60 | const HTTP_BAD_GATEWAY = 502;
61 | const HTTP_SERVICE_UNAVAILABLE = 503;
62 | const HTTP_GATEWAY_TIMEOUT = 504;
63 | const HTTP_HTTP_VERSION_NOT_SUPPORTED = 505;
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/src/app/code/community/TS/ApiPlus/etc/system.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | text
24 | 100
25 | 1
26 | 1
27 | 1
28 |
29 |
30 |
31 | select
32 | adminhtml/system_config_source_yesno
33 | 10
34 | 1
35 | 1
36 | 1
37 |
38 |
39 |
40 | select
41 | adminhtml/system_config_source_yesno
42 | 20
43 | 1
44 | 1
45 | 1
46 |
47 | 1
48 |
49 |
50 |
51 |
52 | text
53 | 30
54 | 1
55 | 1
56 | 1
57 | validate-not-negative-number
58 |
59 | 1
60 | 1
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/src/app/code/community/TS/ApiPlus/Trait/Data.php:
--------------------------------------------------------------------------------
1 |
14 | */
15 | trait TS_ApiPlus_Trait_Data
16 | {
17 |
18 | use TS_ApiPlus_Trait_Config;
19 |
20 |
21 | /**
22 | * @return TS_ApiPlus_Model_Server_Handler
23 | */
24 | protected function getApiServerHandler()
25 | {
26 | return Mage::getSingleton('ts_apiplus/server_handler');
27 | }
28 |
29 |
30 | /**
31 | * @return TS_ApiPlus_Model_Http_Request
32 | */
33 | protected function getApiRequest()
34 | {
35 | return Mage::getSingleton('ts_apiplus/http_request');
36 | }
37 |
38 |
39 | /**
40 | * @return TS_ApiPlus_Model_Http_Response
41 | */
42 | protected function getApiResponse()
43 | {
44 | return Mage::getSingleton('ts_apiplus/http_response');
45 | }
46 |
47 |
48 | /**
49 | * @return bool
50 | */
51 | protected function canUserResultCache()
52 | {
53 | if (!$this->isResultCacheEnabled()) {
54 | return false;
55 | }
56 |
57 | if (!$this->getCoreCacheInstance()->canUse('api_plus_results')) {
58 | return false;
59 | }
60 |
61 | return true;
62 | }
63 |
64 |
65 | /**
66 | * @return Mage_Core_Model_Cache
67 | */
68 | protected function getCoreCacheInstance()
69 | {
70 | return Mage::getSingleton('core/cache');
71 | }
72 |
73 |
74 | /**
75 | * Get the common helper.
76 | *
77 | * @return TS_ApiPlus_Helper_Data
78 | */
79 | protected function helper()
80 | {
81 | return Mage::helper('ts_apiplus');
82 | }
83 |
84 |
85 | /**
86 | * Retrieve the class group of the self object.
87 | *
88 | * @return string
89 | */
90 | protected function getClassGroupName()
91 | {
92 | $classGroup = strtolower($this->getClassGroup());
93 |
94 | if ('mage' === substr($classGroup, 0, 4)) {
95 | $classGroup = substr($classGroup, 5, strlen($classGroup) - 5);
96 | }
97 |
98 | return $classGroup;
99 | }
100 |
101 |
102 | /**
103 | * Retrieve helper module name
104 | *
105 | * @return string
106 | */
107 | protected function getClassGroup()
108 | {
109 | $className = get_class($this);
110 | $classGroup = substr($className, 0, strpos($className, '_', strpos($className, '_') + 1));
111 |
112 | if (!class_exists($classGroup . '_Helper_Data')) {
113 | $classGroup = 'Mage_Core';
114 | }
115 |
116 | return $classGroup;
117 | }
118 |
119 |
120 | /**
121 | * Translate
122 | *
123 | * @return string
124 | */
125 | public function __()
126 | {
127 | $args = func_get_args();
128 | $expr = new Mage_Core_Model_Translate_Expr(array_shift($args), $this->getClassGroup());
129 | array_unshift($args, $expr);
130 |
131 | return Mage::app()->getTranslator()->translate($args);
132 | }
133 |
134 | }
135 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # API Plus for Magento
2 |
3 | [](https://travis-ci.org/tiagosampaio/ApiPlus)
4 | [](#)
5 | [](https://github.com/tiagosampaio/ApiPlus/issues)
6 | [](https://github.com/tiagosampaio/ApiPlus/network)
7 | [](https://raw.githubusercontent.com/tiagosampaio/ApiPlus/master/LICENSE.txt)
8 |
9 | Rather than using (slow) SOAP to make calls to Magento's API why not to simply send a *POST* to an endpoint provinding your authentication data in request header and a JSON-encoded body with the resource name you want to consume and arguments needed for the call?
10 |
11 | API Plus for Magento is a module that improves how Magendo API can be consumed by third party applications. By using API Plus in your Magento store you make the API connection much eaiser but with the same abstraction layer and providing the same flexibility and security that Magento platform already provides for all its community.
12 |
13 | ## NOTE
14 |
15 | This documentation is not complete but I'm working on it to improve and make it better everytime I have a little free time.
16 |
17 | ## Features
18 |
19 | - **Much easier!**: API Plus is much, much, much easier to be used in your Magento platform. By using it you don't need to make SOAP calls anymore.
20 | - **Flexibility**: API Plus uses the Magento API's abstraction so, the same flexibility is provided by API Plus.
21 | - **Security**: API Plus is as secure as Magento's authentication system.
22 | - **Performance**: By using API Plus your API connections and results will be much faster then using the default SOAP calls.
23 |
24 | ## Authors, contributors and maintainers
25 |
26 | Author:
27 | - [Tiago Sampaio](http://tiagosampaio.com)
28 |
29 | ## Compability
30 |
31 | - PHP:
32 | - 5.4
33 | - 5.5
34 | - 5.6
35 | - Magento CE:
36 | - 1.6.x
37 | - 1.7.x
38 | - 1.8.x
39 | - 1.9.x
40 | - Magento EE:
41 | - 1.11.x
42 | - 1.12.x
43 | - 1.13.x
44 | - 1.14.x
45 |
46 | ## Documentation
47 |
48 | ### Basic
49 |
50 | It's quite simple! Rather then using SOAP process described in [Magento Webservice Documentation](http://devdocs.magento.com/guides/m1x/api/soap/introduction.html) all you need to do is to send a POST request to:
51 |
52 | [https://www.yourmagentohost.com/`api/json`](#)
53 |
54 | Providing the following authentication parameters in request header:
55 |
56 | Parameter Key | Parameter Value
57 | --- | ---
58 | `apiUsername` | [Your Magento's API Username]
59 | `apiKey` | [Your Magento's API Secret Key]
60 |
61 | And the body in JSON format:
62 |
63 | ```json
64 | {
65 | "resource": "catalog_product.list"
66 | }
67 | ```
68 |
69 | If you need to send any arguments, like you do in SOAP request for some resources, you simply add a new node called `args` in the JSON request body:
70 |
71 | ```json
72 | {
73 | "resource": "catalog_product.list",
74 | "args": {
75 | "complex_filter": [
76 | {
77 | "key": "type",
78 | "value": {
79 | "key": "in",
80 | "value": "configurable,grouped"
81 | }
82 | }
83 | ]
84 | }
85 | }
86 | ```
87 |
88 | ## Links
89 |
90 | 🇧🇷 [Novo Módulo Magento para Integração com API: API Plus!](http://tiagosampaio.com/novo-modulo-magento-para-integracao-com-api-api-plus/)
91 |
92 | ## License
93 |
94 | (c) 2016 [MIT License](LICENSE.txt) - [Tiago Sampaio](http://tiagosampaio.com/)
95 |
--------------------------------------------------------------------------------
/src/app/code/community/TS/ApiPlus/Model/Server/Handler.php:
--------------------------------------------------------------------------------
1 |
14 | */
15 | class TS_ApiPlus_Model_Server_Handler extends Mage_Api_Model_Server_Handler
16 | {
17 |
18 | use TS_ApiPlus_Trait_Data;
19 |
20 |
21 | /**
22 | * Call resource functionality
23 | *
24 | * @param string $sessionId
25 | * @param string $apiPath
26 | * @param array $args
27 | * @return mixed
28 | */
29 | public function callSimple($apiPath, $args = array())
30 | {
31 | list($resourceName, $methodName) = explode('.', $apiPath);
32 |
33 | if (empty($resourceName) || empty($methodName)) {
34 | /** @todo Return 404 */
35 | $this->_fault('resource_path_invalid');
36 | return $this;
37 | }
38 |
39 | $resourcesAlias = $this->_getConfig()->getResourcesAlias();
40 | $resources = $this->_getConfig()->getResources();
41 | if (isset($resourcesAlias->$resourceName)) {
42 | $resourceName = (string) $resourcesAlias->$resourceName;
43 | }
44 |
45 | if (!isset($resources->$resourceName) || !isset($resources->$resourceName->methods->$methodName)) {
46 | /** @todo Return 404 */
47 | $this->_fault('resource_path_invalid');
48 | return $this;
49 | }
50 |
51 | if (!isset($resources->$resourceName->public)
52 | && isset($resources->$resourceName->acl)
53 | && !$this->_isAllowed((string)$resources->$resourceName->acl)) {
54 | /** @todo Return 503 */
55 | $this->_fault('access_denied');
56 | }
57 |
58 |
59 | if (!isset($resources->$resourceName->methods->$methodName->public)
60 | && isset($resources->$resourceName->methods->$methodName->acl)
61 | && !$this->_isAllowed((string)$resources->$resourceName->methods->$methodName->acl)) {
62 | /** @todo Return 503 */
63 | $this->_fault('access_denied');
64 | }
65 |
66 | $methodInfo = $resources->$resourceName->methods->$methodName;
67 |
68 | try {
69 | $method = (isset($methodInfo->method) ? (string) $methodInfo->method : $methodName);
70 | $modelName = $this->_prepareResourceModelName((string) $resources->$resourceName->model);
71 |
72 | try {
73 | $model = Mage::getModel($modelName);
74 |
75 | if ($model instanceof Mage_Api_Model_Resource_Abstract) {
76 | $model->setResourceConfig($resources->$resourceName);
77 | }
78 | } catch (Exception $e) {
79 | /** @todo Return 503 */
80 | throw new Mage_Api_Exception('resource_path_not_callable');
81 | }
82 |
83 | if (method_exists($model, $method)) {
84 | if (isset($methodInfo->arguments) && ((string)$methodInfo->arguments) == 'array') {
85 | return $model->$method((is_array($args) ? $args : array($args)));
86 | } elseif (!is_array($args)) {
87 | return $model->$method($args);
88 | } else {
89 | return call_user_func_array(array(&$model, $method), $args);
90 | }
91 | } else {
92 | /** @todo Return 503 */
93 | throw new Mage_Api_Exception('resource_path_not_callable');
94 | }
95 | } catch (Mage_Api_Exception $e) {
96 | $this->_fault($e->getMessage(), $resourceName, $e->getCustomMessage());
97 | } catch (Exception $e) {
98 | Mage::logException($e);
99 | /** @todo Return 503 */
100 | $this->_fault('internal', null, $e->getMessage());
101 | }
102 |
103 | return $this;
104 | }
105 |
106 |
107 | /**
108 | * Dispatch webservice fault
109 | *
110 | * @param string $faultName
111 | * @param string $resourceName
112 | * @param string $customMessage
113 | */
114 | protected function _fault($faultName, $resourceName = null, $customMessage = null)
115 | {
116 | $faults = $this->_getConfig()->getFaults($resourceName);
117 |
118 | if (isset($faults[$faultName])) {
119 | $fault = (array) $faults[$faultName];
120 | } else {
121 | $fault = (array) $faults['unknown'];
122 | }
123 |
124 | $httpCode = isset($fault['http_code']) ? $fault['http_code'] : $this->_getDefaultHttpErrorCode();
125 | $message = isset($fault['message']) ? $fault['message'] : $this->_getDefaultHttpErrorMessage();
126 |
127 | if (!is_null($customMessage)) {
128 | $message = $customMessage;
129 | }
130 |
131 | throw Mage::exception('TS_ApiPlus', $message, $httpCode);
132 | }
133 |
134 |
135 | /**
136 | * @return int
137 | */
138 | protected function _getDefaultHttpErrorCode()
139 | {
140 | return TS_ApiPlus_Model_Http_Response::HTTP_INTERNAL_SERVER_ERROR;
141 | }
142 |
143 |
144 | /**
145 | * @return string
146 | */
147 | protected function _getDefaultHttpErrorMessage()
148 | {
149 | return $this->__('There was a problem in the request.');
150 | }
151 |
152 |
153 | /**
154 | * Retrieve webservice configuration
155 | *
156 | * @return TS_ApiPlus_Model_Config
157 | */
158 | protected function _getConfig()
159 | {
160 | return Mage::getSingleton('ts_apiplus/config');
161 | }
162 |
163 | }
164 |
--------------------------------------------------------------------------------
/src/app/code/community/TS/ApiPlus/Model/Http/Request.php:
--------------------------------------------------------------------------------
1 |
14 | */
15 | class TS_ApiPlus_Model_Http_Request
16 | {
17 |
18 | use TS_ApiPlus_Trait_Data,
19 | TS_ApiPlus_Trait_Http;
20 |
21 |
22 | /** @var Mage_Api_Model_User */
23 | protected $_user = null;
24 |
25 | /** @var string */
26 | protected $_data = null;
27 |
28 | /** @var stdClass */
29 | protected $_decodedData = null;
30 |
31 | /** @var string */
32 | protected $_resource = null;
33 |
34 | /** @var string */
35 | protected $_args = null;
36 |
37 |
38 | public function __construct()
39 | {
40 | $this->initUser();
41 | $this->initRequestData();
42 | }
43 |
44 |
45 | /**
46 | * @return bool
47 | */
48 | public function validate()
49 | {
50 | if ($this->getUser()->getId() && $this->getUser()->getIsActive() != '1') {
51 |
52 | $message = $this->__('Your account has been deactivated.');
53 | $this->sendHttpErrorResponse(TS_ApiPlus_Model_Http_Response::HTTP_UNAUTHORIZED, $message);
54 |
55 | } elseif (!Mage::getModel('api/user')->hasAssigned2Role($this->getUser()->getId())) {
56 |
57 | $message = $this->__('Access denied.');
58 | $this->sendHttpErrorResponse(TS_ApiPlus_Model_Http_Response::HTTP_UNAUTHORIZED, $message);
59 |
60 | } else {
61 | if (!$this->getUser()->getId()) {
62 | $message = $this->__('Unable to login.');
63 | $this->sendHttpErrorResponse(TS_ApiPlus_Model_Http_Response::HTTP_UNAUTHORIZED, $message);
64 | }
65 |
66 | }
67 |
68 | return true;
69 | }
70 |
71 |
72 | /**
73 | * Dispatch the request.
74 | */
75 | public function dispatch()
76 | {
77 | try {
78 | $this->validate();
79 |
80 | $result = $this->getResultFromCache();
81 |
82 | if ((false === $result) || empty($result)) {
83 | $result = $this->getApiServerHandler()->callSimple($this->getResource(), $this->getArgs());
84 | $result = Zend_Json_Encoder::encode($result);
85 |
86 | $this->saveResultInCache($result);
87 | }
88 |
89 | $this->getHttpResponse()->setHeader('Content-type', 'application/json', true);
90 | $this->getHttpResponse()->setBody($result);
91 | } catch (Exception $e) {
92 | $this->sendHttpErrorResponse($e->getCode(), $e->getMessage());
93 | }
94 |
95 | $this->getHttpResponse()->sendHeaders();
96 | }
97 |
98 |
99 | /**
100 | * @return Mage_Api_Model_User
101 | */
102 | public function getUser()
103 | {
104 | return $this->_user;
105 | }
106 |
107 |
108 | /**
109 | * @return string
110 | */
111 | public function getData()
112 | {
113 | if (empty($this->_data)) {
114 | $this->_data = file_get_contents('php://input');
115 | }
116 |
117 | return $this->_data;
118 | }
119 |
120 |
121 | /**
122 | * @return mixed|stdClass
123 | *
124 | * @throws Zend_Json_Exception
125 | */
126 | public function getDecodedData()
127 | {
128 | if (empty($this->_decodedData)) {
129 | $this->_decodedData = Zend_Json_Decoder::decode($this->getData(), Zend_Json::TYPE_OBJECT);
130 | }
131 |
132 | return $this->_decodedData;
133 | }
134 |
135 |
136 | /**
137 | * @return string
138 | */
139 | public function getResource()
140 | {
141 | if (empty($this->_resource)) {
142 | $reflection = new ReflectionObject($this->getDecodedData());
143 |
144 | if (false === $reflection->hasProperty('resource')) {
145 | $this->sendHttpErrorResponse(
146 | TS_ApiPlus_Model_Http_Response::HTTP_METHOD_NOT_ALLOWED,
147 | $this->__('There is no resource method defined in your request. Please check it and try again.')
148 | );
149 | }
150 |
151 | $this->_resource = $this->getDecodedData()->resource;
152 | }
153 |
154 | return $this->_resource;
155 | }
156 |
157 |
158 | /**
159 | * @return string
160 | */
161 | public function getArgs()
162 | {
163 | if (empty($this->_args)) {
164 | $this->_args = $this->getDecodedData()->args;
165 | }
166 |
167 | return $this->_args;
168 | }
169 |
170 |
171 | /**
172 | * @return bool|string
173 | */
174 | protected function getResultFromCache()
175 | {
176 | if (!$this->canUserResultCache()) {
177 | return false;
178 | }
179 |
180 | $result = $this->getCoreCacheInstance()->load($this->getCacheKey());
181 |
182 | return $result;
183 | }
184 |
185 |
186 | /**
187 | * @param string $result
188 | *
189 | * @return $this
190 | */
191 | protected function saveResultInCache($result)
192 | {
193 | if (!$this->canUserResultCache()) {
194 | return $this;
195 | }
196 |
197 | $tags = array(TS_ApiPlus_Model_Config::CACHE_TAG);
198 | $lifeTime = $this->getResultCacheLifetime();
199 |
200 | $this->getCoreCacheInstance()->save($result, $this->getCacheKey(), $tags, $lifeTime);
201 |
202 | return $this;
203 | }
204 |
205 |
206 | /**
207 | * @return string
208 | */
209 | protected function getCacheKey()
210 | {
211 | $prefix = 'ts_apiplus_';
212 | $cacheKey = md5($this->getData());
213 | return $prefix . $cacheKey;
214 | }
215 |
216 |
217 | /**
218 | * @return $this
219 | *
220 | * @throws Zend_Controller_Request_Exception
221 | */
222 | protected function initUser()
223 | {
224 | $username = (string) $this->getHttpRequest()->getHeader('apiUsername');
225 | $apiKey = (string) $this->getHttpRequest()->getHeader('apiKey');
226 |
227 | $this->_user = Mage::getModel('api/user');
228 |
229 | if (false == $this->getUser()->authenticate($username, $apiKey)) {
230 | $message = $this->__('Your credentials are incorrect. Please verify the username and password.');
231 | $this->sendHttpErrorResponse(TS_ApiPlus_Model_Http_Response::HTTP_UNAUTHORIZED, $message);
232 | }
233 |
234 | /** @var Mage_Api_Model_Session $session */
235 | $session = Mage::getSingleton('api/session');
236 | $session->setData('user', $this->getUser());
237 | $session->setData('acl', Mage::getResourceModel('api/acl')->loadAcl());
238 |
239 | return $this;
240 | }
241 |
242 |
243 | /**
244 | * @return $this
245 | *
246 | * @throws Zend_Json_Exception
247 | */
248 | protected function initRequestData()
249 | {
250 | if (!($this->getResource())) {
251 | $this->sendHttpErrorResponse(TS_ApiPlus_Model_Http_Response::HTTP_BAD_REQUEST);
252 | }
253 |
254 | return $this;
255 | }
256 |
257 | }
258 |
--------------------------------------------------------------------------------