Skip to content

Commit

Permalink
Merge pull request #33 from MyParcelCOM/feature/added-additional-supp…
Browse files Browse the repository at this point in the history
…ort-classes

✨  Maintenance (support/exception classes)
  • Loading branch information
NickVries committed Apr 30, 2024
2 parents 0666188 + 3226943 commit db11ca6
Show file tree
Hide file tree
Showing 19 changed files with 563 additions and 140 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# integration-commons
Library with common classes used for constructing MyParcel.com eCommerce Integrations
# marketplace-commons
Library with common classes used for constructing MyParcel.com marketplace integrations

## PHP 8
The minimum PHP version is `8.2`. To update dependencies on a system without PHP 8 use:
Expand Down
242 changes: 124 additions & 118 deletions composer.lock

Large diffs are not rendered by default.

37 changes: 37 additions & 0 deletions src/Exceptions/AbstractRequestException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

declare(strict_types=1);

namespace MyParcelCom\Integration\Exceptions;

use InvalidArgumentException;
use Symfony\Component\HttpFoundation\Response;
use Throwable;

abstract class AbstractRequestException extends InvalidArgumentException
{
/**
* @psalm-pure
*/
public function __construct(
protected string $title,
string $detail,
int $code = 0,
Throwable $previous = null,
) {
parent::__construct($detail, $code, $previous);
}

public function render(): Response
{
return response()->json([
'errors' => [
[
'status' => (string) $this->code,
'title' => $this->title,
'detail' => $this->message,
],
],
], $this->code);
}
}
19 changes: 19 additions & 0 deletions src/Exceptions/RequestInputException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

declare(strict_types=1);

namespace MyParcelCom\Integration\Exceptions;

use Throwable;

class RequestInputException extends AbstractRequestException
{
public function __construct(
protected string $title,
string $detail,
int $code = 400,
Throwable $previous = null,
) {
parent::__construct($title, $detail, $code, $previous);
}
}
19 changes: 19 additions & 0 deletions src/Exceptions/RequestUnauthorizedException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

declare(strict_types=1);

namespace MyParcelCom\Integration\Exceptions;

use Throwable;

class RequestUnauthorizedException extends AbstractRequestException
{
public function __construct(
protected string $title,
string $detail,
int $code = 401,
Throwable $previous = null,
) {
parent::__construct($title, $detail, $code, $previous);
}
}
46 changes: 46 additions & 0 deletions src/Http/Requests/FormRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

declare(strict_types=1);

namespace MyParcelCom\Integration\Http\Requests;

use Illuminate\Foundation\Http\FormRequest as IlluminateFormRequest;
use MyParcelCom\Integration\Exceptions\RequestInputException;
use MyParcelCom\Integration\ShopId;
use Ramsey\Uuid\Exception\InvalidUuidStringException;
use Ramsey\Uuid\Uuid;

class FormRequest extends IlluminateFormRequest
{
public function authorize(): bool
{
return true;
}

/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules(): array
{
return [];
}

public function shopId(): ShopId
{
$shopId = $this->query('shop_id');

if (!$shopId) {
throw new RequestInputException('Bad request', 'No shop_id provided in the request query');
}

try {
$shopUuid = Uuid::fromString($shopId);
} catch (InvalidUuidStringException) {
throw new RequestInputException('Unprocessable entity', 'shop_id is not a valid UUID', 422);
}

return new ShopId($shopUuid);
}
}
50 changes: 50 additions & 0 deletions src/Http/Requests/OrdersCountRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

declare(strict_types=1);

namespace MyParcelCom\Integration\Http\Requests;

use Carbon\Carbon;
use Illuminate\Support\Facades\Validator;

class OrdersCountRequest extends FormRequest
{
private const DATE_FORMAT = 'Y-m-d';

public function dateFrom(): Carbon
{
$from = $this->query('date_from');
if (!$from) {
return Carbon::now()->subDay();
}

$this->validateDateFormat($from);

return $this->toCarbon($from);
}

public function dateTo(): Carbon
{
$to = $this->query('date_to');
if (!$to) {
return Carbon::now();
}

$this->validateDateFormat($to);

return $this->toCarbon($to);
}

private function validateDateFormat(string $date): void
{
Validator::validate(
['date' => $date],
['date' => 'date_format:' . self::DATE_FORMAT],
);
}

private function toCarbon(string $date): Carbon
{
return Carbon::createFromFormat(self::DATE_FORMAT, $date)->startOfDay();
}
}
36 changes: 36 additions & 0 deletions src/Http/Requests/ShipmentRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

declare(strict_types=1);

namespace MyParcelCom\Integration\Http\Requests;

use Carbon\Carbon;

class ShipmentRequest extends FormRequest
{
public function startDate(): Carbon
{
return Carbon::createFromFormat('Y-m-d H:i:s', $this->input('filter.start_date') . ' 00:00:00');
}

public function endDate(): Carbon
{
return Carbon::createFromFormat('Y-m-d H:i:s', $this->input('filter.end_date') . ' 23:59:59');
}

/**
* @return int|null
*/
public function pageNumber(): ?int
{
return $this->input('page.number') ? (int) $this->input('page.number') : null;
}

/**
* @return int|null
*/
public function pageSize(): ?int
{
return $this->input('page.size') ? (int) $this->input('page.size') : null;
}
}
61 changes: 61 additions & 0 deletions src/Http/Requests/ShipmentStatusCallbackRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

declare(strict_types=1);

namespace MyParcelCom\Integration\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Arr;
use MyParcelCom\Integration\Exceptions\RequestInputException;
use MyParcelCom\Integration\ShopId;
use Ramsey\Uuid\Exception\InvalidUuidStringException;
use Ramsey\Uuid\Uuid;

class ShipmentStatusCallbackRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}

/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules(): array
{
return [];
}

public function getShipmentData(): array
{
$included = $this->get('included');

return collect($included)->first(fn ($include) => $include['type'] === 'shipments');
}

public function getStatusData(): array
{
$included = $this->get('included');

return collect($included)->first(fn ($include) => $include['type'] === 'statuses');
}

public function shopId(): ShopId
{
$shopId = Arr::get($this->getShipmentData(), 'relationships.shop.data.id');

if (!$shopId) {
throw new RequestInputException('Bad request', 'No shop_id provided in the request body');
}

try {
$shopUuid = Uuid::fromString($shopId);
} catch (InvalidUuidStringException $exception) {
throw new RequestInputException('Unprocessable entity', 'shop_id is not a valid UUID', 422);
}

return new ShopId($shopUuid);
}
}
28 changes: 28 additions & 0 deletions src/Http/Requests/ShopSetupRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);

namespace MyParcelCom\Integration\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class ShopSetupRequest extends FormRequest
{
public function authorize(): true
{
return true;
}

public function rules(): array
{
return [
'data.settings' => 'array',
'data.redirect_url' => 'url',
];
}

public function redirectUrl(): ?string
{
return $this->input('data.redirect_url');
}
}
34 changes: 34 additions & 0 deletions src/Http/Responses/ShopSetupResponse.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

declare(strict_types=1);

namespace MyParcelCom\Integration\Http\Responses;

use Illuminate\Contracts\Support\Responsable;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Response;
use Symfony\Component\HttpFoundation\Response as SymfonyResponse;

class ShopSetupResponse implements Responsable
{
public function __construct(
private readonly ?string $authorizationUrl = null,
) {
}

/**
* @inheritDoc
*/
public function toResponse($request): SymfonyResponse
{
if (!$this->authorizationUrl) {
return new Response('', SymfonyResponse::HTTP_NO_CONTENT);
}

return new JsonResponse([
'data' => [
'authorization_url' => $this->authorizationUrl,
]
]);
}
}
20 changes: 20 additions & 0 deletions src/Http/Responses/ShopTearDownResponse.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

declare(strict_types=1);

namespace MyParcelCom\Integration\Http\Responses;

use Illuminate\Contracts\Support\Responsable;
use Illuminate\Http\Response;
use Symfony\Component\HttpFoundation\Response as SymfonyResponse;

class ShopTearDownResponse implements Responsable
{
/**
* @inheritDoc
*/
public function toResponse($request): SymfonyResponse
{
return new Response('', SymfonyResponse::HTTP_NO_CONTENT);
}
}
10 changes: 7 additions & 3 deletions src/Order/Items/Feature.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

namespace MyParcelCom\Integration\Order\Items;

use JetBrains\PhpStorm\ArrayShape;

class Feature
{
public function __construct(
Expand All @@ -15,7 +13,13 @@ public function __construct(
) {
}

#[ArrayShape(['key' => 'string', 'value' => 'string|int|float|bool', 'annotation' => 'string|null'])]
/**
* @return array{
* key: string,
* value: string|int|float|bool,
* annotation: string|null
* }
*/
public function toArray(): array
{
return array_filter([
Expand Down
Loading

0 comments on commit db11ca6

Please sign in to comment.