Skip to content

Commit

Permalink
Clean up field generators
Browse files Browse the repository at this point in the history
  • Loading branch information
barw4 committed Oct 24, 2024
1 parent c13ec95 commit 32ca57e
Show file tree
Hide file tree
Showing 3 changed files with 168 additions and 155 deletions.
142 changes: 142 additions & 0 deletions src/lib/Output/Generator/AbstractFieldTypeHashGenerator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
<?php

/**
* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/

namespace Ibexa\Rest\Output\Generator;

use Ibexa\Rest\Output\Generator\Data\ArrayList;
use Ibexa\Rest\Output\Generator\Json\ArrayObject;
use Ibexa\Rest\Output\Generator\Json\JsonObject;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerAwareTrait;
use Psr\Log\LoggerInterface;
use Psr\Log\NullLogger;
use Symfony\Component\Serializer\Exception\ExceptionInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;

abstract class AbstractFieldTypeHashGenerator implements LoggerAwareInterface
{
use LoggerAwareTrait;

private NormalizerInterface $normalizer;

private bool $strictMode;

public function __construct(
NormalizerInterface $normalizer,
?LoggerInterface $logger = null,
bool $strictMode = false
) {
$this->normalizer = $normalizer;
$this->logger = $logger ?? new NullLogger();
$this->strictMode = $strictMode;
}

/**
* Generates the field type value $hashValue as a child of the given Object
* using $hashElementName as the property name.
*/
public function generateHashValue(
JsonObject|ArrayObject|ArrayList $parent,
string $hashElementName,
mixed $hashValue
): void {
$parent->$hashElementName = $this->generateValue($parent, $hashValue);
}

/**
* Generates and returns a JSON structure (array or object) depending on $value type
* with $parent.
*
* If $type only contains numeric keys, the resulting structure will be an
* JSON array, otherwise a JSON object
*
* @param array<mixed> $value
*/
protected function generateArrayValue(
JsonObject|ArrayObject|ArrayList $parent,
array $value,
): JsonObject|ArrayObject|ArrayList {
if ($this->isNumericArray($value)) {
return $this->generateListArray($parent, $value);
} else {
return $this->generateHashArray($parent, $value);
}
}

/**
* Generates and returns a value based on $hashValue type, with $parent (
* if the type of $hashValue supports it).
*/
abstract protected function generateValue(JsonObject|ArrayObject|ArrayList $parent, mixed $value): mixed;

/**
* Checks if the given $value is a purely numeric array.
*
* @param array<mixed> $value
*/
protected function isNumericArray(array $value): bool
{
foreach (array_keys($value) as $key) {
if (is_string($key)) {
return false;
}
}

return true;
}

protected function generateObjectValue(JsonObject|ArrayObject|ArrayList $parent, object $value): mixed
{
try {
$value = $this->normalizer->normalize($value, 'json', ['parent' => $parent]);
} catch (ExceptionInterface $e) {
if ($this->strictMode) {
throw $e;
}
$message = sprintf(
'Unable to normalize value for type "%s". %s. '
. 'Ensure that a normalizer is registered with tag: "%s".',
get_class($value),
$e->getMessage(),
'ibexa.rest.serializer.normalizer',
);

assert($this->logger instanceof LoggerInterface);
$this->logger->error($message, [
'exception' => $e,
]);

$value = null;
}

if (is_array($value)) {
return $this->generateArrayValue($parent, $value);
}

return $value;
}

/**
* Generates a JSON array from the given $hashArray with $parent.
*
* @param array<int> $listArray
*/
abstract protected function generateListArray(
JsonObject|ArrayObject|ArrayList $parent,
array $listArray,
): JsonObject|ArrayObject|ArrayList;

/**
* Generates a JSON object from the given $hashArray with $parent.
*
* @param array<mixed> $hashArray
*/
abstract protected function generateHashArray(
JsonObject|ArrayObject|ArrayList $parent,
array $hashArray,
): JsonObject|ArrayObject|ArrayList;
}
152 changes: 13 additions & 139 deletions src/lib/Output/Generator/Json/FieldTypeHashGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,57 +4,16 @@
* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);

namespace Ibexa\Rest\Output\Generator\Json;

use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerAwareTrait;
use Psr\Log\LoggerInterface;
use Psr\Log\NullLogger;
use Symfony\Component\Serializer\Exception\ExceptionInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use Ibexa\Rest\Output\Generator\AbstractFieldTypeHashGenerator;
use Ibexa\Rest\Output\Generator\Data\ArrayList;

class FieldTypeHashGenerator implements LoggerAwareInterface
class FieldTypeHashGenerator extends AbstractFieldTypeHashGenerator
{
use LoggerAwareTrait;

private NormalizerInterface $normalizer;

private bool $strictMode;

public function __construct(
NormalizerInterface $normalizer,
?LoggerInterface $logger = null,
bool $strictMode = false
) {
$this->normalizer = $normalizer;
$this->logger = $logger ?? new NullLogger();
$this->strictMode = $strictMode;
}

/**
* Generates the field type value $hashValue as a child of the given Object
* using $hashElementName as the property name.
*
* @param \Ibexa\Rest\Output\Generator\Json\ArrayObject|\Ibexa\Rest\Output\Generator\Json\JsonObject|\Ibexa\Rest\Output\Generator\Data\ArrayList $parent
* @param string $hashElementName
* @param mixed $hashValue
*/
public function generateHashValue($parent, $hashElementName, $hashValue)
{
$parent->$hashElementName = $this->generateValue($parent, $hashValue);
}

/**
* Generates and returns a value based on $hashValue type, with $parent (
* if the type of $hashValue supports it).
*
* @param \Ibexa\Rest\Output\Generator\Json\ArrayObject|\Ibexa\Rest\Output\Generator\Json\JsonObject $parent
* @param mixed $value
*
* @return mixed
*/
protected function generateValue($parent, $value)
protected function generateValue(JsonObject|ArrayObject|ArrayList $parent, mixed $value): mixed
{
if ($value === null || is_scalar($value)) {
// Will be handled accordingly on serialization
Expand All @@ -72,37 +31,10 @@ protected function generateValue($parent, $value)
throw new \Exception('Invalid type in Field value hash: ' . get_debug_type($value));
}

/**
* Generates and returns a JSON structure (array or object) depending on $value type
* with $parent.
*
* If $type only contains numeric keys, the resulting structure will be an
* JSON array, otherwise a JSON object
*
* @param \Ibexa\Rest\Output\Generator\Json\ArrayObject|\Ibexa\Rest\Output\Generator\Json\JsonObject $parent
* @param array<mixed> $value
*
* @return \Ibexa\Rest\Output\Generator\Json\ArrayObject|\Ibexa\Rest\Output\Generator\Json\JsonObject
*/
protected function generateArrayValue($parent, array $value)
{
if ($this->isNumericArray($value)) {
return $this->generateListArray($parent, $value);
} else {
return $this->generateHashArray($parent, $value);
}
}

/**
* Generates a JSON array from the given $hashArray with $parent.
*
* @param \Ibexa\Rest\Output\Generator\Json\ArrayObject|\Ibexa\Rest\Output\Generator\Json\JsonObject|\Ibexa\Rest\Output\Generator\Data\ArrayList $parent
* @param array<int> $listArray
*
* @return \Ibexa\Rest\Output\Generator\Json\ArrayObject|JsonObject
*/
protected function generateListArray($parent, array $listArray)
{
protected function generateListArray(
JsonObject|ArrayObject|ArrayList $parent,
array $listArray,
): JsonObject|ArrayObject|ArrayList {
$arrayObject = new ArrayObject($parent);
foreach ($listArray as $listItem) {
$arrayObject->append($this->generateValue($arrayObject, $listItem));
Expand All @@ -111,73 +43,15 @@ protected function generateListArray($parent, array $listArray)
return $arrayObject;
}

/**
* Generates a JSON object from the given $hashArray with $parent.
*
* @param \Ibexa\Rest\Output\Generator\Json\ArrayObject|\Ibexa\Rest\Output\Generator\Json\JsonObject $parent
* @param array<mixed> $hashArray
*
* @return \Ibexa\Rest\Output\Generator\Json\JsonObject
*/
protected function generateHashArray($parent, array $hashArray)
{
protected function generateHashArray(
JsonObject|ArrayObject|ArrayList $parent,
array $hashArray,
): JsonObject|ArrayObject|ArrayList {
$object = new JsonObject($parent);
foreach ($hashArray as $hashKey => $hashItem) {
$object->$hashKey = $this->generateValue($object, $hashItem);
}

return $object;
}

/**
* Checks if the given $value is a purely numeric array.
*
* @param array $value
*
* @return bool
*/
protected function isNumericArray(array $value)
{
foreach (array_keys($value) as $key) {
if (is_string($key)) {
return false;
}
}

return true;
}

/**
* @param \Ibexa\Rest\Output\Generator\Json\ArrayObject|\Ibexa\Rest\Output\Generator\Json\JsonObject $parent
*
* @return mixed
*/
protected function generateObjectValue($parent, object $value)
{
try {
$value = $this->normalizer->normalize($value, 'json', ['parent' => $parent]);
} catch (ExceptionInterface $e) {
if ($this->strictMode) {
throw $e;
}
$message = sprintf(
'Unable to normalize value for type "%s". %s. '
. 'Ensure that a normalizer is registered with tag: "%s".',
get_class($value),
$e->getMessage(),
'ibexa.rest.serializer.normalizer',
);
$this->logger->error($message, [
'exception' => $e,
]);

$value = null;
}

if (is_array($value)) {
return $this->generateArrayValue($parent, $value);
}

return $value;
}
}
29 changes: 13 additions & 16 deletions src/lib/Output/Generator/Xml/FieldTypeHashGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@

namespace Ibexa\Rest\Output\Generator\Xml;

use Ibexa\Rest\Output\Generator\Json\FieldTypeHashGenerator as JsonFieldTypeHashGenerator;
use Ibexa\Rest\Output\Generator\AbstractFieldTypeHashGenerator;
use Ibexa\Rest\Output\Generator\Data\ArrayList;
use Ibexa\Rest\Output\Generator\Json\ArrayObject;
use Ibexa\Rest\Output\Generator\Json\JsonObject;

final class FieldTypeHashGenerator extends JsonFieldTypeHashGenerator
final class FieldTypeHashGenerator extends AbstractFieldTypeHashGenerator
{
protected function generateValue($parent, $value): mixed
protected function generateValue(JsonObject|ArrayObject|ArrayList $parent, mixed $value): mixed
{
if ($value === null) {
return null;
Expand All @@ -30,17 +32,10 @@ protected function generateValue($parent, $value): mixed
}
}

protected function generateArrayValue($parent, $value): JsonObject
{
if ($this->isNumericArray($value)) {
return $this->generateListArray($parent, $value);
} else {
return $this->generateHashArray($parent, $value);
}
}

protected function generateListArray($parent, array $listArray): JsonObject
{
protected function generateListArray(
JsonObject|ArrayObject|ArrayList $parent,
array $listArray,
): JsonObject|ArrayObject|ArrayList {
$object = new JsonObject($parent);
$object->value = [];

Expand All @@ -53,8 +48,10 @@ protected function generateListArray($parent, array $listArray): JsonObject
return $object;
}

protected function generateHashArray($parent, array $hashArray): JsonObject
{
protected function generateHashArray(
JsonObject|ArrayObject|ArrayList $parent,
array $hashArray,
): JsonObject|ArrayObject|ArrayList {
$object = new JsonObject($parent);
$object->value = [];

Expand Down

0 comments on commit 32ca57e

Please sign in to comment.