Skip to content

Instantly share code, notes, and snippets.

@jeremykendall
Created October 25, 2016 15:53
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jeremykendall/af8c81e0a410feef84213520432a09aa to your computer and use it in GitHub Desktop.
Save jeremykendall/af8c81e0a410feef84213520432a09aa to your computer and use it in GitHub Desktop.
Quick and dirty Fractal HAL serializer
<?php
/**
* The MIT License (MIT)
* Copyright (c) 2016 Alegion (http://www.alegion.com)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
namespace Alegion\Fractal\Serializer;
use League\Fractal\Pagination\CursorInterface;
use League\Fractal\Pagination\PaginatorInterface;
use League\Fractal\Resource\ResourceInterface;
use League\Fractal\Serializer\ArraySerializer;
use Nocarrier\Hal;
/**
* HalSerializer for use with Fractal.
*/
class HalSerializer extends ArraySerializer
{
/**
* @var Hal
*/
private $hal;
/**
* HalSerializer constructor.
*
* @param Hal $hal Used for "top level" resources in collections only
*/
public function __construct(Hal $hal)
{
$this->hal = $hal;
}
/**
* Serialize a collection.
*
* @param string $resourceKey
* @param array $data
*
* @return array
*/
public function collection($resourceKey, array $data)
{
\Functional\each($data, function (array $resource) use ($resourceKey) {
$embedded = new Hal(null, $this->item(null, $resource));
$this->hal->addResource($resourceKey, $embedded);
});
return $this->getHalAsArray($this->hal);
}
/**
* Serialize an item.
*
* @param string $resourceKey Not used in this implementation
* @param array $data
*
* @return array
*/
public function item($resourceKey, array $data): array
{
$hal = new Hal();
if (array_key_exists('links', $data)) {
\Functional\each($data['links'], function ($link) use ($hal, $resourceKey) {
$rel = $resourceKey ?? $link['rel'];
$attributes = $link['attributes'] ?? [];
$hal->addLink($link['rel'], $link['uri'], $attributes);
});
unset($data['links']);
}
$hal->setData($data);
return $this->getHalAsArray($hal);
}
/**
* Serialize null resource.
*
* @return array
*/
public function null()
{
// TODO: Implement null() method.
return [];
}
/**
* Serialize the included data.
*
* @param ResourceInterface $resource
* @param array $data
*
* @return array
*
* @throws \RuntimeException
*/
public function includedData(ResourceInterface $resource, array $data)
{
throw new \RuntimeException('HalSerializer::includedData NOT IMPLEMENTED');
}
/**
* Serialize the meta.
*
* @param array $meta
*
* @return array
*/
public function meta(array $meta)
{
$this->hal->setData(array_merge($this->hal->getData(), $meta));
return $this->getHalAsArray($this->hal);
}
/**
* Serialize the paginator.
*
* @param PaginatorInterface $paginator
*
* @return array
*/
public function paginator(PaginatorInterface $paginator)
{
$currentPage = (int) $paginator->getCurrentPage();
$lastPage = (int) $paginator->getLastPage();
$data = [
'total' => (int) $paginator->getTotal(),
'count' => (int) $paginator->getCount(),
'per_page' => (int) $paginator->getPerPage(),
'current_page' => $currentPage,
'total_pages' => $lastPage,
];
$links = [];
$links['self'] = $paginator->getUrl($currentPage);
if ($currentPage > 1) {
$links['first'] = $paginator->getUrl(1);
$links['previous'] = $paginator->getUrl($currentPage - 1);
}
if ($currentPage < $lastPage) {
$links['next'] = $paginator->getUrl($currentPage + 1);
$links['last'] = $paginator->getUrl($lastPage);
}
foreach ($links as $rel => $uri) {
$this->hal->addLink($rel, $uri);
}
$this->hal->setData(array_merge($this->hal->getData(), $data));
// Return empty array so Scope doesn't set pagination data and links
// in a pagination key
return [];
}
/**
* Serialize the cursor.
*
* @param CursorInterface $cursor
*
* @return array
*/
public function cursor(CursorInterface $cursor)
{
// TODO: Implement cursor() method.
return [];
}
/**
* Returns an array representation of the Hal entity.
*
* @param Hal $hal
*
* @return array
*/
private function getHalAsArray(Hal $hal)
{
$pretty = false;
$encode = false;
return $hal->asJson($pretty, $encode);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment