From 921dbda7563900aefc740f9f909fe2cedaf7e33b Mon Sep 17 00:00:00 2001 From: Ilyas Salikhov Date: Thu, 6 Nov 2014 02:44:52 +0300 Subject: [PATCH] New version of PHP client for API v3. Not all methods implements --- .gitignore | 3 + README.md | 50 +- composer.json | 19 +- lib/IntaroCrm/Exception/ApiException.php | 6 - lib/IntaroCrm/Exception/CurlException.php | 6 - lib/IntaroCrm/RestApi.php | 581 ------------------ lib/RetailCrm/ApiClient.php | 101 +++ lib/RetailCrm/Exception/CurlException.php | 7 + .../Exception/InvalidJsonException.php | 7 + lib/RetailCrm/Http/Client.php | 81 +++ lib/RetailCrm/Response/ApiResponse.php | 112 ++++ phpunit.xml.dist | 21 + tests/RetailCrm/Test/TestCase.php | 20 + tests/RetailCrm/Tests/ApiClientTest.php | 127 ++++ tests/RetailCrm/Tests/Http/ClientTest.php | 61 ++ .../Tests/Response/ApiResponseTest.php | 233 +++++++ tests/bootstrap.php | 4 + 17 files changed, 791 insertions(+), 648 deletions(-) delete mode 100644 lib/IntaroCrm/Exception/ApiException.php delete mode 100644 lib/IntaroCrm/Exception/CurlException.php delete mode 100644 lib/IntaroCrm/RestApi.php create mode 100644 lib/RetailCrm/ApiClient.php create mode 100644 lib/RetailCrm/Exception/CurlException.php create mode 100644 lib/RetailCrm/Exception/InvalidJsonException.php create mode 100644 lib/RetailCrm/Http/Client.php create mode 100644 lib/RetailCrm/Response/ApiResponse.php create mode 100644 phpunit.xml.dist create mode 100644 tests/RetailCrm/Test/TestCase.php create mode 100644 tests/RetailCrm/Tests/ApiClientTest.php create mode 100644 tests/RetailCrm/Tests/Http/ClientTest.php create mode 100644 tests/RetailCrm/Tests/Response/ApiResponseTest.php create mode 100644 tests/bootstrap.php diff --git a/.gitignore b/.gitignore index e43b0f9..7ce5942 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ .DS_Store +phpunit.xml +vendor/ +composer.lock \ No newline at end of file diff --git a/README.md b/README.md index 2af9afe..16ad6d8 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ -IntaroCRM REST API client +PHP client for retailCRM API ================= -PHP Client for [IntaroCRM REST API](http://docs.intarocrm.ru/rest-api/). +PHP client for [retailCRM API](http://www.retailcrm.ru/docs/Разработчики/Разработчики#api). Requirements ------------ @@ -14,47 +14,7 @@ Installation 1) Install [composer](https://getcomposer.org/download/) into the project directory. -2) Add IntaroCRM REST API client in your composer.json: -```js -{ - "require": { - "intarocrm/rest-api-client": "1.3.*" - } -} -``` -3) Use command `php composer.phar update intarocrm/rest-api-client` to install new vendor into `vendor/` folder. - - - -Usage ------------- - -### Create API clent class - -``` php - -$crmApiClient = new \IntaroCrm\RestApi( - 'https://demo.intarocrm.ru', - 'T9DMPvuNt7FQJMszHUdG8Fkt6xHsqngH' -); -``` -Constructor arguments are: - -1. Your IntaroCRM acount URL-address -2. Your site API Token - -### Example: get order types list - -``` php - -try { - $orderTypes = $crmApiClient->orderTypesList(); -} -catch (\IntaroCrm\Exception\CurlException $e) { - //$logger->addError('orderTypesList: connection error'); -} -catch (\IntaroCrm\Exception\ApiException $e) { - //$logger->addError('orderTypesList: ' . $e->getMessage()); -} - +2) Run: +```bash +composer require retailcrm/api-client-php 3.0 ``` diff --git a/composer.json b/composer.json index 4a0745b..aad1734 100644 --- a/composer.json +++ b/composer.json @@ -1,29 +1,28 @@ { - "name": "intarocrm/rest-api-client", - "description": "PHP Client for IntaroCRM REST API", + "name": "retailcrm/api-client-php", + "description": "PHP client for retailCRM API", "type": "library", - "keywords": ["api", "Intaro CRM", "rest"], - "homepage": "http://www.intarocrm.ru/", + "keywords": ["API", "retailCRM", "REST"], + "homepage": "http://www.retailcrm.ru/", "authors": [ { - "name": "Kruglov Kirill", - "email": "kruglov@intaro.ru", - "role": "Developer" + "name": "retailCRM", + "email": "support@retailcrm.ru" } ], "require": { - "php": ">=5.2.0", + "php": ">=5.3.0", "ext-curl": "*" }, "support": { "email": "support@intarocrm.ru" }, "autoload": { - "psr-0": { "IntaroCrm\\": "lib/" } + "psr-0": { "RetailCrm\\": "lib/" } }, "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "3.0.x-dev" } } } \ No newline at end of file diff --git a/lib/IntaroCrm/Exception/ApiException.php b/lib/IntaroCrm/Exception/ApiException.php deleted file mode 100644 index 75e4d8d..0000000 --- a/lib/IntaroCrm/Exception/ApiException.php +++ /dev/null @@ -1,6 +0,0 @@ -apiUrl = $crmUrl.'/api/v'.$this->apiVersion.'/'; - $this->apiKey = $apiKey; - $this->parameters = array('apiKey' => $this->apiKey); - } - - /* Методы для работы с заказами */ - /** - * Получение заказа по id - * - * @param string $id - идентификатор заказа - * @param string $by - поиск заказа по id или externalId - * @return array - информация о заказе - */ - public function orderGet($id, $by = 'externalId') - { - $url = $this->apiUrl.'orders/'.$id; - - if ($by != 'externalId') - $this->parameters['by'] = $by; - $result = $this->curlRequest($url); - return $result; - } - - /** - * Создание заказа - * - * @param array $order- информация о заказе - * @return array - */ - public function orderCreate($order) - { - $dataJson = json_encode($order); - $this->parameters['order'] = $dataJson; - - $url = $this->apiUrl.'orders/create'; - $result = $this->curlRequest($url, 'POST'); - return $result; - } - - /** - * Изменение заказа - * - * @param array $order- информация о заказе - * @return array - */ - public function orderEdit($order) - { - $dataJson = json_encode($order); - $this->parameters['order'] = $dataJson; - - $url = $this->apiUrl.'orders/'.$order['externalId'].'/edit'; - $result = $this->curlRequest($url, 'POST'); - return $result; - } - - /** - * Пакетная загрузка заказов - * - * @param array $orders - массив заказов - * @return array - */ - public function orderUpload($orders) - { - $dataJson = json_encode($orders); - $this->parameters['orders'] = $dataJson; - - $url = $this->apiUrl.'orders/upload'; - $result = $this->curlRequest($url, 'POST'); - if (is_null($result) && isset($result['uploadedOrders'])) - return $result['uploadedOrders']; - return $result; - } - - /** - * Обновление externalId у заказов с переданными id - * - * @param array $orders- массив, содержащий id и externalId заказа - * @return array - */ - public function orderFixExternalIds($order) - { - $dataJson = json_encode($order); - $this->parameters['orders'] = $dataJson; - - $url = $this->apiUrl.'orders/fix-external-ids'; - $result = $this->curlRequest($url, 'POST'); - return $result; - } - - /** - * Получение последних измененных заказов - * - * @param \DateTime|string|int $startDate - начальная дата и время выборки (Y-m-d H:i:s) - * @param \DateTime|string|int $endDate - конечная дата и время выборки (Y-m-d H:i:s) - * @param int $limit - ограничение на размер выборки - * @param int $offset - сдвиг - * @return array - массив заказов - */ - public function orderHistory($startDate = null, $endDate = null, $limit = 100, $offset = 0) - { - $url = $this->apiUrl.'orders/history'; - $this->parameters['startDate'] = $this->ensureDateTime($startDate); - $this->parameters['endDate'] = $this->ensureDateTime($endDate); - $this->parameters['limit'] = $limit; - $this->parameters['offset'] = $offset; - - $result = $this->curlRequest($url); - return $result; - } - - /* Методы для работы с клиентами */ - /** - * Получение клиента по id - * - * @param string $id - идентификатор - * @param string $by - поиск заказа по id или externalId - * @return array - информация о клиенте - */ - public function customerGet($id, $by = 'externalId') - { - $url = $this->apiUrl.'customers/'.$id; - if ($by != 'externalId') - $this->parameters['by'] = $by; - $result = $this->curlRequest($url); - return $result; - } - - /** - * Получение списка клиентов в соответсвии с запросом - * - * @param string $phone - телефон - * @param string $email - почтовый адрес - * @param string $fio - фио пользователя - * @param int $limit - ограничение на размер выборки - * @param int $offset - сдвиг - * @return array - массив клиентов - */ - public function customers($phone = null, $email = null, $fio = null, $limit = 200, $offset = 0) - { - $url = $this->apiUrl.'customers'; - if($phone) $this->parameters['phone'] = $phone; - if($email) $this->parameters['email'] = $email; - if($fio) $this->parameters['fio'] = $fio; - $this->parameters['limit'] = $limit; - $this->parameters['offset'] = $offset; - - $result = $this->curlRequest($url); - return $result; - } - - /** - * Создание клиента - * - * @param array $customer - информация о клиенте - * @return array - */ - public function customerCreate($customer) - { - $dataJson = json_encode($customer); - $this->parameters['customer'] = $dataJson; - - $url = $this->apiUrl.'customers/create'; - $result = $this->curlRequest($url, 'POST'); - return $result; - } - - /** - * Редактирование клиента - * - * @param array $customer - информация о клиенте - * @return array - */ - public function customerEdit($customer) - { - $dataJson = json_encode($customer); - $this->parameters['customer'] = $dataJson; - - $url = $this->apiUrl.'customers/'.$customer['externalId'].'/edit'; - $result = $this->curlRequest($url, 'POST'); - return $result; - } - - /** - * Пакетная загрузка клиентов - * - * @param array $customers - массив клиентов - * @return array - */ - public function customerUpload($customers) - { - $dataJson = json_encode($customers); - $this->parameters['customers'] = $dataJson; - - $url = $this->apiUrl.'customers/upload'; - $result = $this->curlRequest($url, 'POST'); - if (is_null($result) && isset($result['uploaded'])) - return $result['uploaded']; - return $result; - } - - /** - * Обновление externalId у клиентов с переданными id - * - * @param array $customers- массив, содержащий id и externalId заказа - * @return array - */ - public function customerFixExternalIds($customers) - { - $dataJson = json_encode($customers); - $this->parameters['customers'] = $dataJson; - - $url = $this->apiUrl.'customers/fix-external-ids'; - $result = $this->curlRequest($url, 'POST'); - return $result; - } - - /** - * Получение списка заказов клиента - * - * @param string $id - идентификатор клиента - * @param string $by - поиск заказа по id или externalId - * @param \DateTime|string|int $startDate - начальная дата выборки (Y-m-d H:i:s) - * @param \DateTime|string|int $endDate - конечная дата выборки (Y-m-d H:i:s) - * @param int $limit - ограничение на размер выборки - * @param int $offset - сдвиг - * @return array - массив заказов - */ - public function customerOrdersList($id, $startDate = null, $endDate = null, - $limit = 100, $offset = 0, $by = 'externalId') - { - $url = $this->apiUrl.'customers/'.$id.'/orders'; - if ($by != 'externalId') - $this->parameters['by'] = $by; - $this->parameters['startDate'] = $this->ensureDateTime($startDate); - $this->parameters['endDate'] = $this->ensureDateTime($endDate); - $this->parameters['limit'] = $limit; - $this->parameters['offset'] = $offset; - - $result = $this->curlRequest($url); - return $result; - } - - /* Методы для работы со справочниками */ - /** - * Получение списка типов доставки - * - * @return array - массив типов доставки - */ - public function deliveryTypesList() - { - $url = $this->apiUrl.'reference/delivery-types'; - $result = $this->curlRequest($url); - return $result; - } - - /** - * Редактирование типа доставки - * - * @param array $deliveryType - информация о типе доставки - * @return array - */ - public function deliveryTypeEdit($deliveryType) - { - $dataJson = json_encode($deliveryType); - $this->parameters['deliveryType'] = $dataJson; - - $url = $this->apiUrl.'reference/delivery-types/'.$deliveryType['code'].'/edit'; - $result = $this->curlRequest($url, 'POST'); - return $result; - } - - /** - * Получение списка служб доставки - * - * @return array - массив типов доставки - */ - public function deliveryServicesList() - { - $url = $this->apiUrl.'reference/delivery-services'; - $result = $this->curlRequest($url); - return $result; - } - - /** - * Редактирование службы доставки - * - * @param array $deliveryService - информация о типе доставки - * @return array - */ - public function deliveryServiceEdit($deliveryService) - { - $dataJson = json_encode($deliveryService); - $this->parameters['deliveryService'] = $dataJson; - - $url = $this->apiUrl.'reference/delivery-services/'.$deliveryService['code'].'/edit'; - $result = $this->curlRequest($url, 'POST'); - return $result; - } - - - /** - * Получение списка типов оплаты - * - * @return array - массив типов оплаты - */ - public function paymentTypesList() - { - $url = $this->apiUrl.'reference/payment-types'; - $result = $this->curlRequest($url); - return $result; - } - - /** - * Редактирование типа оплаты - * - * @param array $paymentType - информация о типе оплаты - * @return array - */ - public function paymentTypesEdit($paymentType) - { - $dataJson = json_encode($paymentType); - $this->parameters['paymentType'] = $dataJson; - - $url = $this->apiUrl.'reference/payment-types/'.$paymentType['code'].'/edit'; - $result = $this->curlRequest($url, 'POST'); - return $result; - } - - - /** - * Получение списка статусов оплаты - * - * @return array - массив статусов оплаты - */ - public function paymentStatusesList() - { - $url = $this->apiUrl.'reference/payment-statuses'; - $result = $this->curlRequest($url); - return $result; - } - - /** - * Редактирование статуса оплаты - * - * @param array $paymentStatus - информация о статусе оплаты - * @return array - */ - public function paymentStatusesEdit($paymentStatus) - { - $dataJson = json_encode($paymentStatus); - $this->parameters['paymentStatus'] = $dataJson; - - $url = $this->apiUrl.'reference/payment-statuses/'.$paymentStatus['code'].'/edit'; - $result = $this->curlRequest($url, 'POST'); - return $result; - } - - - /** - * Получение списка типов заказа - * - * @return array - массив типов заказа - */ - public function orderTypesList() - { - $url = $this->apiUrl.'reference/order-types'; - $result = $this->curlRequest($url); - return $result; - } - - /** - * Редактирование типа заказа - * - * @param array $orderType - информация о типе заказа - * @return array - */ - public function orderTypesEdit($orderType) - { - $dataJson = json_encode($orderType); - $this->parameters['orderType'] = $dataJson; - - $url = $this->apiUrl.'reference/order-types/'.$orderType['code'].'/edit'; - $result = $this->curlRequest($url, 'POST'); - return $result; - } - - - /** - * Получение списка способов оформления заказа - * - * @return array - массив способов оформления заказа - */ - public function orderMethodsList() - { - $url = $this->apiUrl.'reference/order-methods'; - $result = $this->curlRequest($url); - return $result; - } - - /** - * Редактирование способа оформления заказа - * - * @param array $orderMethod - информация о способе оформления заказа - * @return array - */ - public function orderMethodsEdit($orderMethod) - { - $dataJson = json_encode($orderMethod); - $this->parameters['orderMethod'] = $dataJson; - - $url = $this->apiUrl.'reference/order-methods/'.$orderMethod['code'].'/edit'; - $result = $this->curlRequest($url, 'POST'); - return $result; - } - - /** - * Получение списка статусов заказа - * - * @return array - массив статусов заказа - */ - public function orderStatusesList() - { - $url = $this->apiUrl.'reference/statuses'; - $result = $this->curlRequest($url); - return $result; - } - - /** - * Редактирование статуса заказа - * - * @param array $status - информация о статусе заказа - * @return array - */ - public function orderStatusEdit($status) - { - $dataJson = json_encode($status); - $this->parameters['status'] = $dataJson; - - $url = $this->apiUrl.'reference/statuses/'.$status['code'].'/edit'; - $result = $this->curlRequest($url, 'POST'); - return $result; - } - - - /** - * Получение списка групп статусов заказа - * - * @return array - массив групп статусов заказа - */ - public function orderStatusGroupsList() - { - $url = $this->apiUrl.'reference/status-groups'; - $result = $this->curlRequest($url); - return $result; - } - - /** - * Обновление статистики - * - * @return array - статус вып обновления - */ - public function statisticUpdate() - { - $url = $this->apiUrl.'statistic/update'; - $result = $this->curlRequest($url); - return $result; - } - - /** - * @return \DateTime - */ - public function getGeneratedAt() - { - return $this->generatedAt; - } - - protected function ensureDateTime($value) - { - if ($value instanceof \DateTime) { - return $value->format('Y-m-d H:i:s'); - } elseif (is_int($value)) { - return date('Y-m-d H:i:s', $value); - } - - return $value; - } - - protected function getErrorMessage($response) - { - $str = ''; - if (isset($response['message'])) - $str = $response['message']; - elseif (isset($response[0]['message'])) - $str = $response[0]['message']; - elseif (isset($response['error']) && isset($response['error']['message'])) - $str = $response['error']['message']; - elseif (isset($response['errorMsg'])) - $str = $response['errorMsg']; - - if (isset($response['errors']) && sizeof($response['errors'])) { - foreach ($response['errors'] as $error) - $str .= '. ' . $error; - } - - if (!strlen($str)) - return 'Application Error'; - - return $str; - } - - protected function curlRequest($url, $method = 'GET', $format = 'json') - { - if ($method == 'GET' && !is_null($this->parameters)) - $url .= '?'.http_build_query($this->parameters); - - $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, $url); - curl_setopt($ch, CURLOPT_FAILONERROR, FALSE); - //curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);// allow redirects - curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // return into a variable - curl_setopt($ch, CURLOPT_TIMEOUT, 30); // times out after 30s - //curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); - - - if ($method == 'POST') - { - curl_setopt($ch, CURLOPT_POST, true); - curl_setopt($ch, CURLOPT_POSTFIELDS, $this->parameters); - } - - $response = curl_exec($ch); - $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); - unset($this->parameters); - /* Сброс массива с параметрами */ - $this->parameters = array('apiKey' => $this->apiKey); - - $errno = curl_errno($ch); - $error = curl_error($ch); - curl_close($ch); - - if ($errno) - throw new Exception\CurlException($error, $errno); - - $result = json_decode($response, true); - - if ($statusCode >= 400 || isset($result['success']) && $result['success'] === false) { - throw new Exception\ApiException($this->getErrorMessage($result), $statusCode); - } - - if (isset($result['generatedAt'])) { - $this->generatedAt = new \DateTime($result['generatedAt']); - unset($result['generatedAt']); - } - - unset($result['success']); - - if (count($result) == 0) - return true; - - return reset($result); - } -} diff --git a/lib/RetailCrm/ApiClient.php b/lib/RetailCrm/ApiClient.php new file mode 100644 index 0000000..f79b6e3 --- /dev/null +++ b/lib/RetailCrm/ApiClient.php @@ -0,0 +1,101 @@ +client = new Client($url, array('apiKey' => $apiKey)); + } + + /** + * Create a order + * + * @param array $order + * @return ApiResponse + */ + public function ordersCreate(array $order) + { + return $this->client->makeRequest("/orders/create", Client::METHOD_POST, array( + 'order' => json_encode($order) + )); + } + + /** + * Edit a order + * + * @param array $order + * @return ApiResponse + */ + public function ordersEdit(array $order, $by = 'externalId') + { + $this->checkIdParameter($by); + + if (!isset($order[$by])) { + throw new \InvalidArgumentException(sprintf('Order array must contain the "%s" parameter.', $by)); + } + + return $this->client->makeRequest("/orders/" . $order[$by] . "/edit", Client::METHOD_POST, array( + 'order' => json_encode($order), + 'by' => $by, + )); + } + + /** + * Get order by id or externalId + * + * @param string $id + * @param string $by (default: 'externalId') + * @return ApiResponse + */ + public function ordersGet($id, $by = 'externalId') + { + $this->checkIdParameter($by); + + return $this->client->makeRequest("/orders/$id", Client::METHOD_GET, array('by' => $by)); + } + + /** + * Check ID parameter + * + * @param string $by + * @return bool + */ + protected function checkIdParameter($by) + { + $allowedForBy = array('externalId', 'id'); + if (!in_array($by, $allowedForBy)) { + throw new \InvalidArgumentException(sprintf( + 'Value "%s" for parameter "by" is not valid. Allowed values are %s.', + $by, + implode(', ', $allowedForBy) + )); + } + + return true; + } +} \ No newline at end of file diff --git a/lib/RetailCrm/Exception/CurlException.php b/lib/RetailCrm/Exception/CurlException.php new file mode 100644 index 0000000..098fc30 --- /dev/null +++ b/lib/RetailCrm/Exception/CurlException.php @@ -0,0 +1,7 @@ +url = $url; + $this->defaultParameters = $defaultParameters; + } + + /** + * Make HTTP request + * + * @param string $path + * @param string $method (default: 'GET') + * @param array $parameters (default: array()) + * @return ApiResponse + */ + public function makeRequest($path, $method, array $parameters = array(), $timeout = 30) + { + $allowedMethods = array(self::METHOD_GET, self::METHOD_POST); + if (!in_array($method, $allowedMethods)) { + throw new \InvalidArgumentException(sprintf( + 'Method "%s" is not valid. Allowed methods are %s', + $method, + implode(', ', $allowedMethods) + )); + } + + $parameters = array_merge($this->defaultParameters, $parameters); + + $path = $this->url . $path; + if (self::METHOD_GET === $method && sizeof($parameters)) { + $path .= '?' . http_build_query($parameters); + } + + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $path); + curl_setopt($ch, CURLOPT_FAILONERROR, FALSE); + // curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); // allow redirects + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // return into a variable + curl_setopt($ch, CURLOPT_TIMEOUT, (int) $timeout); // times out after 30s + // curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); + + if (self::METHOD_POST === $method) { + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_POSTFIELDS, $parameters); + } + + $responseBody = curl_exec($ch); + $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + + $errno = curl_errno($ch); + $error = curl_error($ch); + curl_close($ch); + + if ($errno) { + throw new CurlException($error, $errno); + } + + return new ApiResponse($statusCode, $responseBody); + } + } diff --git a/lib/RetailCrm/Response/ApiResponse.php b/lib/RetailCrm/Response/ApiResponse.php new file mode 100644 index 0000000..c35c6db --- /dev/null +++ b/lib/RetailCrm/Response/ApiResponse.php @@ -0,0 +1,112 @@ +statusCode = (int) $statusCode; + + if (!empty($responseBody)) { + $response = json_decode($responseBody, true); + + if (!$response && JSON_ERROR_NONE !== ($error = json_last_error())) { + throw new InvalidJsonException( + "Invalid JSON in the API response body. Error code #$error", + $error + ); + } + + $this->response = $response; + } + } + + /** + * Return HTTP response status code + * + * @return int + */ + public function getStatusCode() + { + return $this->statusCode; + } + + /** + * HTTP request was successful + * + * @return bool + */ + public function isSuccessful() + { + return $this->statusCode < 400; + } + + /** + * Allow to access for the property throw class method + * + * @param string $name + * @return mixed + */ + public function __call($name, $arguments) + { + // convert getSomeProperty to someProperty + $propertyName = strtolower(substr($name, 3, 1)) . substr($name, 4); + + if (!isset($this->response[$propertyName])) { + throw new \InvalidArgumentException("Method \"$name\" not found"); + } + + return $this->response[$propertyName]; + } + + /** + * Allow to access for the property throw object property + * + * @param string $name + * @return mixed + */ + public function __get($name) + { + if (!isset($this->response[$name])) { + throw new \InvalidArgumentException("Property \"$name\" not found"); + } + + return $this->response[$name]; + } + + public function offsetSet($offset, $value) + { + throw new \BadMethodCallException('This activity not allowed'); + } + + public function offsetUnset($offset) + { + throw new \BadMethodCallException('This call not allowed'); + } + + public function offsetExists($offset) + { + return isset($this->response[$offset]); + } + + public function offsetGet($offset) + { + if (!isset($this->response[$offset])) { + throw new \InvalidArgumentException("Property \"$offset\" not found"); + } + + return $this->response[$offset]; + } +} \ No newline at end of file diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..ac37b0e --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,21 @@ + + + + + + + + + + + + tests/RetailCrm/Tests + + + + + + ./src/RetailCrm + + + diff --git a/tests/RetailCrm/Test/TestCase.php b/tests/RetailCrm/Test/TestCase.php new file mode 100644 index 0000000..c004a66 --- /dev/null +++ b/tests/RetailCrm/Test/TestCase.php @@ -0,0 +1,20 @@ +assertInstanceOf('RetailCrm\ApiClient', $client); + } + + /** + * @group integration + */ + public function testOrdersCreate() + { + $client = static::getApiClient(); + + $externalId = time(); + + $response = $client->ordersCreate(array( + 'firstName' => self::FIRST_NAME, + 'externalId' => $externalId, + )); + $this->assertInstanceOf('RetailCrm\Response\ApiResponse', $response); + $this->assertEquals(201, $response->getStatusCode()); + $this->assertTrue(is_int($response->getId())); + + return array( + 'id' => $response->getId(), + 'externalId' => $externalId, + ); + } + + /** + * @group integration + * @depends testOrdersCreate + */ + public function testOrdersGet(array $ids) + { + $client = static::getApiClient(); + + $response = $client->ordersGet(678678678); + $this->assertInstanceOf('RetailCrm\Response\ApiResponse', $response); + $this->assertEquals(404, $response->getStatusCode()); + $this->assertFalse($response->success); + + $response = $client->ordersGet($ids['id'], 'id'); + $orderById = $response->order; + $this->assertInstanceOf('RetailCrm\Response\ApiResponse', $response); + $this->assertEquals(200, $response->getStatusCode()); + $this->assertTrue($response->success); + $this->assertEquals(self::FIRST_NAME, $response->order['firstName']); + + $response = $client->ordersGet($ids['externalId'], 'externalId'); + $this->assertEquals($orderById['id'], $response->order['id']); + + return $ids; + } + + /** + * @group unit + * @expectedException \InvalidArgumentException + */ + public function testOrdersGetException() + { + $client = static::getApiClient(); + + $response = $client->ordersGet(678678678, 'asdf'); + } + + /** + * @group integration + * @depends testOrdersGet + */ + public function testOrdersEdit(array $ids) + { + $client = static::getApiClient(); + + $response = $client->ordersEdit( + array( + 'id' => 22342134, + 'lastName' => '12345', + ), + 'id' + ); + $this->assertInstanceOf('RetailCrm\Response\ApiResponse', $response); + $this->assertEquals(404, $response->getStatusCode()); + + $response = $client->ordersEdit(array( + 'externalId' => $ids['externalId'], + 'lastName' => '12345', + )); + $this->assertInstanceOf('RetailCrm\Response\ApiResponse', $response); + $this->assertEquals(200, $response->getStatusCode()); + $this->assertTrue($response->success); + + $response = $client->ordersEdit(array( + 'externalId' => time(), + 'lastName' => '12345', + )); + $this->assertInstanceOf('RetailCrm\Response\ApiResponse', $response); + $this->assertEquals(201, $response->getStatusCode()); + $this->assertTrue($response->success); + } + + + /** + * @group unit + * @expectedException \InvalidArgumentException + */ + public function testOrdersEditException() + { + $client = static::getApiClient(); + + $response = $client->ordersEdit(array('id' => 678678678), 'asdf'); + } +} diff --git a/tests/RetailCrm/Tests/Http/ClientTest.php b/tests/RetailCrm/Tests/Http/ClientTest.php new file mode 100644 index 0000000..59b8260 --- /dev/null +++ b/tests/RetailCrm/Tests/Http/ClientTest.php @@ -0,0 +1,61 @@ +assertInstanceOf('RetailCrm\Http\Client', $client); + } + + /** + * @group unit + * @expectedException \InvalidArgumentException + */ + public function testHttpRequiring() + { + $client = new Client('http://a.intarocrm.ru', array('apiKey' => '123')); + } + + /** + * @group unit + * @expectedException \InvalidArgumentException + */ + public function testMakeRequestWrongMethod() + { + $client = new Client('https://asdf.df', array()); + $client->makeRequest('/a', 'adsf'); + } + + /** + * @group integration + * @expectedException RetailCrm\Exception\CurlException + */ + public function testMakeRequestWrongUrl() + { + $client = new Client('https://asdf.df', array()); + $client->makeRequest('/a', Client::METHOD_GET, array(), 1); + } + + /** + * @group integration + */ + public function testMakeRequestSuccess() + { + $client = new Client('https://demo.intarocrm.ru/api/' . ApiClient::VERSION, array()); + $response = $client->makeRequest('/a', Client::METHOD_GET); + + $this->assertInstanceOf('RetailCrm\Response\ApiResponse', $response); + $this->assertEquals(403, $response->getStatusCode()); + } +} diff --git a/tests/RetailCrm/Tests/Response/ApiResponseTest.php b/tests/RetailCrm/Tests/Response/ApiResponseTest.php new file mode 100644 index 0000000..fa70176 --- /dev/null +++ b/tests/RetailCrm/Tests/Response/ApiResponseTest.php @@ -0,0 +1,233 @@ +assertInstanceOf( + 'RetailCrm\Response\ApiResponse', + $response, + 'Response object created' + ); + + $response = new ApiResponse(201, '{ "success": true }'); + $this->assertInstanceOf( + 'RetailCrm\Response\ApiResponse', + $response, + 'Response object created' + ); + } + + /** + * @group unit + * @expectedException RetailCrm\Exception\InvalidJsonException + */ + public function testJsonInvalid() + { + $response = new ApiResponse(400, '{ "asdf": }'); + } + + /** + * @group unit + */ + public function testStatusCodeGetting() + { + $response = new ApiResponse(200); + $this->assertEquals( + 200, + $response->getStatusCode(), + 'Response object returns the right status code' + ); + + $response = new ApiResponse(460, '{ "success": false }'); + $this->assertEquals( + 460, + $response->getStatusCode(), + 'Response object returns the right status code' + ); + } + + /** + * @group unit + */ + public function testIsSuccessful() + { + $response = new ApiResponse(200); + $this->assertTrue( + $response->isSuccessful(), + 'Request was successful' + ); + + $response = new ApiResponse(460, '{ "success": false }'); + $this->assertFalse( + $response->isSuccessful(), + 'Request was failed' + ); + } + + /** + * @group unit + */ + public function testMagicCall() + { + $response = new ApiResponse(201, '{ "success": true }'); + $this->assertEquals( + true, + $response->getSuccess(), + 'Response object returns property value throw magic method' + ); + } + + /** + * @group unit + * @expectedException \InvalidArgumentException + */ + public function testMagicCallException1() + { + $response = new ApiResponse(200); + $response->getSome(); + } + + /** + * @group unit + * @expectedException \InvalidArgumentException + */ + public function testMagicCallException2() + { + $response = new ApiResponse(201, '{ "success": true }'); + $response->getSomeSuccess(); + } + + /** + * @group unit + */ + public function testMagicGet() + { + $response = new ApiResponse(201, '{ "success": true }'); + $this->assertEquals( + true, + $response->success, + 'Response object returns property value throw magic get' + ); + } + + /** + * @group unit + * @expectedException \InvalidArgumentException + */ + public function testMagicGetException1() + { + $response = new ApiResponse(200); + $response->some; + } + + /** + * @group unit + * @expectedException \InvalidArgumentException + */ + public function testMagicGetException2() + { + $response = new ApiResponse(201, '{ "success": true }'); + $response->someSuccess; + } + + /** + * @group unit + */ + public function testArrayGet() + { + $response = new ApiResponse(201, '{ "success": true }'); + $this->assertEquals( + true, + $response['success'], + 'Response object returns property value throw magic array get' + ); + } + + /** + * @group unit + * @expectedException \InvalidArgumentException + */ + public function testArrayGetException1() + { + $response = new ApiResponse(200); + $response['some']; + } + + /** + * @group unit + * @expectedException \InvalidArgumentException + */ + public function testArrayGetException2() + { + $response = new ApiResponse(201, '{ "success": true }'); + $response['someSuccess']; + } + + /** + * @group unit + */ + public function testArrayIsset() + { + $response = new ApiResponse(201, '{ "success": true }'); + + $this->assertTrue( + isset($response['success']), + 'Response object returns property existing' + ); + + $this->assertFalse( + isset($response['suess']), + 'Response object returns property existing' + ); + } + + /** + * @group unit + * @expectedException \BadMethodCallException + */ + public function testArraySetException1() + { + $response = new ApiResponse(201, '{ "success": true }'); + $response['success'] = 'a'; + } + + /** + * @group unit + * @expectedException \BadMethodCallException + */ + public function testArraySetException2() + { + $response = new ApiResponse(201, '{ "success": true }'); + $response['sssssssuccess'] = 'a'; + } + + /** + * @group unit + * @expectedException \BadMethodCallException + */ + public function testArrayUnsetException1() + { + $response = new ApiResponse(201, '{ "success": true }'); + unset($response['success']); + } + + /** + * @group unit + * @expectedException \BadMethodCallException + */ + public function testArrayUnsetException2() + { + $response = new ApiResponse(201, '{ "success": true }'); + unset($response['sssssssuccess']); + } +} diff --git a/tests/bootstrap.php b/tests/bootstrap.php new file mode 100644 index 0000000..f1cd65b --- /dev/null +++ b/tests/bootstrap.php @@ -0,0 +1,4 @@ +add('RetailCrm\\Test', __DIR__);