Skip to content

Commit

Permalink
add html formatter
Browse files Browse the repository at this point in the history
Signed-off-by: Klein Florian <[email protected]>
  • Loading branch information
docteurklein committed Mar 20, 2019
1 parent dd4b436 commit 19f46de
Show file tree
Hide file tree
Showing 11 changed files with 161 additions and 118 deletions.
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ A php library to describe resources and serve different hypermedia formats based

## how ?

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

```php
use Hippiemedia\Resource;
Expand All @@ -16,7 +16,6 @@ use Hippiemedia\Operation;
use Hippiemedia\Field;
use Hippiemedia\Format;
use Hippiemedia\Negotiate;
use Hippiemedia\UrlGenerator;

final class Hypermedia
{
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"require": {
"lstrojny/functional-php": "^1.0",
"willdurand/negotiation": "^2.0",
"symfony/routing": "^3.0 | ^4.0"
"docteurklein/json-chunks": "^1.0"
},
"autoload": {
"psr-4": {
Expand Down
115 changes: 37 additions & 78 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 19 additions & 0 deletions example/whatever.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php declare(strict_types=1);

// php -S 0:8080 -t example
// xdg-open http://0:8080/whatever.php

use Hippiemedia\Infra\Negotiate\WilldurandNegotiator;
use Hippiemedia\Format;
use Hippiemedia\Resource;

require(__DIR__.'/../vendor/autoload.php');

$contentType = array_change_key_case(getallheaders())['content-type'] ?? 'text/html';

$negotiate = new WilldurandNegotiator(new \Negotiation\Negotiator, 'text/html', new Format\Html, new Format\Siren, new Format\Hal);
$format = $negotiate($contentType);

header('Content-Type: '.$format->accepts());

echo implode("\n", iterator_to_array($format(Resource::whatever()), false));
20 changes: 20 additions & 0 deletions spec/Hippiemedia/Format/HtmlSpec.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace spec\Hippiemedia\Format;

use Hippiemedia\Format\Siren;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Hippiemedia\Resource;

class HtmlSpec extends ObjectBehavior
{
function it_formats_html()
{
$iterable = $this(Resource::whatever());

$html = implode("\n", iterator_to_array($iterable->getWrappedObject(), false));
$dom = new \DOMDocument('1.0', 'UTF-8');
$dom->loadHTML($html);
}
}
12 changes: 9 additions & 3 deletions src/Format/Hal.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Hippiemedia\Format;
use Hippiemedia\Resource;
use Hippiemedia\Link;
use DocteurKlein\JsonChunks\Encode;

final class Hal implements Format
{
Expand All @@ -15,6 +16,11 @@ public function accepts(): string
}

public function __invoke(Resource $resource): iterable
{
return Encode::from($this->normalize($resource));
}

private function normalize(Resource $resource): iterable
{
$linksByRel = array_merge(
f\group($resource->links, f\invoker('rel')),
Expand All @@ -39,7 +45,7 @@ public function __invoke(Resource $resource): iterable
}),
'_embedded' => array_merge(f\map($operationsByRel, function($operations) {
return f\map(array_values($operations), function($operation) {
return $this(new Resource($operation->url, [
return $this->normalize(new Resource($operation->url, [
'_templates' => [
'default' => [
'title' => $operation->title,
Expand All @@ -62,8 +68,8 @@ public function __invoke(Resource $resource): iterable
], array_merge([new Link(['self'], $operation->url, $operation->templated)], $operation->links), []));
});
}), f\map($resource->embedded, function($resources) {
return f\map($resources, $this);
}, $this))
return array_map([$this, 'normalize'], $resources);
}))
]);
}
}
65 changes: 65 additions & 0 deletions src/Format/Html.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php declare(strict_types=1);

namespace Hippiemedia\Format;

use Functional as f;
use Hippiemedia\Format;
use Hippiemedia\Resource;
use Hippiemedia\Operation;

final class Html implements Format
{
public function accepts(): string
{
return 'text/html';
}

public function __invoke(Resource $resource): iterable
{
$state = print_r($resource->state, true);
yield '<div>';
yield "<pre>{$state}</pre>";
yield from $this->links($resource);
yield from $this->operations($resource);
yield '</div>';
}

private function links(Resource $resource): iterable
{
yield '<ul>';
foreach ($resource->links as $link) {
yield <<<HTML
<li><a href="{$link->href}">{$link->title}</a></li>
HTML;
}
yield '</ul>';
}

private function operations(Resource $resource): iterable
{
foreach ($resource->operations as $operation) {
yield <<<HTML
<form action="{$operation->url}" method="{$operation->method}">
<fieldset>
<legend>{$operation->title}</legend>
HTML
;
yield from $this->fields($operation);

yield <<<HTML
</fieldset>
<input type="submit" />
</form>
HTML;
}
}

private function fields(Operation $operation): iterable
{
foreach ($operation->fields as $field) {
yield <<<HTML
<input name="{$field->name}" value="{$field->value}" />
HTML;
}
}
}
8 changes: 7 additions & 1 deletion src/Format/Siren.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Hippiemedia\Format;
use Hippiemedia\Resource;
use Hippiemedia\Link;
use DocteurKlein\JsonChunks\Encode;

final class Siren implements Format
{
Expand All @@ -15,6 +16,11 @@ public function accepts(): string
}

public function __invoke(Resource $resource): iterable
{
return Encode::from($this->normalize($resource));
}

private function normalize(Resource $resource): iterable
{
return [
'class' => [],
Expand All @@ -31,7 +37,7 @@ public function __invoke(Resource $resource): iterable
'entities' => array_reduce(array_keys($resource->embedded), function($acc, $rel) use($resource) {
$resources = $resource->embedded[$rel];
return array_merge($acc, f\map($resources, function($resource) use($rel) {
return array_merge($this($resource), ['rel' => [$rel]]);
return array_merge($this->normalize($resource), ['rel' => [$rel]]);
}));
}, []),
'actions' => f\map(array_values($resource->operations), function($operation) {
Expand Down
31 changes: 0 additions & 31 deletions src/Infra/UrlGenerator/SymfonyRouter.php

This file was deleted.

2 changes: 1 addition & 1 deletion src/Operation.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public static function whatever(array $data = [])
{
return new self(
$data['rel'] ?? 'rel',
$data['method'] ?? 'method',
$data['method'] ?? 'POST',
$data['url'] ?? 'url',
$data['templated'] ?? false,
$data['title'] ?? 'title',
Expand Down
2 changes: 1 addition & 1 deletion src/Resource.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public static function whatever(array $data = [])
$data['state'] ?? ['state'],
$data['links'] ?? [Link::whatever()],
$data['operations'] ?? [Operation::whatever()],
$data['embedded'] ?? ['rel' => [self::whatever(['embedded' => []])]]
$data['embedded'] ?? ['rel' => [self::whatever(['state' => ['SUB'], 'embedded' => []])]]
);
}

Expand Down

0 comments on commit 19f46de

Please sign in to comment.