Skip to content

Commit

Permalink
Merge pull request biig-io#30 from swagindustries/feature/add-collect…
Browse files Browse the repository at this point in the history
…ion-model

Add collection response
  • Loading branch information
Nek- authored Aug 18, 2020
2 parents e255690 + 8687a7d commit b9e80d0
Show file tree
Hide file tree
Showing 8 changed files with 123 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Support of more kind of FormError
- Removed the requirement to have CSRF protection enabled #25
- Behat test suite. Melodiia is officially battle tested!
- Add Collection model to render easily standard output with collections #12

### Changed
- New PHP minimum requirement is PHP 7.3
Expand Down
30 changes: 30 additions & 0 deletions features/custom_responses.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
Feature:
As a developer
I should be able to render custom response easily with Melodiia

Scenario: return array of object for a response
Given there are some todos
And I make a GET request on "/todos/contains/foo"
Then the last response contains:
"""
{
"meta": {
"totalPages": 1,
"totalResults": 1,
"currentPage": 1,
"maxPerPage": 1
},
"links": {
"prev": null,
"next": null,
"last": "http://localhost/todos/contains/foo",
"first": "http://localhost/todos/contains/foo"
},
"data": [
{
"id": 1,
"content": "foo"
}
]
}
"""
12 changes: 12 additions & 0 deletions src/Response/Model/Collection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace SwagIndustries\Melodiia\Response\Model;

/**
* Fix issue #12.
*/
class Collection extends \ArrayIterator
{
}
16 changes: 16 additions & 0 deletions src/Serialization/Json/OkContentNormalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace SwagIndustries\Melodiia\Serialization\Json;

use Pagerfanta\Pagerfanta;
use SwagIndustries\Melodiia\Response\Model\Collection;
use SwagIndustries\Melodiia\Response\OkContent;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
Expand Down Expand Up @@ -79,6 +80,21 @@ public function normalize($object, $format = null, array $context = [])
'first' => \preg_replace('/([?&])page=(\d+)/', '$1page=1', $uri),
];
}
if ($content instanceof Collection) {
$uri = $this->requestStack->getMasterRequest()->getUri();
$result['meta'] = [
'totalPages' => 1,
'totalResults' => count($content),
'currentPage' => 1,
'maxPerPage' => count($content),
];
$result['links'] = [
'prev' => null,
'next' => null,
'last' => $uri,
'first' => $uri,
];
}

$result['data'] = [];
foreach ($content as $item) {
Expand Down
30 changes: 30 additions & 0 deletions tests/Melodiia/Serialization/Json/OkContentNormalizerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\Prophecy\ObjectProphecy;
use SwagIndustries\Melodiia\Response\Model\Collection;
use SwagIndustries\Melodiia\Response\OkContent;
use SwagIndustries\Melodiia\Serialization\Json\OkContentNormalizer;
use Symfony\Component\HttpFoundation\Request;
Expand Down Expand Up @@ -131,4 +132,33 @@ public function testItSerializePager()
],
], $res);
}

public function testItSerializeCollection()
{
$collection = new Collection([['acme' => 'foo'], ['acme' => 'bar']]);
$this->mainNormalizer->normalize(['acme' => 'foo'], Argument::cetera())->willReturn(['acme' => 'foo'])->shouldBeCalled();
$this->mainNormalizer->normalize(['acme' => 'bar'], Argument::cetera())->willReturn(['acme' => 'bar'])->shouldBeCalled();
$this->request->getUri()->willReturn('http://foo.com/bar');

$res = $this->okContentNormalizer->normalize(new OkContent($collection));

$this->assertEquals([
'data' => [
['acme' => 'foo'],
['acme' => 'bar'],
],
'meta' => [
'totalPages' => 1,
'totalResults' => 2,
'currentPage' => 1,
'maxPerPage' => 2,
],
'links' => [
'prev' => null,
'next' => null,
'last' => 'http://foo.com/bar',
'first' => 'http://foo.com/bar',
],
], $res);
}
}
3 changes: 3 additions & 0 deletions tests/TestApplication/config/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,6 @@ services:

SwagIndustries\Melodiia\Tests\Behat\:
resource: '../../Behat/*'

TestApplication\Controller\TodoContainsAction:
tags: ['controller.service_arguments']
5 changes: 5 additions & 0 deletions tests/TestApplication/config/routing.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ get_todos:
defaults:
melodiia_model: TestApplication\Entity\Todo

get_todo_contains:
path: /todos/contains/{word}
methods: GET
controller: 'TestApplication\Controller\TodoContainsAction'

get_todo:
path: /todos/{id}
controller: 'melodiia.crud.controller.get'
Expand Down
26 changes: 26 additions & 0 deletions tests/TestApplication/src/Controller/TodoContainsAction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace TestApplication\Controller;

use Doctrine\ORM\EntityManagerInterface;
use SwagIndustries\Melodiia\Response\Model\Collection;
use SwagIndustries\Melodiia\Response\OkContent;
use Symfony\Component\String\UnicodeString;
use TestApplication\Entity\Todo;

class TodoContainsAction
{
/**
* This is just a test. To achieve that easily you should use filters and crud controllers.
*/
public function __invoke(EntityManagerInterface $manager, $word)
{
$todos = array_filter($manager->getRepository(Todo::class)->findAll(), function (Todo $todo) use ($word) {
$str = new UnicodeString($todo->getContent());

return $str->containsAny($word);
});

return new OkContent(new Collection($todos));
}
}

0 comments on commit b9e80d0

Please sign in to comment.