├── .coveralls.yml
├── .editorconfig
├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── build.xml
├── composer.json
├── phpmd.xml
├── phpunit.xml
├── src
└── Magento
│ └── Client
│ ├── Rest
│ ├── AccessToken.php
│ ├── MagentoOauthPlugin.php
│ ├── MagentoRestClient.php
│ ├── OauthException.php
│ ├── RequestToken.php
│ └── Token.php
│ └── Xmlrpc
│ └── MagentoXmlrpcClient.php
└── test
└── bootstrap.php
/.coveralls.yml:
--------------------------------------------------------------------------------
1 | # for php-coveralls
2 | service_name: travis-ci
3 | src_dir: src
4 | coverage_clover: build/logs/clover.xml
5 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | ; top-most EditorConfig file
2 | root = true
3 |
4 | ; Unix-style newlines
5 | [*]
6 | end_of_line = LF
7 |
8 | [*.php]
9 | indent_style = space
10 | indent_size = 4
11 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 | /composer.lock
3 | /vendor
4 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 |
3 | php:
4 | - "5.5"
5 | - "5.4"
6 | - "5.3"
7 |
8 | before_script:
9 | - composer install --prefer-dist --dev
10 |
11 | after_script:
12 | - php vendor/bin/coveralls -v
13 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2013 Chris Pliakas
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Magento Client Library For PHP
2 |
3 | [](https://travis-ci.org/cpliakas/magento-client-php)
4 | [](https://coveralls.io/r/cpliakas/magento-client-php?branch=master)
5 | [](https://packagist.org/packages/cpliakas/magento-client-php)
6 | [](https://packagist.org/packages/cpliakas/magento-client-php)
7 |
8 | Provides a client library to make REST and XMLRPC calls to a Magento instance.
9 |
10 | ## Installation
11 |
12 | Magento Client Library For PHP can be installed with [Composer](http://getcomposer.org)
13 | by adding it as a dependency to your project's composer.json file.
14 |
15 | ```json
16 | {
17 | "require": {
18 | "cpliakas/magento-client-php": "*"
19 | }
20 | }
21 | ```
22 |
23 | After running `php composer.phar update` on the command line, include the
24 | autoloader in your PHP scripts so that the SDK classes are made available.
25 |
26 | ```php
27 | require_once 'vendor/autoload.php';
28 | ```
29 |
30 | Please refer to [Composer's documentation](https://github.com/composer/composer/blob/master/doc/00-intro.md#introduction)
31 | for more detailed installation and usage instructions.
32 |
33 | ## Usage
34 |
35 | ### XMLRPC
36 |
37 | The following example returns a list of products with SKUs that start with "123":
38 |
39 | ```php
40 |
41 | use Magento\Client\Xmlrpc\MagentoXmlrpcClient;
42 |
43 | $client = MagentoXmlrpcClient::factory(array(
44 | 'base_url' => 'http://magentohost',
45 | 'api_user' => 'api.user',
46 | 'api_key' => 'some.private.key',
47 | ));
48 |
49 | $filters = array(
50 | 'sku' => array('like' => '123%'),
51 | );
52 |
53 | $result = $client->call('catalog_product.list', array($filters));
54 | ```
55 |
56 | ### Rest
57 |
58 | The following example returns a list of products:
59 |
60 | ```php
61 |
62 | use Magento\Client\Rest\MagentoRestClient;
63 |
64 | $client = MagentoRestClient::factory(array(
65 | 'base_url' => 'http://magentohost',
66 | 'consumer_key' => 'abc123...',
67 | 'consumer_secret' => 'def456...',
68 | 'token' => 'ghi789...',
69 | 'token_secret' => 'jkl012...',
70 | ));
71 |
72 | $result = $client->get('/api/rest/products')->send()->json();
73 |
74 | ```
75 |
76 | Refer to [Guzzle's documentation](https://guzzle.readthedocs.org/en/latest/http-client/request.html#creating-requests-with-a-client)
77 | for more information on sending requests to the server.
78 |
--------------------------------------------------------------------------------
/build.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cpliakas/magento-client-php",
3 | "type": "library",
4 | "description": "A PHP client library that consumes Magento's REST and XMLRPC APIs",
5 | "homepage": "https://github.com/cpliakas/magento-client-php",
6 | "license": "MIT",
7 | "authors": [
8 | {
9 | "name": "See contributors",
10 | "homepage": "https://github.com/cpliakas/magento-client-php/graphs/contributors"
11 | }
12 | ],
13 | "support": {
14 | "issues": "https://github.com/cpliakas/magento-client-php/issues"
15 | },
16 | "require": {
17 | "php": ">=5.3.3",
18 | "guzzle/guzzle": "~3.0",
19 | "lstrojny/fxmlrpc": ">=0.8,<0.9"
20 | },
21 | "require-dev": {
22 | "pdepend/pdepend": "~1.0",
23 | "phploc/phploc": "~2.0",
24 | "phpmd/phpmd": "~1.0",
25 | "phpunit/phpunit": "~3.0",
26 | "satooshi/php-coveralls": "*",
27 | "sebastian/phpcpd": "~2.0"
28 | },
29 | "autoload": {
30 | "psr-0": {
31 | "Magento\\Client": "src/"
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/phpmd.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 | PHP Project Starter Rulset: Adopted From Jenkins for Symfony 2
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/phpunit.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
14 | test
15 |
16 |
17 |
18 |
19 |
20 | src
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/src/Magento/Client/Rest/AccessToken.php:
--------------------------------------------------------------------------------
1 | getParamsToSign($request, $timestamp, $nonce);
23 |
24 | // Convert booleans to strings.
25 | $params = $this->prepareParameters($params);
26 |
27 | // Build signing string from combined params
28 | $parameterString = new QueryString($params);
29 |
30 | // Remove the port to get around the Magento bug.
31 | // @see http://stackoverflow.com/a/14693714/870667
32 | $requestUrl = $request->getUrl(true);
33 | if (preg_match('@/oauth/(initiate|token)$@', $requestUrl->getPath())) {
34 | $requestUrl->setPort('');
35 | }
36 |
37 | $url = Url::factory($requestUrl->setQuery('')->setFragment(null));
38 |
39 | return strtoupper($request->getMethod()) . '&'
40 | . rawurlencode($url) . '&'
41 | . rawurlencode((string) $parameterString);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/Magento/Client/Rest/MagentoRestClient.php:
--------------------------------------------------------------------------------
1 | 'http://localhost',
20 | 'base_path' => '',
21 | );
22 |
23 | $required = array(
24 | 'base_url',
25 | 'base_path',
26 | 'consumer_key',
27 | 'consumer_secret',
28 | );
29 |
30 | $config = Collection::fromConfig($config, $defaults, $required);
31 |
32 | $magento = new static($config->get('base_url'), $config);
33 | $magento->addSubscriber(new MagentoOauthPlugin($config->toArray()));
34 |
35 | $magento->setDefaultOption('headers', array(
36 | 'Content-Type' => 'application/json',
37 | 'Accept' => '*/*',
38 | ));
39 |
40 | return $magento;
41 | }
42 |
43 | /**
44 | * {@inheritdoc}
45 | *
46 | * Prepends the {+base_path} expressions to the URI
47 | */
48 | public function createRequest($method = 'GET', $uri = null, $headers = null, $body = null, array $options = array())
49 | {
50 | $uri = '{+base_path}/' . ltrim($uri, '/');
51 | return parent::createRequest($method, $uri, $headers, $body, $options);
52 | }
53 |
54 | /**
55 | * @return \Magento\Client\Rest\RequestToken
56 | *
57 | * @throws \Magento\Client\Rest\OauthException
58 | */
59 | public function getRequestToken()
60 | {
61 | try {
62 | $response = $this->post('/oauth/initiate')->send();
63 | } catch (ClientErrorResponseException $e) {
64 | throw OauthException::factory($e->getRequest(), $e->getResponse());
65 | }
66 | return new RequestToken($this, $response);
67 | }
68 |
69 | /**
70 | * @return \Magento\Client\Rest\AccessToken
71 | *
72 | * @throws \Magento\Client\Rest\OauthException
73 | */
74 | public function getAccessToken()
75 | {
76 | try {
77 | $response = $this->post('/oauth/token')->send();
78 | } catch (ClientErrorResponseException $e) {
79 | throw OauthException::factory($e->getRequest(), $e->getResponse());
80 | }
81 | return new AccessToken($this, $response);
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/src/Magento/Client/Rest/OauthException.php:
--------------------------------------------------------------------------------
1 | getStatusCode(),
23 | '[reason phrase] ' . $response->getReasonPhrase(),
24 | '[url] ' . $request->getUrl(),
25 | ));
26 |
27 | $e = new static($message);
28 | $e->setResponse($response);
29 | $e->setRequest($request);
30 |
31 | return $e;
32 | }
33 |
34 | /**
35 | * Returns the Magento problem constant.
36 | *
37 | * @return string
38 | */
39 | public function getOauthProblem()
40 | {
41 | parse_str($this->getResponse()->getBody(true), $arr);
42 | return isset($arr['oauth_problem']) ? $arr['oauth_problem'] : '';
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/Magento/Client/Rest/RequestToken.php:
--------------------------------------------------------------------------------
1 | callbackConfirmed = $arr['oauth_callback_confirmed'];
25 | }
26 |
27 | /**
28 | * @return bool
29 | */
30 | public function callbackConfirmed()
31 | {
32 | return $this->callbackConfirmed;
33 | }
34 |
35 | /**
36 | * @param string $path
37 | *
38 | * @return Guzzle\Http\Url
39 | */
40 | public function getAuthUrl($path)
41 | {
42 | return Url::factory($this->client->getConfig('base_url'))
43 | ->setPath($path)
44 | ->setQuery(array('oauth_token' => $this->token))
45 | ;
46 | }
47 |
48 | /**
49 | * @return Guzzle\Http\Url
50 | */
51 | public function getCustomerAuthUrl()
52 | {
53 | return $this->getAuthUrl('/oauth/authorize');
54 | }
55 |
56 | /**
57 | * @return Guzzle\Http\Url
58 | */
59 | public function getAdminAuthUrl()
60 | {
61 | return $this->getAuthUrl('/admin/oauth_authorize');
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/Magento/Client/Rest/Token.php:
--------------------------------------------------------------------------------
1 | client = $client;
38 | $this->response = $response;
39 |
40 | parse_str($response->getBody(true), $arr);
41 | if (!isset($arr['oauth_token'])) {
42 | throw new \UnexpectedValueException('Invalid response: missing oauth_token');
43 | }
44 | if (!isset($arr['oauth_token_secret'])) {
45 | throw new \UnexpectedValueException('Invalid response: missing oauth_token_secret');
46 | }
47 |
48 | $this->token = $arr['oauth_token'];
49 | $this->tokenSecret = $arr['oauth_token_secret'];
50 | }
51 |
52 | /**
53 | * @param array $arr
54 | */
55 | public function init(array $arr) {}
56 |
57 | /**
58 | * @return \Magento\Client\Rest\MagentoRestClient
59 | */
60 | public function getClient()
61 | {
62 | return $this->client;
63 | }
64 |
65 | /**
66 | * @return \Guzzle\Http\Message\Response
67 | */
68 | public function getResponse()
69 | {
70 | return $this->response;
71 | }
72 |
73 | /**
74 | * @return string
75 | */
76 | public function getToken()
77 | {
78 | return $this->token;
79 | }
80 |
81 | /**
82 | * @return string
83 | */
84 | public function getTokenSecret()
85 | {
86 | return $this->tokenSecret;
87 | }
88 |
89 | /**
90 | * @return string
91 | */
92 | public function __toString()
93 | {
94 | return $this->response->getBody(true);
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/src/Magento/Client/Xmlrpc/MagentoXmlrpcClient.php:
--------------------------------------------------------------------------------
1 | '',
29 | );
30 |
31 | $required = array(
32 | 'base_url',
33 | 'api_user',
34 | 'api_key',
35 | 'session',
36 | );
37 |
38 | // Instantiate the Acquia Search plugin.
39 | $config = Collection::fromConfig($config, $defaults, $required);
40 | return new static($config->get('base_url'), $config);
41 | }
42 |
43 | /**
44 | * @param bool $autoClose
45 | *
46 | * @return \Magento\Client\Xmlrpc\MagentoXmlrpcClient
47 | */
48 | public function autoCloseSession($autoClose = true)
49 | {
50 | $this->autoCloseSession = $autoClose;
51 | return $this;
52 | }
53 |
54 | /**
55 | * Ends the session if applicable.
56 | */
57 | public function __destruct()
58 | {
59 | if ($this->autoCloseSession && $this->client) {
60 | $this->client->call('endSession', array($this->getConfig('session')));
61 | }
62 | }
63 |
64 | /**
65 | * @return \fXmlRpc\Client
66 | */
67 | public function getClient()
68 | {
69 | if (!isset($this->client)) {
70 | $uri = rtrim($this->getConfig('base_url'), '/') . '/api/xmlrpc/';
71 | $bridge = new \fXmlRpc\Transport\GuzzleBridge($this);
72 | $this->client = new \fXmlRpc\Client($uri, $bridge);
73 | }
74 |
75 | return $this->client;
76 | }
77 |
78 | /**
79 | * @return string
80 | */
81 | public function getSession()
82 | {
83 | $session = $this->getConfig('session');
84 |
85 | if (!$session) {
86 | $this->autoCloseSession = true;
87 | $session = $this->getClient()->call('login', array(
88 | $this->getConfig('api_user'),
89 | $this->getConfig('api_key')
90 | ));
91 | $this->getConfig()->set('session', $session);
92 | }
93 |
94 | return $session;
95 | }
96 |
97 | /**
98 | * @param string $method
99 | * @param array $params
100 | *
101 | * @return array
102 | *
103 | * @throws \fXmlRpc\Exception\ResponseException
104 | */
105 | public function call($method, array $params = array())
106 | {
107 | $params = array($this->getSession(), $method, $params);
108 | return $this->getClient()->call('call', $params);
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/test/bootstrap.php:
--------------------------------------------------------------------------------
1 | add('Magento\Client\Test', 'test');
11 | $loader->register();
12 |
--------------------------------------------------------------------------------