Skip to content

Commit

Permalink
ISSUE-72: Add context instead of group + Add breadcrum path
Browse files Browse the repository at this point in the history
  • Loading branch information
BowlOfSoup committed Mar 2, 2024
1 parent 0185916 commit 51e4ffc
Show file tree
Hide file tree
Showing 9 changed files with 167 additions and 20 deletions.
68 changes: 68 additions & 0 deletions src/Model/Context.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php

declare(strict_types=1);

namespace BowlOfSoup\NormalizerBundle\Model;

class Context
{
/** @var string|null */
private $group;

/** @var string[] */
private $includes = [];

public function getGroup(): ?string
{
return $this->group;
}

/**
* @return $this
*/
public function setGroup(?string $group): self
{
$this->group = $group;
return $this;
}

public function getIncludes(): array
{
return $this->includes;
}

/**
* @return $this
*/
public function setIncludes(array $includes): self
{
$this->includes = $includes;

return $this;
}

/**
* @return $this
*/
public function setIncludesFromString(string $includes): self
{
$this->setIncludes(explode(',', $includes));

return $this;
}

/**
* @return $this
*/
public function addInclude(string $include): self
{
$this->includes[] = $include;

return $this;
}

public function hasInclude(string $assertion): bool
{
return in_array($assertion, $this->includes);
}
}
29 changes: 28 additions & 1 deletion src/Service/Normalize/AbstractNormalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
use BowlOfSoup\NormalizerBundle\Annotation\Normalize;
use BowlOfSoup\NormalizerBundle\Annotation\Translate;
use BowlOfSoup\NormalizerBundle\Exception\BosNormalizerException;
use BowlOfSoup\NormalizerBundle\Model\Context;
use BowlOfSoup\NormalizerBundle\Model\ObjectCache;
use BowlOfSoup\NormalizerBundle\Service\Extractor\AnnotationExtractor;
use BowlOfSoup\NormalizerBundle\Service\Extractor\ClassExtractor;
use BowlOfSoup\NormalizerBundle\Service\Normalizer;
use BowlOfSoup\NormalizerBundle\Service\ObjectHelper;
use Doctrine\Common\Collections\Collection;
use Symfony\Contracts\Translation\TranslatorInterface;
Expand All @@ -32,6 +32,12 @@ abstract class AbstractNormalizer
/** @var string|null */
protected $group = null;

/** @var \BowlOfSoup\NormalizerBundle\Model\Context */
protected $context;

/** @var array */
protected $currentPath = [];

/** @var int|null */
protected $maxDepth = null;

Expand Down Expand Up @@ -75,6 +81,26 @@ protected function hasMaxDepth(): bool
return null !== $this->maxDepth && ($this->processedDepth + 1) > $this->maxDepth;
}

/**
* This function deals with processing $context, which due to compatibility can be either a group or a context model.
* Refactor this in the next major version.
*
* @param \BowlOfSoup\NormalizerBundle\Model\Context|string|null $context
*/
protected function handleContext($context): void
{
if (is_string($context)) {
// Group has been given instead of context. Set group on context.
$context = (new Context())->setGroup($context);
} elseif (!$context instanceof Context) {
// No context has been given, instantiate empty context.
$context = new Context();
}

$this->group = $context->getGroup();
$this->context = $context;
}

/**
* @throws \BowlOfSoup\NormalizerBundle\Exception\BosNormalizerException
*
Expand Down Expand Up @@ -198,6 +224,7 @@ protected function normalizeReferencedCollection($propertyValue, Normalize $prop
$normalizedCollection[] = (!empty($normalizedObject) ? $normalizedObject : null);
}
--$this->processedDepth;

}

return $normalizedCollection;
Expand Down
7 changes: 4 additions & 3 deletions src/Service/Normalize/MethodNormalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,21 @@ public function __construct(
}

/**
* @param \BowlOfSoup\NormalizerBundle\Model\Context|string|null $context
*
* @throws \BowlOfSoup\NormalizerBundle\Exception\BosNormalizerException
* @throws \ReflectionException
*/
public function normalize(
Normalizer $sharedNormalizer,
ObjectBag $objectBag,
?string $group
$context
): array {
$object = $objectBag->getObject();
$objectName = $objectBag->getObjectName();

$this->sharedNormalizer = $sharedNormalizer;
$this->group = $group;

$this->handleContext($context);
$this->processedDepthObjects[$objectName] = $this->processedDepth;

$normalizedMethods = [];
Expand Down
27 changes: 20 additions & 7 deletions src/Service/Normalize/PropertyNormalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,20 +32,22 @@ public function __construct(
}

/**
* @param \BowlOfSoup\NormalizerBundle\Model\Context|string|null $context
*
* @throws \BowlOfSoup\NormalizerBundle\Exception\BosNormalizerException
* @throws \ReflectionException
*/
public function normalize(
Normalizer $sharedNormalizer,
ObjectBag $objectBag,
?string $group
$context
): array {
$object = $objectBag->getObject();
$objectName = $objectBag->getObjectName();
$objectIdentifier = $objectBag->getObjectIdentifier();

$this->sharedNormalizer = $sharedNormalizer;
$this->group = $group;
$this->handleContext($context);
$this->nameAndClassStore[$objectIdentifier] = new Store();

$normalizedProperties = [];
Expand Down Expand Up @@ -123,6 +125,15 @@ private function normalizeProperty(
continue;
}

$annotationName = $propertyAnnotation->getName();
if (!empty($annotationName)) {
$propertyName = $propertyAnnotation->getName();
}

// Add to current path, like a breadcrumb where we are when normalizing.
$this->currentPath[] = $propertyName;
dump($this->currentPath);

Check failure on line 135 in src/Service/Normalize/PropertyNormalizer.php

View workflow job for this annotation

GitHub Actions / build (8.2)

Function dump not found.

if ($propertyAnnotation->hasType()) {
$propertyValue = $this->getValueForPropertyWithType(
$object,
Expand All @@ -142,17 +153,19 @@ private function normalizeProperty(
}
}

$annotationName = $propertyAnnotation->getName();
if (!empty($annotationName)) {
$propertyName = $propertyAnnotation->getName();
}

$propertyValue = (is_array($propertyValue) && empty($propertyValue) ? null : $propertyValue);
if (null !== $translationAnnotation) {
$propertyValue = $this->translateValue($propertyValue, $translationAnnotation);
}

$normalizedProperties[$propertyName] = $propertyValue;

// Decrease current path.
if (is_array($this->currentPath) && count($this->currentPath) > 1) {
array_pop($this->currentPath);
} else {
$this->currentPath = [];
}
}

return $normalizedProperties;
Expand Down
30 changes: 22 additions & 8 deletions src/Service/Normalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace BowlOfSoup\NormalizerBundle\Service;

use BowlOfSoup\NormalizerBundle\Exception\BosNormalizerException;
use BowlOfSoup\NormalizerBundle\Model\Context;
use BowlOfSoup\NormalizerBundle\Model\ObjectBag;
use BowlOfSoup\NormalizerBundle\Model\ObjectCache;
use BowlOfSoup\NormalizerBundle\Service\Extractor\ClassExtractor;
Expand Down Expand Up @@ -36,28 +37,39 @@ public function __construct(
* Normalize an object or an array of objects, for a specific group.
*
* @param mixed $data
* @param \BowlOfSoup\NormalizerBundle\Model\Context|string|null $context
*
* @throws \BowlOfSoup\NormalizerBundle\Exception\BosNormalizerException
* @throws \ReflectionException
*/
public function normalize($data, string $group = null): array
public function normalize($data, $context = null): array
{
if (empty($data)) {
return [];
}

if (is_string($context)) {
// Group has been given instead of context. Set group on context.
$context = (new Context())->setGroup($context);
} elseif (!$context instanceof Context) {
// No context has been given, instantiate empty context.
$context = new Context();
}

$this->cleanUpSession();

return $this->normalizeData($data, $group);
return $this->normalizeData($data, $context);
}

/**
* Get properties for given object, annotations per property and begin normalizing.
*
* @param \BowlOfSoup\NormalizerBundle\Model\Context|string $context
*
* @throws \ReflectionException
* @throws \BowlOfSoup\NormalizerBundle\Exception\BosNormalizerException
*/
public function normalizeObject(object $object, ?string $group): array
public function normalizeObject(object $object, $context): array
{
$normalizedConstructs = [];
$objectName = get_class($object);
Expand All @@ -73,10 +85,10 @@ public function normalizeObject(object $object, ?string $group): array

$objectBag = new ObjectBag($object, $objectIdentifier, $objectName);

$normalizedClassProperties = $this->propertyNormalizer->normalize($this, $objectBag, $group);
$normalizedClassProperties = $this->propertyNormalizer->normalize($this, $objectBag, $context);
$normalizedConstructs = array_merge($normalizedConstructs, ...$normalizedClassProperties);

$normalizedClassMethods = $this->methodNormalizer->normalize($this, $objectBag, $group);
$normalizedClassMethods = $this->methodNormalizer->normalize($this, $objectBag, $context);
$normalizedConstructs = array_merge($normalizedConstructs, ...$normalizedClassMethods);

if (null !== $objectIdentifier) {
Expand All @@ -89,20 +101,22 @@ public function normalizeObject(object $object, ?string $group): array
}

/**
* @param \BowlOfSoup\NormalizerBundle\Model\Context|string $context
*
* @throws \BowlOfSoup\NormalizerBundle\Exception\BosNormalizerException
* @throws \ReflectionException
*/
private function normalizeData($data, ?string $group): array
private function normalizeData($data, $context): array
{
$this->propertyNormalizer->cleanUp();
$normalizedData = [];

if (is_iterable($data) || $data instanceof \Traversable) {
foreach ($data as $item) {
$normalizedData[] = $this->normalizeData($item, $group);
$normalizedData[] = $this->normalizeData($item, $context);
}
} elseif (is_object($data)) {
$normalizedData = $this->normalizeObject($data, $group);
$normalizedData = $this->normalizeObject($data, $context);
} else {
throw new BosNormalizerException('Can only normalize an object or an array of objects. Input contains: ' . gettype($data));
}
Expand Down
20 changes: 19 additions & 1 deletion tests/Service/NormalizerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

use BowlOfSoup\NormalizerBundle\Exception\BosNormalizerException;
use BowlOfSoup\NormalizerBundle\Service\Extractor\ClassExtractor;
use BowlOfSoup\NormalizerBundle\Service\Normalizer;
use BowlOfSoup\NormalizerBundle\Tests\ArraySubset;
use BowlOfSoup\NormalizerBundle\Tests\assets\Address;
use BowlOfSoup\NormalizerBundle\Tests\assets\Group;
Expand Down Expand Up @@ -99,12 +98,31 @@ public function testNormalizeSuccessDifferentGroup(): void
'surName' => 'Of Soup',
'addresses' => [
[
'street' => 'Dummy Street',
'number' => null,
'postalCode' => null,
'city' => 'Amsterdam',
'getSpecialNotesForDelivery' => 'some special string',
],
[
'street' => null,
'number' => '4',
'postalCode' => '1234AB',
'city' => null,
'getSpecialNotesForDelivery' => 'some special string',
],
],
'hobbies' => [
[
'id' => 1,
],
[
'id' => 2,
],
[
'id' => 3,
],
]
];

$this->assertNotEmpty($result);
Expand Down
4 changes: 4 additions & 0 deletions tests/assets/Address.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,31 @@ class Address
* @var string
*
* @Bos\Normalize(group={"default"})
* @Bos\Normalize(group={"anotherGroup"})
*/
private $street;

/**
* @var int
*
* @Bos\Normalize(group={"default"})
* @Bos\Normalize(group={"anotherGroup"})
*/
private $number;

/**
* @var string
*
* @Bos\Normalize(group={"default"})
* @Bos\Normalize(group={"anotherGroup"})
*/
private $postalCode;

/**
* @var string
*
* @Bos\Normalize(group={"default"}, callback="getCityWithFormat")
* @Bos\Normalize(group={"anotherGroup"})
*/
private $city;

Expand Down
1 change: 1 addition & 0 deletions tests/assets/Hobbies.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class Hobbies
{
/**
* @Bos\Normalize(group={"default", "duplicateObjectId"})
* @Bos\Normalize(group={"anotherGroup"})
*
* @var int|null
*/
Expand Down
1 change: 1 addition & 0 deletions tests/assets/Person.php
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ class Person extends AbstractPerson
* @var \BowlOfSoup\NormalizerBundle\Tests\assets\Hobbies[]
*
* @Bos\Normalize(group={"default", "duplicateObjectId"}, type="collection")
* @Bos\Normalize(group={"anotherGroup"}, type="collection")
*/
private $hobbies;

Expand Down

0 comments on commit 51e4ffc

Please sign in to comment.