Skip to content

Commit

Permalink
v2.0.4 (#72)
Browse files Browse the repository at this point in the history
* Fix query params formatting for arrays in Mirakl API calls
  • Loading branch information
youssef-stripe authored Mar 25, 2021
1 parent 3ce889b commit 5597398
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 36 deletions.
75 changes: 45 additions & 30 deletions src/Service/MiraklClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,27 @@ public function __construct(HttpClientInterface $miraklClient)
$this->client = $miraklClient;
}

private function get(string $endpoint, array $params = []): ResponseInterface
{
if ($params) {
$endpoint .= '?' . $this->parseQueryParams($params);
}

return $this->client->request('GET', $endpoint);
}

private function put(string $endpoint, array $params): ResponseInterface
{
$options = [ 'json' => $params ];
return $this->client->request('PUT', $endpoint, $options);
}

private function parseQueryParams(array $params)
{
$queryString = http_build_query($params, '', '&', PHP_QUERY_RFC3986);
return preg_replace('/%5B[0-9]*%5D=/U', '=', $queryString);
}

private function parseResponse(ResponseInterface $response, string ...$path)
{
$body = json_decode($response->getContent(), true);
Expand All @@ -49,12 +70,11 @@ private function parseResponse(ResponseInterface $response, string ...$path)

private function paginateByOffset(string $endpoint, array $params = [], string ...$path)
{
$options = [ 'query' => array_merge([ 'max' => 10 ], $params) ];

$response = $this->client->request('GET', $endpoint, $options);
$response = $this->get($endpoint, array_merge([ 'max' => 10 ], $params));
$body = $this->parseResponse($response, ...$path);

while ($next = $this->getNextLink($response)) {
$response = $this->client->request('GET', $next);
$response = $this->get($next);
$objects = $this->parseResponse($response, ...$path);
if (empty($objects)) {
break;
Expand All @@ -68,13 +88,11 @@ private function paginateByOffset(string $endpoint, array $params = [], string .

private function paginateByPage(string $endpoint, array $params = [], string ...$path)
{
$options = [ 'query' => array_merge([ 'limit' => 10 ], $params) ];

$response = $this->client->request('GET', $endpoint, $options);
$response = $this->get($endpoint, array_merge([ 'limit' => 10 ], $params));
$body = $this->parseResponse($response, ...$path);

while ($next = $this->getNextPage($response)) {
$options = [ 'query' => [ 'page_token' => $next ] ];
$response = $this->client->request('GET', $endpoint, $options);
$response = $this->get($endpoint, [ 'page_token' => $next ]);
$objects = $this->parseResponse($response, ...$path);
if (empty($objects)) {
break;
Expand Down Expand Up @@ -178,7 +196,7 @@ public function listProductPendingDebits()
// PA01
public function validateProductPendingDebits(array $orders)
{
$this->client->request('PUT', '/api/payment/debit', [ 'json' => [ 'orders' => $orders ] ]);
$this->put('/api/payment/debit', [ 'orders' => $orders ]);
}

// PA12
Expand Down Expand Up @@ -209,7 +227,7 @@ public function listProductPendingRefunds()
// PA02
public function validateProductPendingRefunds(array $refunds)
{
$this->client->request('PUT', '/api/payment/refund', [ 'json' => [ 'refunds' => $refunds ] ]);
$this->put('/api/payment/refund', [ 'refunds' => $refunds ]);
}

// SOR11
Expand All @@ -231,15 +249,15 @@ public function listServiceOrdersByDate(string $datetime)
// SOR11 by order_id
public function listServiceOrdersById(array $orderIds)
{
$res = $this->paginateByPage('/api/mms/orders', [ 'order_id' => implode(',', $orderIds) ], 'data');
$res = $this->paginateByPage('/api/mms/orders', [ 'order_id' => $orderIds ], 'data');
$res = $this->arraysToObjects($res, MiraklServiceOrder::class);
return $this->objectsToMap($res, 'getId');
}

// SOR11 by commercial_id
public function listServiceOrdersByCommercialId(array $commercialIds)
{
$res = $this->paginateByPage('/api/mms/orders', [ 'commercial_order_id' => implode(',', $commercialIds) ], 'data');
$res = $this->paginateByPage('/api/mms/orders', [ 'commercial_order_id' => $commercialIds ], 'data');
$res = $this->arraysToObjects($res, MiraklServiceOrder::class);
return $this->objectsToMap($res, 'getCommercialId', 'getId');
}
Expand All @@ -255,15 +273,15 @@ public function listServicePendingDebits()
// SPA11 by order ID
public function listServicePendingDebitsByOrderIds(array $orderIds)
{
$res = $this->paginateByPage('/api/mms/debits', [ 'order_id' => implode(',', $orderIds) ], 'data');
$res = $this->paginateByPage('/api/mms/debits', [ 'order_id' => $orderIds ], 'data');
$res = $this->arraysToObjects($res, MiraklServicePendingDebit::class);
return $this->objectsToMap($res, 'getOrderId');
}

// SPA01
public function validateServicePendingDebits(array $orders)
{
$this->client->request('PUT', '/api/mms/debits', [ 'json' => [ 'orders' => $orders ] ]);
$this->put('/api/mms/debits', [ 'orders' => $orders ]);
}

// SPA12
Expand All @@ -277,7 +295,7 @@ public function listServicePendingRefunds()
// SPA02
public function validateServicePendingRefunds(array $refunds)
{
$this->client->request('PUT', '/api/mms/refunds', [ 'json' => $refunds ]);
$this->put('/api/mms/refunds', $refunds);
}

// IV01
Expand All @@ -304,30 +322,27 @@ public function listInvoicesByShopId(int $shopId)
// S20
public function fetchShops(?array $shopIds, ?\DateTimeInterface $updatedAfter = null, bool $paginate = true)
{
$filters = ['query' => []];
$filters['query']['domains'] = 'PRODUCT,SERVICE';
$filters['query']['paginate'] = $paginate ? 'true' : 'false';
$params = [
'domains' => 'PRODUCT,SERVICE',
'paginate' => $paginate ? 'true' : 'false'
];

if (null !== $shopIds) {
$filters['query']['shop_ids'] = implode(',', $shopIds);
$params['shop_ids'] = implode(',', $shopIds);
}
if (null !== $updatedAfter) {
$filters['query']['updated_since'] = $updatedAfter->format(self::DATE_FORMAT);
$params['updated_since'] = $updatedAfter->format(self::DATE_FORMAT);
}

$response = $this->client->request('GET', '/api/shops', $filters);

return $this->parseResponse($response, 'shops');
$res = $this->get('/api/shops', $params);
return $this->parseResponse($res, 'shops');
}

// S07
public function patchShops(array $patchedShops)
{
$response = $this->client->request('PUT', '/api/shops', [
'json' => [ 'shops' => $patchedShops ],
]);

return $this->parseResponse($response, 'shop_returns');
$res = $this->put('/api/shops', [ 'shops' => $patchedShops ]);
return $this->parseResponse($res, 'shop_returns');
}

// parse a date based on the format used by Mirakl
Expand All @@ -339,6 +354,6 @@ public static function getDatetimeFromString(string $date): \DateTimeInterface
// parse a date based on the format used by Mirakl
public static function getStringFromDatetime(\DateTimeInterface $date): string
{
return str_replace('+0000', 'Z', $date->format(self::DATE_FORMAT));
return $date->format(self::DATE_FORMAT);
}
}
39 changes: 33 additions & 6 deletions tests/MiraklMockedHttpClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ public function __construct(string $customFieldCode)

$responseFactory = function ($method, $url, $options) {
$path = parse_url($url, PHP_URL_PATH);
parse_str(parse_url($url, PHP_URL_QUERY), $params);
$params = $this->parseQueryParams(parse_url($url, PHP_URL_QUERY));
$requestBody = json_decode($options['body'] ?? '', true);
try {
$response = $this->mockResponse($method, $path, $params, $requestBody);
Expand Down Expand Up @@ -133,6 +133,31 @@ public function __construct(string $customFieldCode)
parent::__construct($responseFactory, self::MIRAKL_BASE_URL);
}

private function parseQueryParams($str)
{
$arr = [];
if (!$str) {
return $arr;
}

foreach (explode('&', $str) as $i) {
list($name, $value) = explode('=', $i, 2);
$value = urldecode($value);

if (isset($arr[$name])) {
if (is_array($arr[$name])) {
$arr[$name][] = $value;
} else {
$arr[$name] = array($arr[$name], $value);
}
} else {
$arr[$name] = $value;
}
}

return $arr;
}

private function isOffsetPagination($path, $params)
{
switch ($path) {
Expand All @@ -151,9 +176,9 @@ private function isOffsetPagination($path, $params)
private function getLinkHeader($path, $params)
{
if ($this->isOffsetPagination($path, $params) && 0 === ($params['offset'] ?? 0)) {
$previous = self::MIRAKL_BASE_URL . $path . '?' . http_build_query($params);
$previous = self::MIRAKL_BASE_URL . $path . '?' . http_build_query($params, '', '&', PHP_QUERY_RFC3986);
$params['offset'] = 10;
$next = self::MIRAKL_BASE_URL . $path . '?' . http_build_query($params);
$next = self::MIRAKL_BASE_URL . $path . '?' . http_build_query($params, '', '&', PHP_QUERY_RFC3986);
$link = '<' . $previous . '>; rel="previous", <' . $next . '>; rel="next"';
return [ 'Link' => $link ];
}
Expand Down Expand Up @@ -207,12 +232,14 @@ private function mockResponse(string $method, string $path, array $params, ?arra

return [ $key => $this->mockOrdersByStartDate($isService, $date, $page) ];
case isset($params['order_ids']): // Product
$orderIds = explode(',', $params['order_ids']);
case isset($params['order_id']): // Service
$orderIds = isset($params['order_id']) ? explode(',', $params['order_id']) : explode(',', $params['order_ids']);
$orderIds = $orderIds ?? (array) $params['order_id'];
return [ $key => $this->mockOrdersById($isService, $orderIds) ];
case isset($params['commercial_ids']): // Product
$commercialIds = explode(',', $params['commercial_ids']);
case isset($params['commercial_order_id']): // Service
$commercialIds = isset($params['commercial_order_id']) ? explode(',', $params['commercial_order_id']) : explode(',', $params['commercial_ids']);
$commercialIds = $commercialIds ?? (array) $params['commercial_order_id'];
return [ $key => $this->mockOrdersByCommercialId($isService, $commercialIds) ];
default:
return [ $key => [] ];
Expand All @@ -224,7 +251,7 @@ private function mockResponse(string $method, string $path, array $params, ?arra
$isService = $isService ?? false;
switch (true) {
case isset($params['order_id']):
return [ 'data' => $this->mockPendingDebitsByOrderIds(explode(',', $params['order_id'])) ];
return [ 'data' => $this->mockPendingDebitsByOrderIds((array) $params['order_id']) ];
case 'GET' === $method:
$pendingDebits = $this->mockPendingDebits($isService, $page);
if ($isService) {
Expand Down

0 comments on commit 5597398

Please sign in to comment.