From ecb26bc1ff8aef731296d3a1647a7df7b2828a58 Mon Sep 17 00:00:00 2001 From: Alex Lushpai Date: Sat, 12 Mar 2016 01:54:33 +0300 Subject: [PATCH] PSR-2, refactoring, tests --- .gitignore | 3 +- README.md | 50 ++- composer.json | 13 +- lib/RetailCrm/ApiClient.php | 355 ++++++++++++++---- lib/RetailCrm/Http/Client.php | 74 ++-- lib/RetailCrm/Response/ApiResponse.php | 17 + phpunit.xml.dist | 3 + tests/RetailCrm/Test/TestCase.php | 11 +- tests/RetailCrm/Tests/ApiClientPacksTest.php | 64 +++- tests/RetailCrm/Tests/ApiClientStoreTest.php | 30 +- tests/RetailCrm/Tests/Http/ClientTest.php | 10 - .../Tests/Response/ApiResponseTest.php | 2 +- 12 files changed, 458 insertions(+), 174 deletions(-) diff --git a/.gitignore b/.gitignore index 620af19..0e22d4b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ /vendor /bin composer.lock +composer.phar phpunit.xml .idea .DS_Store @@ -8,4 +9,4 @@ phpunit.xml .buildpath .project .swp -/nbproject \ No newline at end of file +/nbproject diff --git a/README.md b/README.md index fb67845..aa065e6 100644 --- a/README.md +++ b/README.md @@ -1,33 +1,31 @@ -# PHP-клиент для retailCRM API +# retailCRM API PHP client -PHP-клиент для работы с [retailCRM API](http://www.retailcrm.ru/docs/Developers/ApiVersion3). +PHP-client for [retailCRM API](http://www.retailcrm.ru/docs/Developers/ApiVersion3). -Рекомендуем обращаться к [документации](http://retailcrm.github.io/api-client-php) по библиотеке, в частности по классу [RetailCrm\ApiClient](http://retailcrm.github.io/api-client-php/class-RetailCrm.ApiClient.html). +Use [API documentation](http://retailcrm.github.io/api-client-php) -## Обязательные требования +## Requirements -* PHP версии 5.3 и выше -* PHP-расширение cURL +* PHP 5.3 and above +* PHP's cURL support -## Установка +## Install -1) Установите [composer](https://getcomposer.org/download/) +1) Get [composer](https://getcomposer.org/download/) -2) Выполните в папке проекта: +2) Run into your project directory: ```bash composer require retailcrm/api-client-php ~3.0.0 ``` -В конфиг `composer.json` вашего проекта будет добавлена библиотека `retailcrm/api-client-php`, которая установится в папку `vendor/`. При отсутствии файла конфига или папки с вендорами они будут созданы. - -В случае, если до этого в вашем проекте не использовался `composer`, подключите файл автозагрузки вендоров. Для этого укажите в коде проекта: +If you have not used `composer` before, include autoloader into your project. ```php require 'path/to/vendor/autoload.php'; ``` -## Примеры использования +## Usage -### Получение информации о заказе +### Get order ```php $client = new \RetailCrm\ApiClient( 'https://demo.retailcrm.ru', @@ -38,30 +36,30 @@ $client = new \RetailCrm\ApiClient( try { $response = $client->ordersGet('M-2342'); } catch (\RetailCrm\Exception\CurlException $e) { - echo "Сетевые проблемы. Ошибка подключения к retailCRM: " . $e->getMessage(); + echo "Connection error: " . $e->getMessage(); } if ($response->isSuccessful()) { echo $response->order['totalSumm']; - // или $response['order']['totalSumm']; - // или + // or $response['order']['totalSumm']; + // or // $order = $response->getOrder(); // $order['totalSumm']; } else { echo sprintf( - "Ошибка получения информации о заказа: [Статус HTTP-ответа %s] %s", + "Error: [HTTP-code %s] %s", $response->getStatusCode(), $response->getErrorMsg() ); - // получить детализацию ошибок + // error details //if (isset($response['errors'])) { // print_r($response['errors']); //} } ``` -### Создание заказа +### Create order ```php $client = new \RetailCrm\ApiClient( @@ -82,21 +80,21 @@ try { ) )); } catch (\RetailCrm\Exception\CurlException $e) { - echo "Сетевые проблемы. Ошибка подключения к retailCRM: " . $e->getMessage(); + echo "Connection error: " . $e->getMessage(); } if ($response->isSuccessful() && 201 === $response->getStatusCode()) { - echo 'Заказ успешно создан. ID заказа в retailCRM = ' . $response->id; - // или $response['id']; - // или $response->getId(); + echo 'Order successfully created. Order ID into retailCRM = ' . $response->id; + // or $response['id']; + // or $response->getId(); } else { echo sprintf( - "Ошибка создания заказа: [Статус HTTP-ответа %s] %s", + "Error: [HTTP-code %s] %s", $response->getStatusCode(), $response->getErrorMsg() ); - // получить детализацию ошибок + // error details //if (isset($response['errors'])) { // print_r($response['errors']); //} diff --git a/composer.json b/composer.json index 8280092..d933d6d 100644 --- a/composer.json +++ b/composer.json @@ -4,6 +4,7 @@ "type": "library", "keywords": ["API", "retailCRM", "REST"], "homepage": "http://www.retailcrm.ru/", + "license": "MIT", "authors": [ { "name": "retailCRM", @@ -12,15 +13,17 @@ ], "require": { "php": ">=5.3.0", - "ext-curl": "*" + "ext-curl": "*", + "phpunit/php-code-coverage": "3.3.0", + "phpunit/php-invoker": "1.1.4" }, "require-dev": { - "phpunit/phpunit": "3.7.*", - "phpmd/phpmd": "2.1.*", + "phpunit/phpunit": "5.2.*", + "phpmd/phpmd": "2.4.*", "sebastian/phpcpd": "2.0.*", "sebastian/phpdcd": "1.0.*", - "squizlabs/php_codesniffer": "dev-master", - "apigen/apigen": "~4.0@dev" + "squizlabs/php_codesniffer": "2.5.*", + "apigen/apigen": "4.1.*" }, "support": { "email": "support@intarocrm.ru" diff --git a/lib/RetailCrm/ApiClient.php b/lib/RetailCrm/ApiClient.php index cb546cd..1adfe30 100644 --- a/lib/RetailCrm/ApiClient.php +++ b/lib/RetailCrm/ApiClient.php @@ -35,11 +35,13 @@ class ApiClient * @param string $apiKey api key * @param string $site site code * + * @throws \InvalidArgumentException + * * @return mixed */ public function __construct($url, $apiKey, $site = null) { - if ('/' != substr($url, strlen($url) - 1, 1)) { + if ('/' !== substr($url, strlen($url) - 1, 1)) { $url .= '/'; } @@ -56,13 +58,17 @@ class ApiClient * @param int $page (default: null) * @param int $limit (default: null) * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function ordersList(array $filter = array(), $page = null, $limit = null) { $parameters = array(); - if (sizeof($filter)) { + if (count($filter)) { $parameters['filter'] = $filter; } if (null !== $page) { @@ -85,18 +91,22 @@ class ApiClient * @param array $order order data * @param string $site (default: null) * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function ordersCreate(array $order, $site = null) { - if (! sizeof($order)) { + if (!count($order)) { throw new \InvalidArgumentException( 'Parameter `order` must contains a data' ); } return $this->client->makeRequest( - "/orders/create", + '/orders/create', Client::METHOD_POST, $this->fillSite($site, array('order' => json_encode($order))) ); @@ -107,18 +117,22 @@ class ApiClient * * @param array $ids order identificators * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function ordersFixExternalIds(array $ids) { - if (! sizeof($ids)) { + if (! count($ids)) { throw new \InvalidArgumentException( 'Method parameter must contains at least one IDs pair' ); } return $this->client->makeRequest( - "/orders/fix-external-ids", + '/orders/fix-external-ids', Client::METHOD_POST, array('orders' => json_encode($ids) ) @@ -134,6 +148,10 @@ class ApiClient * @param int $offset (default: 0) * @param bool $skipMyChanges (default: true) * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function ordersHistory( @@ -174,6 +192,10 @@ class ApiClient * @param array $ids (default: array()) * @param array $externalIds (default: array()) * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function ordersStatuses( @@ -182,10 +204,10 @@ class ApiClient ) { $parameters = array(); - if (sizeof($ids)) { + if (count($ids)) { $parameters['ids'] = $ids; } - if (sizeof($externalIds)) { + if (count($externalIds)) { $parameters['externalIds'] = $externalIds; } @@ -202,18 +224,22 @@ class ApiClient * @param array $orders array of orders * @param string $site (default: null) * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function ordersUpload(array $orders, $site = null) { - if (! sizeof($orders)) { + if (!count($orders)) { throw new \InvalidArgumentException( 'Parameter `orders` must contains array of the orders' ); } return $this->client->makeRequest( - "/orders/upload", + '/orders/upload', Client::METHOD_POST, $this->fillSite($site, array('orders' => json_encode($orders))) ); @@ -226,6 +252,10 @@ class ApiClient * @param string $by (default: 'externalId') * @param string $site (default: null) * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function ordersGet($id, $by = 'externalId', $site = null) @@ -246,11 +276,15 @@ class ApiClient * @param string $by (default: 'externalId') * @param string $site (default: null) * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function ordersEdit(array $order, $by = 'externalId', $site = null) { - if (! sizeof($order)) { + if (!count($order)) { throw new \InvalidArgumentException( 'Parameter `order` must contains a data' ); @@ -258,14 +292,14 @@ class ApiClient $this->checkIdParameter($by); - if (! isset($order[$by])) { + if (!array_key_exists($by, $order)) { throw new \InvalidArgumentException( sprintf('Order array must contain the "%s" parameter.', $by) ); } return $this->client->makeRequest( - "/orders/" . $order[$by] . "/edit", + sprintf('/orders/%s/edit', $order[$by]), Client::METHOD_POST, $this->fillSite( $site, @@ -281,6 +315,10 @@ class ApiClient * @param int $page (default: null) * @param int $limit (default: null) * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function customersList( @@ -290,7 +328,7 @@ class ApiClient ) { $parameters = array(); - if (sizeof($filter)) { + if (count($filter)) { $parameters['filter'] = $filter; } if (null !== $page) { @@ -313,18 +351,22 @@ class ApiClient * @param array $customer customer data * @param string $site (default: null) * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function customersCreate(array $customer, $site = null) { - if (! sizeof($customer)) { + if (! count($customer)) { throw new \InvalidArgumentException( 'Parameter `customer` must contains a data' ); } return $this->client->makeRequest( - "/customers/create", + '/customers/create', Client::METHOD_POST, $this->fillSite($site, array('customer' => json_encode($customer))) ); @@ -335,18 +377,22 @@ class ApiClient * * @param array $ids ids mapping * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function customersFixExternalIds(array $ids) { - if (! sizeof($ids)) { + if (! count($ids)) { throw new \InvalidArgumentException( 'Method parameter must contains at least one IDs pair' ); } return $this->client->makeRequest( - "/customers/fix-external-ids", + '/customers/fix-external-ids', Client::METHOD_POST, array('customers' => json_encode($ids)) ); @@ -358,18 +404,22 @@ class ApiClient * @param array $customers array of customers * @param string $site (default: null) * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function customersUpload(array $customers, $site = null) { - if (! sizeof($customers)) { + if (! count($customers)) { throw new \InvalidArgumentException( 'Parameter `customers` must contains array of the customers' ); } return $this->client->makeRequest( - "/customers/upload", + '/customers/upload', Client::METHOD_POST, $this->fillSite($site, array('customers' => json_encode($customers))) ); @@ -382,6 +432,10 @@ class ApiClient * @param string $by (default: 'externalId') * @param string $site (default: null) * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function customersGet($id, $by = 'externalId', $site = null) @@ -402,11 +456,15 @@ class ApiClient * @param string $by (default: 'externalId') * @param string $site (default: null) * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function customersEdit(array $customer, $by = 'externalId', $site = null) { - if (! sizeof($customer)) { + if (!count($customer)) { throw new \InvalidArgumentException( 'Parameter `customer` must contains a data' ); @@ -414,14 +472,14 @@ class ApiClient $this->checkIdParameter($by); - if (! isset($customer[$by])) { + if (!array_key_exists($by, $customer)) { throw new \InvalidArgumentException( sprintf('Customer array must contain the "%s" parameter.', $by) ); } return $this->client->makeRequest( - "/customers/" . $customer[$by] . "/edit", + sprintf('/customers/%s/edit', $customer[$by]), Client::METHOD_POST, $this->fillSite( $site, @@ -437,6 +495,10 @@ class ApiClient * @param int $page (default: null) * @param int $limit (default: null) * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function ordersPacksList( @@ -446,7 +508,7 @@ class ApiClient ) { $parameters = array(); - if (sizeof($filter)) { + if (count($filter)) { $parameters['filter'] = $filter; } if (null !== $page) { @@ -469,18 +531,22 @@ class ApiClient * @param array $pack pack data * @param string $site (default: null) * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function ordersPacksCreate(array $pack, $site = null) { - if (! sizeof($pack)) { + if (!count($pack)) { throw new \InvalidArgumentException( 'Parameter `pack` must contains a data' ); } return $this->client->makeRequest( - "/orders/packs/create", + '/orders/packs/create', Client::METHOD_POST, $this->fillSite($site, array('pack' => json_encode($pack))) ); @@ -493,6 +559,10 @@ class ApiClient * @param int $page (default: null) * @param int $limit (default: null) * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function ordersPacksHistory( @@ -502,7 +572,7 @@ class ApiClient ) { $parameters = array(); - if (sizeof($filter)) { + if (count($filter)) { $parameters['filter'] = $filter; } if (null !== $page) { @@ -524,6 +594,10 @@ class ApiClient * * @param string $id pack identificator * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function ordersPacksGet($id) @@ -532,7 +606,10 @@ class ApiClient throw new \InvalidArgumentException('Parameter `id` must be set'); } - return $this->client->makeRequest("/orders/packs/$id", Client::METHOD_GET); + return $this->client->makeRequest( + "/orders/packs/$id", + Client::METHOD_GET + ); } /** @@ -540,6 +617,10 @@ class ApiClient * * @param string $id pack identificator * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function ordersPacksDelete($id) @@ -549,7 +630,7 @@ class ApiClient } return $this->client->makeRequest( - "/orders/packs/$id/delete", + sprintf('/orders/packs/%s/delete', $id), Client::METHOD_POST ); } @@ -560,20 +641,22 @@ class ApiClient * @param array $pack pack data * @param string $site (default: null) * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function ordersPacksEdit(array $pack, $site = null) { - if (! sizeof($pack) || empty($pack['id'])) { + if (!count($pack) || empty($pack['id'])) { throw new \InvalidArgumentException( 'Parameter `pack` must contains a data & pack `id` must be set' ); } - $id = $pack['id']; - return $this->client->makeRequest( - "/orders/packs/$id/edit", + sprintf('/orders/packs/%s/edit', $pack['id']), Client::METHOD_POST, $this->fillSite($site, array('pack' => json_encode($pack))) ); @@ -585,19 +668,21 @@ class ApiClient * @param array $filter (default: array()) * @param int $page (default: null) * @param int $limit (default: null) - * @param string $site (default: null) + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException * * @return ApiResponse */ public function storeInventories( array $filter = array(), $page = null, - $limit = null, - $site = null + $limit = null ) { $parameters = array(); - if (sizeof($filter)) { + if (count($filter)) { $parameters['filter'] = $filter; } if (null !== $page) { @@ -610,7 +695,7 @@ class ApiClient return $this->client->makeRequest( '/store/inventories', Client::METHOD_GET, - $this->fillSite($site, $parameters) + $parameters ); } @@ -620,18 +705,22 @@ class ApiClient * @param array $offers offers data * @param string $site (default: null) * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function storeInventoriesUpload(array $offers, $site = null) { - if (! sizeof($offers)) { + if (!count($offers)) { throw new \InvalidArgumentException( 'Parameter `offers` must contains array of the offers' ); } return $this->client->makeRequest( - "/store/inventories/upload", + '/store/inventories/upload', Client::METHOD_POST, $this->fillSite($site, array('offers' => json_encode($offers))) ); @@ -640,6 +729,10 @@ class ApiClient /** * Returns available county list * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function countriesList() @@ -653,6 +746,10 @@ class ApiClient /** * Returns deliveryServices list * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function deliveryServicesList() @@ -668,18 +765,22 @@ class ApiClient * * @param array $data delivery service data * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function deliveryServicesEdit(array $data) { - if (! isset($data['code'])) { + if (!array_key_exists('code', $data)) { throw new \InvalidArgumentException( 'Data must contain "code" parameter.' ); } return $this->client->makeRequest( - '/reference/delivery-services/' . $data['code'] . '/edit', + sprintf('/reference/delivery-services/%s/edit', $data['code']), Client::METHOD_POST, array('deliveryService' => json_encode($data)) ); @@ -688,6 +789,10 @@ class ApiClient /** * Returns deliveryTypes list * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function deliveryTypesList() @@ -703,18 +808,22 @@ class ApiClient * * @param array $data delivery type data * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function deliveryTypesEdit(array $data) { - if (! isset($data['code'])) { + if (!array_key_exists('code', $data)) { throw new \InvalidArgumentException( 'Data must contain "code" parameter.' ); } return $this->client->makeRequest( - '/reference/delivery-types/' . $data['code'] . '/edit', + sprintf('/reference/delivery-types/%s/edit', $data['code']), Client::METHOD_POST, array('deliveryType' => json_encode($data)) ); @@ -723,12 +832,17 @@ class ApiClient /** * Returns orderMethods list * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function orderMethodsList() { return $this->client->makeRequest( - '/reference/order-methods', Client::METHOD_GET + '/reference/order-methods', + Client::METHOD_GET ); } @@ -737,18 +851,22 @@ class ApiClient * * @param array $data order method data * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function orderMethodsEdit(array $data) { - if (! isset($data['code'])) { + if (!array_key_exists('code', $data)) { throw new \InvalidArgumentException( 'Data must contain "code" parameter.' ); } return $this->client->makeRequest( - '/reference/order-methods/' . $data['code'] . '/edit', + sprintf('/reference/order-methods/%s/edit', $data['code']), Client::METHOD_POST, array('orderMethod' => json_encode($data)) ); @@ -757,6 +875,10 @@ class ApiClient /** * Returns orderTypes list * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function orderTypesList() @@ -772,18 +894,22 @@ class ApiClient * * @param array $data order type data * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function orderTypesEdit(array $data) { - if (! isset($data['code'])) { + if (!array_key_exists('code', $data)) { throw new \InvalidArgumentException( 'Data must contain "code" parameter.' ); } return $this->client->makeRequest( - '/reference/order-types/' . $data['code'] . '/edit', + sprintf('/reference/order-types/%s/edit', $data['code']), Client::METHOD_POST, array('orderType' => json_encode($data)) ); @@ -792,6 +918,10 @@ class ApiClient /** * Returns paymentStatuses list * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function paymentStatusesList() @@ -807,18 +937,22 @@ class ApiClient * * @param array $data payment status data * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function paymentStatusesEdit(array $data) { - if (! isset($data['code'])) { + if (!array_key_exists('code', $data)) { throw new \InvalidArgumentException( 'Data must contain "code" parameter.' ); } return $this->client->makeRequest( - '/reference/payment-statuses/' . $data['code'] . '/edit', + sprintf('/reference/payment-statuses/%s/edit', $data['code']), Client::METHOD_POST, array('paymentStatus' => json_encode($data)) ); @@ -827,6 +961,10 @@ class ApiClient /** * Returns paymentTypes list * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function paymentTypesList() @@ -842,18 +980,22 @@ class ApiClient * * @param array $data payment type data * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function paymentTypesEdit(array $data) { - if (! isset($data['code'])) { + if (!array_key_exists('code', $data)) { throw new \InvalidArgumentException( 'Data must contain "code" parameter.' ); } return $this->client->makeRequest( - '/reference/payment-types/' . $data['code'] . '/edit', + sprintf('/reference/payment-types/%s/edit', $data['code']), Client::METHOD_POST, array('paymentType' => json_encode($data)) ); @@ -862,6 +1004,10 @@ class ApiClient /** * Returns productStatuses list * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function productStatusesList() @@ -877,18 +1023,22 @@ class ApiClient * * @param array $data product status data * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function productStatusesEdit(array $data) { - if (! isset($data['code'])) { + if (!array_key_exists('code', $data)) { throw new \InvalidArgumentException( 'Data must contain "code" parameter.' ); } return $this->client->makeRequest( - '/reference/product-statuses/' . $data['code'] . '/edit', + sprintf('/reference/product-statuses/%s/edit', $data['code']), Client::METHOD_POST, array('productStatus' => json_encode($data)) ); @@ -897,11 +1047,18 @@ class ApiClient /** * Returns sites list * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function sitesList() { - return $this->client->makeRequest('/reference/sites', Client::METHOD_GET); + return $this->client->makeRequest( + '/reference/sites', + Client::METHOD_GET + ); } /** @@ -909,18 +1066,22 @@ class ApiClient * * @param array $data site data * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function sitesEdit(array $data) { - if (! isset($data['code'])) { + if (!array_key_exists('code', $data)) { throw new \InvalidArgumentException( 'Data must contain "code" parameter.' ); } return $this->client->makeRequest( - '/reference/sites/' . $data['code'] . '/edit', + sprintf('/reference/sites/%s/edit', $data['code']), Client::METHOD_POST, array('site' => json_encode($data)) ); @@ -929,6 +1090,10 @@ class ApiClient /** * Returns statusGroups list * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function statusGroupsList() @@ -942,11 +1107,18 @@ class ApiClient /** * Returns statuses list * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function statusesList() { - return $this->client->makeRequest('/reference/statuses', Client::METHOD_GET); + return $this->client->makeRequest( + '/reference/statuses', + Client::METHOD_GET + ); } /** @@ -954,18 +1126,22 @@ class ApiClient * * @param array $data status data * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function statusesEdit(array $data) { - if (! isset($data['code'])) { + if (!array_key_exists('code', $data)) { throw new \InvalidArgumentException( 'Data must contain "code" parameter.' ); } return $this->client->makeRequest( - '/reference/statuses/' . $data['code'] . '/edit', + sprintf('/reference/statuses/%s/edit', $data['code']), Client::METHOD_POST, array('status' => json_encode($data)) ); @@ -974,11 +1150,18 @@ class ApiClient /** * Returns stores list * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function storesList() { - return $this->client->makeRequest('/reference/stores', Client::METHOD_GET); + return $this->client->makeRequest( + '/reference/stores', + Client::METHOD_GET + ); } /** @@ -986,24 +1169,28 @@ class ApiClient * * @param array $data site data * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function storesEdit(array $data) { - if (! isset($data['code'])) { + if (!array_key_exists('code', $data)) { throw new \InvalidArgumentException( 'Data must contain "code" parameter.' ); } - if (! isset($data['name'])) { + if (!array_key_exists('name', $data)) { throw new \InvalidArgumentException( 'Data must contain "name" parameter.' ); } return $this->client->makeRequest( - '/reference/stores/' . $data['code'] . '/edit', + sprintf('/reference/stores/%s/edit', $data['code']), Client::METHOD_POST, array('store' => json_encode($data)) ); @@ -1012,11 +1199,18 @@ class ApiClient /** * Update CRM basic statistic * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function statisticUpdate() { - return $this->client->makeRequest('/statistic/update', Client::METHOD_GET); + return $this->client->makeRequest( + '/statistic/update', + Client::METHOD_GET + ); } /** @@ -1027,23 +1221,27 @@ class ApiClient * @param string $code additional phone code * @param string $status call status * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function telephonyCallEvent($phone, $type, $code, $status) { - if (! isset($phone)) { + if (!isset($phone)) { throw new \InvalidArgumentException('Phone number must be set'); } $parameters['phone'] = $phone; - if (! isset($type)) { + if (!isset($type)) { throw new \InvalidArgumentException('Type must be set (in|out|hangup)'); } $parameters['type'] = $type; - if (! isset($code)) { + if (!isset($code)) { throw new \InvalidArgumentException('Code must be set'); } @@ -1062,18 +1260,22 @@ class ApiClient * * @param array $calls calls data * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function telephonyCallsUpload(array $calls) { - if (! sizeof($calls)) { + if (!count($calls)) { throw new \InvalidArgumentException( 'Parameter `calls` must contains array of the calls' ); } return $this->client->makeRequest( - "/telephony/calls/upload", + '/telephony/calls/upload', Client::METHOD_POST, array('calls' => json_encode($calls)) ); @@ -1085,6 +1287,10 @@ class ApiClient * @param string $phone phone number * @param bool $details detailed information * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * * @return ApiResponse */ public function telephonyCallManager($phone, $details) @@ -1098,7 +1304,8 @@ class ApiClient return $this->client->makeRequest( '/telephony/manager', - Client::METHOD_GET, $parameters + Client::METHOD_GET, + $parameters ); } @@ -1129,6 +1336,8 @@ class ApiClient * * @param string $by identify by * + * @throws \InvalidArgumentException + * * @return bool */ protected function checkIdParameter($by) @@ -1138,7 +1347,7 @@ class ApiClient 'id' ); - if (!in_array($by, $allowedForBy)) { + if (!in_array($by, $allowedForBy, false)) { throw new \InvalidArgumentException( sprintf( 'Value "%s" for parameter "by" is not valid. Allowed values are %s.', diff --git a/lib/RetailCrm/Http/Client.php b/lib/RetailCrm/Http/Client.php index 27e65a4..eafb079 100644 --- a/lib/RetailCrm/Http/Client.php +++ b/lib/RetailCrm/Http/Client.php @@ -3,6 +3,7 @@ namespace RetailCrm\Http; use RetailCrm\Exception\CurlException; +use RetailCrm\Exception\InvalidJsonException; use RetailCrm\Response\ApiResponse; /** @@ -30,6 +31,8 @@ class Client * * @param string $url api url * @param array $defaultParameters array of parameters + * + * @throws \InvalidArgumentException */ public function __construct($url, array $defaultParameters = array()) { @@ -60,24 +63,23 @@ class Client * @param string $path request url * @param string $method (default: 'GET') * @param array $parameters (default: array()) - * @param int $timeout (default: 30) - * @param bool $verify (default: false) - * @param bool $debug (default: false) * * @SuppressWarnings(PHPMD.ExcessiveParameterList) * + * @throws \InvalidArgumentException + * @throws CurlException + * @throws InvalidJsonException + * * @return ApiResponse */ public function makeRequest( $path, $method, - array $parameters = array(), - $timeout = 30, - $verify = false, - $debug = false + array $parameters = array() ) { $allowedMethods = array(self::METHOD_GET, self::METHOD_POST); - if (!in_array($method, $allowedMethods)) { + + if (!in_array($method, $allowedMethods, false)) { throw new \InvalidArgumentException( sprintf( 'Method "%s" is not valid. Allowed methods are %s', @@ -91,53 +93,37 @@ class Client $url = $this->url . $path; - if (self::METHOD_GET === $method && sizeof($parameters)) { + if (self::METHOD_GET === $method && count($parameters)) { $url .= '?' . http_build_query($parameters, '', '&'); } - $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, $url); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); - curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); - curl_setopt($ch, CURLOPT_FAILONERROR, false); - curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $verify); - curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, $verify); - - if (!$debug) { - curl_setopt($ch, CURLOPT_TIMEOUT, (int) $timeout); - curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, (int) $timeout); - } else { - curl_setopt( - $ch, - CURLOPT_TIMEOUT_MS, - (int) $timeout + ($this->retry * 2000) - ); - } + $curlHandler = curl_init(); + curl_setopt($curlHandler, CURLOPT_URL, $url); + curl_setopt($curlHandler, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($curlHandler, CURLOPT_FOLLOWLOCATION, 1); + curl_setopt($curlHandler, CURLOPT_FAILONERROR, false); + curl_setopt($curlHandler, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($curlHandler, CURLOPT_SSL_VERIFYHOST, false); + curl_setopt($curlHandler, CURLOPT_TIMEOUT, 30); + curl_setopt($curlHandler, CURLOPT_CONNECTTIMEOUT, 30); if (self::METHOD_POST === $method) { - curl_setopt($ch, CURLOPT_POST, true); - curl_setopt($ch, CURLOPT_POSTFIELDS, $parameters); + curl_setopt($curlHandler, CURLOPT_POST, true); + curl_setopt($curlHandler, CURLOPT_POSTFIELDS, $parameters); } - $responseBody = curl_exec($ch); - $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); - $errno = curl_errno($ch); - $error = curl_error($ch); + $responseBody = curl_exec($curlHandler); + $statusCode = curl_getinfo($curlHandler, CURLINFO_HTTP_CODE); + $errno = curl_errno($curlHandler); + $error = curl_error($curlHandler); - curl_close($ch); + curl_close($curlHandler); - if ($errno && in_array($errno, $this->curlErrors) && $this->retry < 3) { + if ($errno && in_array($errno, $this->curlErrors, false) && $this->retry < 3) { $errno = null; $error = null; - $this->retry += 1; - $this->makeRequest( - $path, - $method, - $parameters, - $timeout, - $verify, - $debug - ); + ++$this->retry; + $this->makeRequest($path, $method, $parameters); } if ($errno) { diff --git a/lib/RetailCrm/Response/ApiResponse.php b/lib/RetailCrm/Response/ApiResponse.php index 5ae57d3..8d97cd7 100644 --- a/lib/RetailCrm/Response/ApiResponse.php +++ b/lib/RetailCrm/Response/ApiResponse.php @@ -28,6 +28,8 @@ class ApiResponse implements \ArrayAccess * * @param int $statusCode HTTP status code * @param mixed $responseBody HTTP body + * + * @throws InvalidJsonException */ public function __construct($statusCode, $responseBody = null) { @@ -71,6 +73,10 @@ class ApiResponse implements \ArrayAccess * Allow to access for the property throw class method * * @param string $name + * @param $arguments + * + * @throws \InvalidArgumentException + * * @return mixed */ public function __call($name, $arguments) @@ -89,6 +95,9 @@ class ApiResponse implements \ArrayAccess * Allow to access for the property throw object property * * @param string $name + * + * @throws \InvalidArgumentException + * * @return mixed */ public function __get($name) @@ -103,6 +112,8 @@ class ApiResponse implements \ArrayAccess /** * @param mixed $offset * @param mixed $value + * + * @throws \BadMethodCallException */ public function offsetSet($offset, $value) { @@ -111,6 +122,8 @@ class ApiResponse implements \ArrayAccess /** * @param mixed $offset + * + * @throws \BadMethodCallException */ public function offsetUnset($offset) { @@ -119,6 +132,7 @@ class ApiResponse implements \ArrayAccess /** * @param mixed $offset + * * @return bool */ public function offsetExists($offset) @@ -128,6 +142,9 @@ class ApiResponse implements \ArrayAccess /** * @param mixed $offset + * + * @throws \InvalidArgumentException + * * @return mixed */ public function offsetGet($offset) diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 652f4e7..6097b7b 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -13,6 +13,9 @@ + + + diff --git a/tests/RetailCrm/Test/TestCase.php b/tests/RetailCrm/Test/TestCase.php index 5eafabb..57d3067 100644 --- a/tests/RetailCrm/Test/TestCase.php +++ b/tests/RetailCrm/Test/TestCase.php @@ -27,15 +27,20 @@ class TestCase extends \PHPUnit_Framework_TestCase /** * Return Client object * - * @param string $url (default: null) - * @param string $apiKey (default: null) + * @param string $url (default: null) + * @param array $defaultParameters (default: array()) + * * @return Client */ public static function getClient($url = null, $defaultParameters = array()) { return new Client( $url ?: $_SERVER['CRM_URL'] . '/api/' . ApiClient::VERSION, - array('apiKey' => isset($defaultParameters['apiKey']) ? $defaultParameters['apiKey'] : $_SERVER['CRM_API_KEY']) + array( + 'apiKey' => array_key_exists('apiKey', $defaultParameters) + ? $defaultParameters['apiKey'] + : $_SERVER['CRM_API_KEY'] + ) ); } } diff --git a/tests/RetailCrm/Tests/ApiClientPacksTest.php b/tests/RetailCrm/Tests/ApiClientPacksTest.php index abc73ed..cc51764 100644 --- a/tests/RetailCrm/Tests/ApiClientPacksTest.php +++ b/tests/RetailCrm/Tests/ApiClientPacksTest.php @@ -26,4 +26,66 @@ class ApiClientPacksTest extends TestCase 'API returns generatedAt in orders assembly history' ); } -} \ No newline at end of file + + /** + * @group integration + */ + public function testOrdersPacksCreate() + { + $client = static::getApiClient(); + $pack = array( + 'itemId' => $_SERVER['CRM_PACK_ITEM'], + 'quantity' => $_SERVER['CRM_PACK_QUANTITY'], + 'store' => $_SERVER['CRM_STORE'] + ); + + $response = $client->ordersPacksCreate($pack); + $this->assertInstanceOf('RetailCrm\Response\ApiResponse', $response); + $this->assertEquals(201, $response->getStatusCode()); + $this->assertTrue($response->success); + } + + /** + * @group integration + */ + public function testOrdersPacksCreateFailed() + { + $client = static::getApiClient(); + $pack = array( + 'itemId' => 12, + 'store' => $_SERVER['CRM_STORE'], + 'quantity' => 2 + ); + + $response = $client->ordersPacksCreate($pack); + $this->assertInstanceOf('RetailCrm\Response\ApiResponse', $response); + $this->assertEquals(400, $response->getStatusCode()); + $this->assertFalse($response->success); + } + + /** + * @group integration + */ + public function testOrdersPacksGet() + { + $client = static::getApiClient(); + + $response = $client->ordersPacksGet(1); + $this->assertInstanceOf('RetailCrm\Response\ApiResponse', $response); + $this->assertEquals(200, $response->getStatusCode()); + $this->assertTrue($response->success); + } + + /** + * @group integration + */ + public function testOrdersPacksDelete() + { + $client = static::getApiClient(); + + $response = $client->ordersPacksDelete(1); + $this->assertInstanceOf('RetailCrm\Response\ApiResponse', $response); + $this->assertEquals(200, $response->getStatusCode()); + $this->assertTrue($response->success); + } +} diff --git a/tests/RetailCrm/Tests/ApiClientStoreTest.php b/tests/RetailCrm/Tests/ApiClientStoreTest.php index de354b0..32b323c 100644 --- a/tests/RetailCrm/Tests/ApiClientStoreTest.php +++ b/tests/RetailCrm/Tests/ApiClientStoreTest.php @@ -4,6 +4,10 @@ namespace RetailCrm\Tests; use RetailCrm\Test\TestCase; +/** + * Class ApiClientStoreTest + * @package RetailCrm\Tests + */ class ApiClientStoreTest extends TestCase { /** @@ -30,8 +34,7 @@ class ApiClientStoreTest extends TestCase public function testStoreInventoriesUploadExceptionEmpty() { $client = static::getApiClient(); - - $response = $client->storeInventoriesUpload(array()); + $client->storeInventoriesUpload(array()); } /** @@ -47,20 +50,27 @@ class ApiClientStoreTest extends TestCase $response = $client->storeInventoriesUpload(array( array( 'externalId' => $externalIdA, - 'available' => 10, - 'purchasePrice' => 1700 + 'stores' => array( + array( + 'code' => $_SERVER['CRM_STORE'], + 'available' => 10, + 'purchasePrice' => 1700 + ) + ) ), array( 'externalId' => $externalIdB, - 'available' => 20, - 'purchasePrice' => 1500 + 'stores' => array( + array( + 'code' => $_SERVER['CRM_STORE'], + 'available' => 20, + 'purchasePrice' => 1500 + ) + ) ), )); $this->assertInstanceOf('RetailCrm\Response\ApiResponse', $response); - $this->assertTrue( - $response->isSuccessful(), - 'Got offer' - ); + $this->assertTrue($response->isSuccessful()); } /** diff --git a/tests/RetailCrm/Tests/Http/ClientTest.php b/tests/RetailCrm/Tests/Http/ClientTest.php index 61e614c..bbecdf8 100644 --- a/tests/RetailCrm/Tests/Http/ClientTest.php +++ b/tests/RetailCrm/Tests/Http/ClientTest.php @@ -58,14 +58,4 @@ class ClientTest extends TestCase $this->assertInstanceOf('RetailCrm\Response\ApiResponse', $response); $this->assertEquals(200, $response->getStatusCode()); } - - /** - * @group integration - */ - public function testMakeRequestRepeatOnTimeout() - { - $client = static::getClient(); - $response = $client->makeRequest('/orders', Client::METHOD_GET, array(), 1, false, true); - $this->assertGreaterThanOrEqual(1, $client->retry); - } } diff --git a/tests/RetailCrm/Tests/Response/ApiResponseTest.php b/tests/RetailCrm/Tests/Response/ApiResponseTest.php index fa70176..74e0fab 100644 --- a/tests/RetailCrm/Tests/Response/ApiResponseTest.php +++ b/tests/RetailCrm/Tests/Response/ApiResponseTest.php @@ -29,7 +29,7 @@ class ApiResponseTest extends TestCase /** * @group unit - * @expectedException RetailCrm\Exception\InvalidJsonException + * @expectedException \RetailCrm\Exception\InvalidJsonException */ public function testJsonInvalid() {