Skip to content

Commit

Permalink
Add "Mutators" directory, deprecate "Transformer" directory (#7)
Browse files Browse the repository at this point in the history
  • Loading branch information
rougin authored Mar 24, 2024
1 parent 02c9ce5 commit 1891601
Show file tree
Hide file tree
Showing 11 changed files with 242 additions and 121 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ All notable changes to `Weasley` will be documented in this file.
### Added
- `TransformerInterface` for handling classes that transforms results
- `JsonTransformer` for transforming the results in JSON format
- `ApiTransformer` for transforming the results based on [Paypal's API Style Guide](https://github.com/paypal/api-standards/blob/master/api-style-guide.md)
- `ApiTransformer` for transforming the results based on [Paypal's API Style Guide](https://web.archive.org/web/20220114091735/https://github.com/paypal/api-standards/blob/master/api-style-guide.md)
- `RestfulController::transformer` for defining the transformer to be used in `RestfulController::index`
- Exception when the specified item does not exists in `RestfulController::show`

Expand Down
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,17 @@ The following classes below uses the [Middleware](https://github.com/rougin/slyt

**NOTE**: In other PHP frameworks, this is also known as `Middlewares`.

### Mutators

Mutators are classes that mutates (transforms) specified result (e.g., [PSR-07](https://www.php-fig.org/psr/psr-7/) responses, API data, etc.):

| Handler | Description |
| ---------- | ----------- |
| [JsonMutator](https://github.com/rougin/weasley/blob/master/src/Mutators/JsonMutator.php) | Mutates the PSR-07 response in JSON format. |
| [RestMutator](https://github.com/rougin/weasley/blob/master/src/Mutators/RestMutator.php) | Mutates the result created from `Laravel/Paginate` based on [Paypal's API Style Guide](https://web.archive.org/web/20220114091735/https://github.com/paypal/api-standards/blob/master/api-style-guide.md). |

**NOTE**: The `Laravel/Paginate` package must be included to use the parsing capabilities of `RestMutator`.

## Changelog

Please see [CHANGELOG][link-changelog] for more information what has changed recently.
Expand Down
20 changes: 20 additions & 0 deletions src/Contract/Mutator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace Rougin\Weasley\Contract;

/**
* Mutator Interface
*
* @package Weasley
* @author Rougin Gutib <rougingutib@gmail.com>
*/
interface Mutator
{
/**
* Mutates the contents of the result.
*
* @param mixed $data
* @return mixed
*/
public function mutate($data);
}
92 changes: 92 additions & 0 deletions src/Mutators/JsonMutator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<?php

namespace Rougin\Weasley\Mutators;

use Psr\Http\Message\ResponseInterface;
use Rougin\Weasley\Contract\Mutator;

/**
* JSON Transformer
*
* @package Weasley
* @author Rougin Gutib <rougingutib@gmail.com>
*/
class JsonMutator implements Mutator
{
/**
* @var array<integer, string>
*/
protected $errors = array();

/**
* @var integer
*/
protected $options = 0;

/**
* @var \Psr\Http\Message\ResponseInterface
*/
protected $response;

/**
* @param \Psr\Http\Message\ResponseInterface $response
* @param integer $options
*/
public function __construct(ResponseInterface $response, $options = 0)
{
$this->errors[] = 'No errors';
$this->errors[] = 'Maximum stack depth exceeded';
$this->errors[] = 'Underflow or the modes mismatch';
$this->errors[] = 'Unexpected control character found';
$this->errors[] = 'Syntax error, malformed JSON';
$this->errors[] = 'Malformed UTF-8 characters, possibly incorrectly encoded';
$this->errors[] = 'One or more recursive references in the value to be encoded';
$this->errors[] = 'One or more NAN or INF values in the value to be encoded';
$this->errors[] = 'A value of a type that cannot be encoded was given';
$this->errors[] = 'A property name that cannot be encoded was given';
$this->errors[] = 'Malformed UTF-16 characters, possibly incorrectly encoded';

$this->options = $options;

$this->response = $response;
}

/**
* @deprecated since ~0.7, use "mutate" instead.
* @codeCoverageIgnore
*
* Transforms the contents of the result.
*
* @param mixed $data
* @return mixed
*/
public function transform($data)
{
return $this->mutate($data);
}

/**
* Mutates the contents of the result.
*
* @param mixed $data
* @return mixed
*/
public function mutate($data)
{
$response = $this->response;

/** @var string */
$stream = @json_encode($data, $this->options);

if (json_last_error() !== JSON_ERROR_NONE)
{
$stream = $this->errors[json_last_error()];

$response = $response->withStatus(400);
}

$response->getBody()->write($stream);

return $response->withHeader('Content-Type', 'application/json');
}
}
77 changes: 77 additions & 0 deletions src/Mutators/RestMutator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?php

namespace Rougin\Weasley\Mutators;

use Illuminate\Contracts\Support\Arrayable;
use Rougin\Weasley\Contract\Mutator;

/**
* API Transformer
*
* @package Weasley
* @author Rougin Gutib <rougingutib@gmail.com>
*/
class RestMutator implements Mutator
{
const PAGINATOR = 'Illuminate\Pagination\LengthAwarePaginator';

/**
* @deprecated since ~0.7, use "mutate" instead.
* @codeCoverageIgnore
*
* Transforms the contents of the result.
*
* @param \Illuminate\Contracts\Support\Arrayable $data
* @return mixed
*/
public function transform($data)
{
return $this->mutate($data);
}

/**
* Mutates the contents of the result.
*
* @param \Illuminate\Contracts\Support\Arrayable $data
* @return mixed
*/
public function mutate($data)
{
$result = $data->toArray();

if (is_object($data) && is_a($data, self::PAGINATOR))
{
/** @var \Illuminate\Pagination\LengthAwarePaginator $data */
$result = $this->paginator($data);
}

return $result;
}

/**
* Converts the paginator into Paypal API standards.
*
* @param \Illuminate\Contracts\Support\Arrayable $data
* @return array<string, mixed>
*/
protected function paginator(Arrayable $data)
{
$object = $data->toArray();

$perPage = (int) $object['per_page'];

$total = (int) $object['total'];

$rounded = round($total / $perPage);

$result = array();

$result['total_items'] = $total;

$result['total_pages'] = $rounded ?: 1;

$result['items'] = $object['data'];

return $result;
}
}
7 changes: 4 additions & 3 deletions src/Routes/HttpRoute.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Rougin\Weasley\Transformer\JsonTransformer;
use Rougin\Weasley\Mutators\JsonMutator;

/**
* HTTP Route
Expand Down Expand Up @@ -68,9 +68,10 @@ public function json($data, $code = 200, $options = 0)
{
$response = $this->response->withStatus($code);

$transformer = new JsonTransformer($response, $options);
$transformer = new JsonMutator($response, $options);

return $transformer->transform($data);
/** @var \Psr\Http\Message\ResponseInterface */
return $transformer->mutate($data);
}

/**
Expand Down
20 changes: 17 additions & 3 deletions src/Routes/JsonRoute.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,14 @@ class JsonRoute extends HttpRoute
/**
* @var string|null
*/
protected $transformer = 'Rougin\Weasley\Transformer\ApiTransformer';
protected $mutator = 'Rougin\Weasley\Mutators\RestMutator';

/**
* @deprecated since ~0.7, use "$mutator" instead.
*
* @var string|null
*/
protected $transformer = null;

/**
* @var \Rougin\Weasley\Validators\AbstractValidator
Expand Down Expand Up @@ -109,9 +116,16 @@ public function index()

$items = $items ? $items : $this->eloquent->all();

$transformer = new $this->transformer;
/** @var \Rougin\Weasley\Contract\Mutator */
$mutator = new $this->mutator;

if ($this->transformer)
{
/** @var \Rougin\Weasley\Transformer\TransformerInterface */
$mutator = new $this->transformer;
}

return $this->json($transformer->transform($items));
return $this->json($mutator->mutate($items));
}

/**
Expand Down
53 changes: 4 additions & 49 deletions src/Transformer/ApiTransformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,61 +2,16 @@

namespace Rougin\Weasley\Transformer;

use Illuminate\Contracts\Support\Arrayable;
use Rougin\Weasley\Mutators\RestMutator;

/**
* @deprecated since ~0.7, use "Mutators/RestMutator" instead.
*
* API Transformer
*
* @package Weasley
* @author Rougin Gutib <rougingutib@gmail.com>
*/
class ApiTransformer implements TransformerInterface
class ApiTransformer extends RestMutator
{
const PAGINATOR = 'Illuminate\Pagination\LengthAwarePaginator';

/**
* Transforms the contents of the result.
*
* @param \Illuminate\Contracts\Support\Arrayable $data
* @return mixed
*/
public function transform($data)
{
$result = $data->toArray();

if (is_object($data) && is_a($data, self::PAGINATOR))
{
/** @var \Illuminate\Pagination\LengthAwarePaginator $data */
$result = $this->paginator($data);
}

return $result;
}

/**
* Converts the paginator into Paypal API standards.
*
* @param \Illuminate\Contracts\Support\Arrayable $data
* @return array<string, mixed>
*/
protected function paginator(Arrayable $data)
{
$object = $data->toArray();

$perPage = (int) $object['per_page'];

$total = (int) $object['total'];

$rounded = round($total / $perPage);

$result = array();

$result['total_items'] = $total;

$result['total_pages'] = $rounded ?: 1;

$result['items'] = $object['data'];

return $result;
}
}
Loading

0 comments on commit 1891601

Please sign in to comment.