Skip to content
Snippets Groups Projects
Commit 6eb12a5a authored by Tobias Gross-Vogt's avatar Tobias Gross-Vogt
Browse files

localData mechanism

parent 1bbf49d7
No related branches found
No related tags found
No related merge requests found
Pipeline #99617 passed
<?php
declare(strict_types=1);
namespace Dbp\Relay\CoreBundle\Entity;
interface LocalDataAwareInterface
{
/**
* Returns the unique name (shortName of the ApiResource) of this entity.
*/
public static function getUniqueEntityName(): string;
/**
* Sets the value of a local data attribute.
*
* @param mixed|null $value
*/
public function setLocalDataValue(string $key, $value): void;
/**
* Returns the value of local data value attribute or null if the attribute is not found.
*
* @return ?mixed
*/
public function getLocalDataValue(string $key);
}
<?php
declare(strict_types=1);
namespace Dbp\Relay\CoreBundle\Entity;
use ApiPlatform\Core\Annotation\ApiProperty;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Serializer\Annotation\Ignore;
trait LocalDataAwareTrait
{
/**
* @ApiProperty(iri="https://schema.org/additionalProperty")
* @Groups({"LocalData:output"})
*
* @var array
*/
private $localData;
public function getLocalData(): array
{
return $this->localData;
}
/**
* Adds a local data entry.
*
* @param mixed|null $value
*/
public function setLocalDataValue(string $key, $value): void
{
if (!$this->localData) {
$this->localData = [];
}
$this->localData[$key] = $value;
}
/**
* @Ignore
* Returns the local data value for the given key or null if the key is not found.
*
* @return ?mixed
*/
public function getLocalDataValue(string $key)
{
return $this->localData ? ($this->localData[$key] ?? null) : null;
}
}
<?php
declare(strict_types=1);
namespace Dbp\Relay\CoreBundle\Event;
use Dbp\Relay\CoreBundle\Entity\LocalDataAwareInterface;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Contracts\EventDispatcher\Event;
class LocalDataAwarePostEvent extends Event
{
/** @var LocalDataAwareInterface */
private $entity;
/** @var array */
private $requestedAttributes;
protected function __construct(LocalDataAwareInterface $entity)
{
$this->entity = $entity;
}
public function setRequestedAttributes(array $requestedAttributes)
{
$this->requestedAttributes = $requestedAttributes;
}
public function getRemainingRequestedAttributes(): array
{
return $this->requestedAttributes;
}
public function getEntity(): LocalDataAwareInterface
{
return $this->entity;
}
public function setLocalDataAttribute(string $key, $value)
{
$arrayKey = array_search($key, $this->requestedAttributes, true);
if ($arrayKey === false) {
throw new HttpException(500, sprintf("local data attribute '%s' not requested for entity '%s'", $key, $this->entity->getUniqueEntityName()));
}
// once set, remove the attribute from the list of requested attributes
array_splice($this->requestedAttributes, $arrayKey, 1);
$this->entity->setLocalDataValue($key, $value);
}
public function isLocalDataAttributeRequested(string $key): bool
{
return in_array($key, $this->requestedAttributes, true);
}
}
......@@ -56,4 +56,8 @@ services:
Dbp\Relay\CoreBundle\Auth\ProxyAuthenticator:
autowire: true
autoconfigure: true
\ No newline at end of file
autoconfigure: true
Dbp\Relay\CoreBundle\Service\LocalDataAwareEventDispatcher:
autowire: true
autoconfigure: true
<?php
declare(strict_types=1);
namespace Dbp\Relay\CoreBundle\Service;
use Dbp\Relay\CoreBundle\Event\LocalDataAwarePostEvent;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpKernel\Exception\HttpException;
class LocalDataAwareEventDispatcher
{
private $requestedAttributes;
/** @var string */
private $unqiueEntityName;
/** @var EventDispatcherInterface */
private $eventDispatcher;
/** @var string */
private $eventName;
public function __construct(string $unqiueEntityName, EventDispatcherInterface $eventDispatcher, string $eventName)
{
$this->unqiueEntityName = $unqiueEntityName;
$this->eventDispatcher = $eventDispatcher;
$this->eventName = $eventName;
}
public function initRequestedLocalDataAttributes(array $options)
{
$this->requestedAttributes = [];
if ($include = $options['include'] ?? null) {
$requestedLocalDataAttributes = explode(',', $include);
foreach ($requestedLocalDataAttributes as $requestedLocalDataAttribute) {
$requestedLocalDataAttribute = trim($requestedLocalDataAttribute);
if (!empty($requestedLocalDataAttribute)) {
$requestedUniqueEntityName = null;
$requestedAttributeName = null;
if (!self::parseLocalDataAttribute($requestedLocalDataAttribute, $requestedUniqueEntityName, $requestedAttributeName)) {
throw new HttpException(400, sprintf("value of 'include' parameter has invalid format: '%s' (Example: 'ResourceName.attr,ResourceName.attr2')", $requestedLocalDataAttribute));
}
if ($this->unqiueEntityName === $requestedUniqueEntityName) {
$this->requestedAttributes[] = $requestedAttributeName;
}
}
}
$this->requestedAttributes = array_unique($this->requestedAttributes);
}
}
public function dispatch(LocalDataAwarePostEvent $event)
{
$event->setRequestedAttributes($this->requestedAttributes);
$this->eventDispatcher->dispatch($event, $this->eventName);
$remainingLocalDataAttributes = $event->getRemainingRequestedAttributes();
if (!empty($remainingLocalDataAttributes)) {
throw new HttpException(500, sprintf("the following local data attributes were not provided for resource '%s': %s", $this->unqiueEntityName, implode(', ', $remainingLocalDataAttributes)));
}
}
private static function parseLocalDataAttribute(string $localDataAttribute, ?string &$entityUniqueName, ?string &$attributeName): bool
{
$parts = explode('.', $localDataAttribute);
if (count($parts) !== 2 || empty($parts[0]) || empty($parts[1])) {
return false;
}
$entityUniqueName = $parts[0];
$attributeName = $parts[1];
return true;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment