View source
<?php
namespace Drupal\jsonapi\Normalizer;
use Drupal\jsonapi\Context\FieldResolver;
use Drupal\jsonapi\Query\EntityCondition;
use Drupal\jsonapi\Query\Filter;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
class FilterNormalizer implements DenormalizerInterface {
const ROOT_ID = '@root';
const CONDITION_KEY = 'condition';
const GROUP_KEY = 'group';
const MEMBER_KEY = 'memberOf';
protected $supportedInterfaceOrClass = Filter::class;
protected $formats = [
'api_json',
];
protected $conditionDenormalizer;
protected $groupDenormalizer;
protected $fieldResolver;
public function __construct(FieldResolver $field_resolver, DenormalizerInterface $condition_denormalizer, DenormalizerInterface $group_denormalizer) {
$this->fieldResolver = $field_resolver;
$this->conditionDenormalizer = $condition_denormalizer;
$this->groupDenormalizer = $group_denormalizer;
}
public function supportsDenormalization($data, $type, $format = NULL) {
return $type === $this->supportedInterfaceOrClass;
}
public function denormalize($data, $class, $format = NULL, array $context = []) {
$expanded = $this
->expand($data, $context);
$denormalized = $this
->denormalizeItems($expanded);
return new Filter($denormalized);
}
protected function expand(array $original, array $context) {
$expanded = [];
foreach ($original as $key => $item) {
if (!is_array($item)) {
$item = [
EntityConditionNormalizer::VALUE_KEY => $item,
];
}
if ($key == static::ROOT_ID) {
$msg = sprintf("'%s' is a reserved filter id.", static::ROOT_ID);
throw new \UnexpectedValueException($msg);
}
if (isset($item[static::CONDITION_KEY][static::MEMBER_KEY])) {
$item[static::MEMBER_KEY] = $item[static::CONDITION_KEY][static::MEMBER_KEY];
unset($item[static::CONDITION_KEY][static::MEMBER_KEY]);
}
elseif (isset($item[static::GROUP_KEY][static::MEMBER_KEY])) {
$item[static::MEMBER_KEY] = $item[static::GROUP_KEY][static::MEMBER_KEY];
unset($item[static::GROUP_KEY][static::MEMBER_KEY]);
}
else {
$item[static::MEMBER_KEY] = static::ROOT_ID;
}
$item['id'] = $key;
$expanded[$key] = $this
->expandItem($key, $item, $context);
}
return $expanded;
}
protected function expandItem($filter_index, array $filter_item, array $context) {
if (isset($filter_item[EntityConditionNormalizer::VALUE_KEY])) {
if (!isset($filter_item[EntityConditionNormalizer::PATH_KEY])) {
$filter_item[EntityConditionNormalizer::PATH_KEY] = $filter_index;
}
$filter_item = [
static::CONDITION_KEY => $filter_item,
static::MEMBER_KEY => $filter_item[static::MEMBER_KEY],
];
}
if (!isset($filter_item[static::CONDITION_KEY][EntityConditionNormalizer::OPERATOR_KEY])) {
$filter_item[static::CONDITION_KEY][EntityConditionNormalizer::OPERATOR_KEY] = '=';
}
if (isset($filter_item[static::CONDITION_KEY][EntityConditionNormalizer::PATH_KEY])) {
$filter_item[static::CONDITION_KEY][EntityConditionNormalizer::PATH_KEY] = $this->fieldResolver
->resolveInternalEntityQueryPath($context['entity_type_id'], $context['bundle'], $filter_item[static::CONDITION_KEY][EntityConditionNormalizer::PATH_KEY]);
}
return $filter_item;
}
protected function denormalizeItems(array $items) {
$root = [
'id' => static::ROOT_ID,
static::GROUP_KEY => [
'conjunction' => 'AND',
],
];
return $this
->buildTree($root, $items);
}
protected function buildTree(array $root, array $items) {
$id = $root['id'];
$members = [];
foreach ($items as $item) {
if ($item[static::MEMBER_KEY] == $id) {
if (isset($item[static::GROUP_KEY])) {
array_push($members, $this
->buildTree($item, $items));
}
elseif (isset($item[static::CONDITION_KEY])) {
$condition = $this->conditionDenormalizer
->denormalize($item[static::CONDITION_KEY], EntityCondition::class);
array_push($members, $condition);
}
}
}
$root[static::GROUP_KEY]['members'] = $members;
return $this->groupDenormalizer
->denormalize($root[static::GROUP_KEY], EntityConditionGroup::class);
}
}