Skip to content

Draft: Start making reusable responses for XML #16

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 36 commits into from
Jul 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
98d9e73
Start making reusable responses for XML
pionl May 10, 2022
4c074ba
Add ability to add header to environment
pionl May 11, 2022
f550ccc
Moved `WrkFlow\ApiSdkBuilder\Response` to `WrkFlow\ApiSdkBuilder\Fact…
pionl May 12, 2022
06e1d51
Improve required / optional getters for WorksWithXML + add datetime
pionl May 12, 2022
af2bbd5
Add more exceptions and use base exception
pionl May 12, 2022
a5d0354
Pass environment to options
pionl May 12, 2022
73fad3f
Add AbstractXMLOptions for building XML option bodies
pionl May 12, 2022
663d3dc
Upgrade rector config
pionl May 12, 2022
a4ebaef
Refactored error handling
pionl May 16, 2022
aa40a38
Improve testability without mocking + fix phpstan
pionl May 18, 2022
2686294
Convert JsonException to ResponseException
pionl May 20, 2022
6e730df
WorkWithValue: Ensure that empty string is interpreted as null
pionl May 24, 2022
ce688d3
Allow null value for xml transformer
pionl Jun 20, 2022
be94004
Upgrade ECS config
pionl Jun 20, 2022
d838aae
Add LaravelFactory that can be made by Laravels container
pionl Jun 22, 2022
f826de0
Renamed LaravelFactory to LaravelApiFactory
pionl Jun 22, 2022
8527ecb
Add dateTime / array getters for WorksWithJson
pionl Jun 23, 2022
d8af60b
Another breaking change - pass converted "body" parameter in __constr…
pionl Jun 23, 2022
42f53ff
Start re-working endpoints / responses to php-get-typed-value package…
pionl Aug 15, 2022
0ce5874
Refactored working with XML/JSON to GetValue package
pionl Aug 17, 2022
3a3a791
Add event support and add proper frameworks support
pionl Aug 23, 2022
8c9b4ac
Improve handling of response exception with custom exceptions + appen…
pionl Aug 24, 2022
b2e742f
Add ability to fake some of the requests or endpoints + fix Content-t…
pionl Aug 25, 2022
3677ad7
Fix xml response building with temp stream
pionl Aug 30, 2022
f8765fd
Log requests (Laravel) and set detect response headers for fake response
pionl Aug 31, 2022
4c7222a
Update ecs config
pionl Sep 12, 2022
f3ec698
Run ecs on rector and rector on ecs
pionl Sep 12, 2022
2ebac72
Laravel: Clip response/request body in logs to max 10 000 characters
pionl Sep 12, 2022
6a0602f
Update php-get-typed-value to show value in validation exception message
pionl Sep 12, 2022
c4c8832
Lint ecs + remove un-used illuminate/container dependency
pionl Sep 12, 2022
0b214bb
Update php-get-typed-value package
pionl Sep 23, 2022
834b731
Update dev packages
pionl May 4, 2023
33af9b7
Update PHP code check GitHub actions
pionl May 4, 2023
3686b0a
Add ability to log API communication (debug log, info log, request / …
pionl May 4, 2023
06543bc
Initialize SendRequestAction in lazy mode for easier testing
pionl Jul 17, 2023
11e2801
Upgrade dev depedencices and wrkflow/php-get-typed-value to 0.8.2
pionl Jul 25, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions .github/workflows/check-code.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: "Code check"

on:
push:
branches:
- main

workflow_call:

pull_request:
paths:
- "src/**"
- "tests/**"
- "composer.json"
- "ecs.php"
- "rector.php"
- "phpstan.neon"
- "phpstan-baseline.neon"
- "phpunit.xml"

concurrency:
group: php-sdk-builder-check-${{ github.ref }}
cancel-in-progress: true

jobs:
code:
name: "Code check"
uses: wrk-flow/reusable-workflows/.github/workflows/php-check.yml@b0886c7fa81dab2fb2615c06eb66e94711652056
secrets: inherit

tests:
name: "Run tests"
strategy:
matrix:
php-version: [ "8.1", "8.2" ]
uses: wrk-flow/reusable-workflows/.github/workflows/php-tests.yml@7b6e90f753beb05d979bf4ad39a009b353a7c6cc
secrets: inherit

15 changes: 0 additions & 15 deletions .github/workflows/check.yml

This file was deleted.

55 changes: 54 additions & 1 deletion UPGRADE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,57 @@

## v0.1.2

- Moved `WrkFlow\ApiSdkBuilder\ApiFactory` to `WrkFlow\ApiSdkBuilder\Factories\ApiFactory`
- Moved `WrkFlow\ApiSdkBuilder\ApiFactory` to `WrkFlow\ApiSdkBuilder\Factories\ApiFactory`.
- Moved `WrkFlow\ApiSdkBuilder\Response` namespace to `WrkFlow\ApiSdkBuilder\Factories\Responses` namespace.
- `WrkFlow\ApiSdkBuilder\Contracts\OptionsContract` has new signature for `toBody(AbstractEnvironment $environment)`.
- `WrkFlow\ApiSdkBuilder\Options\AbstractJsonOptions` has new signature for `toArray(AbstractEnvironment $environment)`.
- `WrkFlow\ApiSdkBuilder\Contracts\SDKContainerFactoryContract` has new signature `mixed $body` parameter for `makeResponse(string $class, ResponseInterface $response, mixed $body): AbstractResponse;`
- `WrkFlow\ApiSdkBuilder\Factories\GuzzleLaravelApiFactory` removed in favor of LaravelServiceProvider provider with HTTP auto discovery.
- `WrkFlow\ApiSdkBuilder\Factories\LaravelApiFactory` removed in favor of LaravelServiceProvider provider with HTTP auto discovery.

### Response classes

Response classes that extends `AbstractJsonResponse/AbstractJsonItemsResponse` requires new parameter `array $body` in `__construct`.

It is **important** that name of the parameters is `$body`.

**Also** `parseJson` function is removed. Transfer your parsing code within constructor.

- `json` returns `GetValue` instance.
- `xml` returns `GetValue` instance. [Docs](https://php-get-typed-value.wrk-flow.com).

### WorksWithJson / WorksWithXml / Transformers

Both traits were removed in favor of [GetValue package that makes accessing data easier](https://php-get-typed-value.wrk-flow.com).

### Endpoint

`makeResponse` has been removed. Update your endpoints to new usage:

```php
public function paginate(
GetUnitsOptions $options = null,
PageInfoOptions $page = new PageInfoOptions()
): UnitsResponse {
$result = $this->api->post($this->uri(), new MergedJsonOptions([$options, $page]));

return $this->makeResponse(UnitsResponse::class, $result);
}
```

to

```php
public function paginate(
GetUnitsOptions $options = null,
PageInfoOptions $page = new PageInfoOptions()
): UnitsResponse {
return $this->api->post(
responseClass: UnitsResponse::class,
uri: $this->uri(),
body: new MergedJsonOptions([$options, $page]),
);
}
```

`__construct` signature has been changed - `MakeBodyFromResponseAction $makeBodyFromResponseAction` removed.
43 changes: 27 additions & 16 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,28 +13,31 @@
"require": {
"php": ">=8.1",
"juststeveking/uri-builder": "^2.0",
"php-http/discovery": "^1.14",
"psr/http-client": "^1.0.1",
"psr/http-message": "^1.0.1"
"psr/http-message": "^1.0.1",
"wrkflow/php-get-typed-value": "^0.8.2"
},
"require-dev": {
"ext-simplexml": "*",
"guzzlehttp/guzzle": "^7.4",
"http-interop/http-factory-guzzle": "^1.2",
"illuminate/container": "^9",
"mockery/mockery": "^1.5",
"nyholm/psr7": "^1.5",
"phpstan/phpstan": "^1.6.3",
"phpstan/phpstan-deprecation-rules": "^1.0.0",
"phpstan/phpstan-mockery": "^1.0",
"phpstan/phpstan-phpunit": "^1.1.1",
"phpunit/phpunit": "^9.5.20",
"rector/rector": "^0.12.22",
"symplify/easy-coding-standard": "^10.2.2"
"laravel/framework": "^9.25",
"laravel/telescope": "v4.14.2",
"league/flysystem": "^3.14",
"mockery/mockery": "^1.5.1",
"nyholm/psr7": "^1.8.0",
"phpstan/phpstan": "1.10.26",
"phpstan/phpstan-deprecation-rules": "^1.1.3",
"phpstan/phpstan-mockery": "^1.1.1",
"phpstan/phpstan-phpunit": "1.3.13",
"phpunit/phpunit": "9.5.21",
"rector/rector": "0.17.7",
"symplify/easy-coding-standard": "11.5.0"
},
"suggest": {
"laravel/framework": "SDKs work great with Laravel - solid container.",
"wrkflow/larastrict": "Improve your Laravel code base with strict conventions.",
"guzzlehttp/guzzle": "If you want to use GuzzleLaravelApiFactory.",
"http-interop/http-factory-guzzle": "If you want to use GuzzleLaravelApiFactory."
"wrkflow/larastrict": "Improve your Laravel code base with strict conventions."
},
"scripts": {
"check": "composer lint && composer test",
Expand All @@ -43,7 +46,7 @@
"lint:stan": "./vendor/bin/phpstan",
"lint:upgrade:check": "vendor/bin/rector process --dry-run",
"lint:upgrade": "vendor/bin/rector process",
"lint": "composer lint:fix && composer lint:upgrade && composer lint:stan",
"lint": "composer lint:upgrade && composer lint:fix && composer lint:stan",
"test": "./vendor/bin/phpunit"
},
"autoload": {
Expand All @@ -56,12 +59,20 @@
"WrkFlow\\ApiSdkBuilderTests\\": "tests/"
}
},
"extra": {
"laravel": {
"providers": [
"WrkFlow\\ApiSdkBuilder\\Laravel\\LaravelServiceProvider"
]
}
},
"config": {
"preferred-install": "dist",
"sort-packages": true,
"optimize-autoloader": true,
"allow-plugins": {
"symfony/thanks": false
"symfony/thanks": false,
"php-http/discovery": false
}
},
"archive": {
Expand Down
50 changes: 24 additions & 26 deletions docs/content/en/architecture/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,20 @@ position: 11
API is built using these conventions:

- **API object:** provides the API interface
- **Environments:** provides user customization of the API
- **Environments:** provides user customization of the API
- **Endpoints:** provides a way to call API endpoint and return response
- **Options:** provides ability to send data to the API endpoint
- **Options:** provides ability to send data to the API endpoint
- **Response:** Holds the response data with defined "options".
- **Entities:** Data transfer objects for responses.
- **Transformers:** Transform classes that will transform any data (response array) to entity.
- **Entities:** Data transfer objects for responses.
- **Transformers:** Transform classes that will transform any data (response array) to entity.

## API

> See [Start building / Usage](/start-building/create-api)

API is the main class that holds:

- which environment we should use,
- which environment we should use,
- which endpoints are available
- defines base headers for the environment

Expand Down Expand Up @@ -77,32 +77,29 @@ Factory is later used in your API to build endpoints, responses.

## Transformers

- Try to indicate within the name of class what is the input / output.
- Try to indicate within the name of class what is the input / output (like *UnitAvailabilityToEntity* or *
JsonToUnitAvailability*).
- Always add `transform(IntType $object): OutType` function that will make the transformation.
- Extend `AbstractJsonTransformer` if you are converting array to entity object. Contains helper method from `WorksWithJson`
- We do recommend implementing `GetValueTransformerContract` interface which then can be used with `*GetterTransformers`

```php
use WrkFlow\ApiSdkBuilder\Transformers\AbstractJsonTransformer;
use use Wrkflow\GetValue\Transformers\ArrayItemGetterTransformer;

class JsonToUnitAvailabilityEntity extends AbstractJsonTransformer
class JsonToUnitAvailabilityEntity implements GetValueTransformerContract
{
private const KEY_AVAILABILITY_STATUS = 'availabilityStatus';

public function transform(array $item): UnitAvailabilityEntity
public function transform(GetValue $value, string $key): UnitAvailabilityEntity
{
$id = $this->getInt($item, 'ID');
$isAvailable = $this->getBool($item, 'isAvailable');

$availabilityStates = [];
if (array_key_exists(self::KEY_AVAILABILITY_STATUS, $item) === true
&& is_array($item[self::KEY_AVAILABILITY_STATUS]) === true) {
foreach ($item[self::KEY_AVAILABILITY_STATUS] as $item) {
$availabilityStates[] = new UnitAvailabilityStateEntity(
day: $item['day'],
state: AvailabilityState::from($item['status']),
$id = $value->getRequiredInt('ID');
$isAvailable = $value->getRequiredBool('isAvailable');

$availabilityStates = $value->getArray('availabilityStatus', [
new ArrayItemGetterTransformer(function (GetValue $value): UnitAvailabilityStateEntity {
return new UnitAvailabilityStateEntity(
day: $value->getRequiredString('day'),
state: $value->getRequiredEnum('status', AvailabilityState::class),
);
}
}
}),
]);

return new UnitAvailabilityEntity(
id: $id,
Expand All @@ -115,9 +112,10 @@ class JsonToUnitAvailabilityEntity extends AbstractJsonTransformer

## Entities

Entities are Data transfer objects. We do place them in `Entities` namespace when it is used by more responses. Otherwise, it is located in same folder as the endpoint.
Entities are Data transfer objects. We do place them in `Entities` namespace when it is used by more responses.
Otherwise, it is located in same folder as the endpoint.

The entity should be immutable.
The entity should be immutable.

```php
class UnitAvailabilityEntity
Expand Down
4 changes: 2 additions & 2 deletions docs/content/en/architecture/endpoints.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class UnitsEndpoint extends AbstractEndpoint
int $id,
GetUnitsOptions $options = null,
): UnitsResponse {
$result = $this->api->post($this->uri()->addPath($id), $options);
$result = $this->api->post($this->uri($id), $options);

return $this->makeResponse(UnitsResponse::class, $result);
}
Expand All @@ -59,7 +59,7 @@ In your endpoint use `$this->api->X()` to call API.
Use `$this->uri()` to get endpoints base url. You can append query data as you please:

- For adding query data use `$this->uri()->addQueryParam('key', 'myvalue')`
- Add path parameter using `$this->uri()->addPath($id)`. No need to add `/`.
- Add path parameter using `$this->uri($id)`. No need to add `/`.
- For more check [JustSteveKing/uri-builder](https://github.com/JustSteveKing/uri-builder).

### Passing data
Expand Down
2 changes: 1 addition & 1 deletion docs/content/en/architecture/headers.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class AcceptsJsonHeaders implements HeadersContract
public function headers(): array
{
return [
'Content-type' => 'application/json',
'Content-Type' => 'application/json',
];
}
}
Expand Down
4 changes: 2 additions & 2 deletions docs/content/en/architecture/responses.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,11 @@ These functions are provided for the consumer:
- You can use `$this->hasKeys(json: $json, keys: [...]): bool` to check if the array contains given keys.
- You can use [WorksWithJson](/architecture/utils#workswithjson) to easily get values from json with proper type.

## JSON response with items array
## JSON/XML response with items array

> For step by step implementation check [Start building / create response](/start-building/create-response)

Use this if you want to provide a way to easily access array items in the json using transformer and base root keys
Use this if you want to provide an easy access to transformed items (from XML/JSON to entity
validation.

### Consumer functions
Expand Down
Loading