Skip to content

Commit 19f46de

Browse files
committed
add html formatter
Signed-off-by: Klein Florian <florian.klein@free.fr>
1 parent dd4b436 commit 19f46de

11 files changed

Lines changed: 161 additions & 118 deletions

File tree

README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ A php library to describe resources and serve different hypermedia formats based
77

88
## how ?
99

10-
- Declare your different resources:
10+
Example integration with a symfony controller
1111

1212
```php
1313
use Hippiemedia\Resource;
@@ -16,7 +16,6 @@ use Hippiemedia\Operation;
1616
use Hippiemedia\Field;
1717
use Hippiemedia\Format;
1818
use Hippiemedia\Negotiate;
19-
use Hippiemedia\UrlGenerator;
2019

2120
final class Hypermedia
2221
{

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"require": {
1313
"lstrojny/functional-php": "^1.0",
1414
"willdurand/negotiation": "^2.0",
15-
"symfony/routing": "^3.0 | ^4.0"
15+
"docteurklein/json-chunks": "^1.0"
1616
},
1717
"autoload": {
1818
"psr-4": {

composer.lock

Lines changed: 37 additions & 78 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

example/whatever.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php declare(strict_types=1);
2+
3+
// php -S 0:8080 -t example
4+
// xdg-open http://0:8080/whatever.php
5+
6+
use Hippiemedia\Infra\Negotiate\WilldurandNegotiator;
7+
use Hippiemedia\Format;
8+
use Hippiemedia\Resource;
9+
10+
require(__DIR__.'/../vendor/autoload.php');
11+
12+
$contentType = array_change_key_case(getallheaders())['content-type'] ?? 'text/html';
13+
14+
$negotiate = new WilldurandNegotiator(new \Negotiation\Negotiator, 'text/html', new Format\Html, new Format\Siren, new Format\Hal);
15+
$format = $negotiate($contentType);
16+
17+
header('Content-Type: '.$format->accepts());
18+
19+
echo implode("\n", iterator_to_array($format(Resource::whatever()), false));
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
namespace spec\Hippiemedia\Format;
4+
5+
use Hippiemedia\Format\Siren;
6+
use PhpSpec\ObjectBehavior;
7+
use Prophecy\Argument;
8+
use Hippiemedia\Resource;
9+
10+
class HtmlSpec extends ObjectBehavior
11+
{
12+
function it_formats_html()
13+
{
14+
$iterable = $this(Resource::whatever());
15+
16+
$html = implode("\n", iterator_to_array($iterable->getWrappedObject(), false));
17+
$dom = new \DOMDocument('1.0', 'UTF-8');
18+
$dom->loadHTML($html);
19+
}
20+
}

src/Format/Hal.php

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use Hippiemedia\Format;
77
use Hippiemedia\Resource;
88
use Hippiemedia\Link;
9+
use DocteurKlein\JsonChunks\Encode;
910

1011
final class Hal implements Format
1112
{
@@ -15,6 +16,11 @@ public function accepts(): string
1516
}
1617

1718
public function __invoke(Resource $resource): iterable
19+
{
20+
return Encode::from($this->normalize($resource));
21+
}
22+
23+
private function normalize(Resource $resource): iterable
1824
{
1925
$linksByRel = array_merge(
2026
f\group($resource->links, f\invoker('rel')),
@@ -39,7 +45,7 @@ public function __invoke(Resource $resource): iterable
3945
}),
4046
'_embedded' => array_merge(f\map($operationsByRel, function($operations) {
4147
return f\map(array_values($operations), function($operation) {
42-
return $this(new Resource($operation->url, [
48+
return $this->normalize(new Resource($operation->url, [
4349
'_templates' => [
4450
'default' => [
4551
'title' => $operation->title,
@@ -62,8 +68,8 @@ public function __invoke(Resource $resource): iterable
6268
], array_merge([new Link(['self'], $operation->url, $operation->templated)], $operation->links), []));
6369
});
6470
}), f\map($resource->embedded, function($resources) {
65-
return f\map($resources, $this);
66-
}, $this))
71+
return array_map([$this, 'normalize'], $resources);
72+
}))
6773
]);
6874
}
6975
}

src/Format/Html.php

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace Hippiemedia\Format;
4+
5+
use Functional as f;
6+
use Hippiemedia\Format;
7+
use Hippiemedia\Resource;
8+
use Hippiemedia\Operation;
9+
10+
final class Html implements Format
11+
{
12+
public function accepts(): string
13+
{
14+
return 'text/html';
15+
}
16+
17+
public function __invoke(Resource $resource): iterable
18+
{
19+
$state = print_r($resource->state, true);
20+
yield '<div>';
21+
yield "<pre>{$state}</pre>";
22+
yield from $this->links($resource);
23+
yield from $this->operations($resource);
24+
yield '</div>';
25+
}
26+
27+
private function links(Resource $resource): iterable
28+
{
29+
yield '<ul>';
30+
foreach ($resource->links as $link) {
31+
yield <<<HTML
32+
<li><a href="{$link->href}">{$link->title}</a></li>
33+
HTML;
34+
}
35+
yield '</ul>';
36+
}
37+
38+
private function operations(Resource $resource): iterable
39+
{
40+
foreach ($resource->operations as $operation) {
41+
yield <<<HTML
42+
<form action="{$operation->url}" method="{$operation->method}">
43+
<fieldset>
44+
<legend>{$operation->title}</legend>
45+
HTML
46+
;
47+
yield from $this->fields($operation);
48+
49+
yield <<<HTML
50+
</fieldset>
51+
<input type="submit" />
52+
</form>
53+
HTML;
54+
}
55+
}
56+
57+
private function fields(Operation $operation): iterable
58+
{
59+
foreach ($operation->fields as $field) {
60+
yield <<<HTML
61+
<input name="{$field->name}" value="{$field->value}" />
62+
HTML;
63+
}
64+
}
65+
}

src/Format/Siren.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use Hippiemedia\Format;
77
use Hippiemedia\Resource;
88
use Hippiemedia\Link;
9+
use DocteurKlein\JsonChunks\Encode;
910

1011
final class Siren implements Format
1112
{
@@ -15,6 +16,11 @@ public function accepts(): string
1516
}
1617

1718
public function __invoke(Resource $resource): iterable
19+
{
20+
return Encode::from($this->normalize($resource));
21+
}
22+
23+
private function normalize(Resource $resource): iterable
1824
{
1925
return [
2026
'class' => [],
@@ -31,7 +37,7 @@ public function __invoke(Resource $resource): iterable
3137
'entities' => array_reduce(array_keys($resource->embedded), function($acc, $rel) use($resource) {
3238
$resources = $resource->embedded[$rel];
3339
return array_merge($acc, f\map($resources, function($resource) use($rel) {
34-
return array_merge($this($resource), ['rel' => [$rel]]);
40+
return array_merge($this->normalize($resource), ['rel' => [$rel]]);
3541
}));
3642
}, []),
3743
'actions' => f\map(array_values($resource->operations), function($operation) {

src/Infra/UrlGenerator/SymfonyRouter.php

Lines changed: 0 additions & 31 deletions
This file was deleted.

src/Operation.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public static function whatever(array $data = [])
3333
{
3434
return new self(
3535
$data['rel'] ?? 'rel',
36-
$data['method'] ?? 'method',
36+
$data['method'] ?? 'POST',
3737
$data['url'] ?? 'url',
3838
$data['templated'] ?? false,
3939
$data['title'] ?? 'title',

0 commit comments

Comments
 (0)