Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions src/Hydrator/DoctrineObjectWithComputed.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
namespace ApiSkeletons\Doctrine\ORM\GraphQL\Hydrator;

use Doctrine\Laminas\Hydrator\DoctrineObject;
use Generator;
use Laminas\Hydrator\Filter\FilterProviderInterface;
use Override;

use function array_flip;
use function array_key_exists;
use function array_keys;
use function get_class_methods;
Expand All @@ -30,6 +32,42 @@ final class DoctrineObjectWithComputed extends DoctrineObject
*/
private array $computedFields = [];

/**
* Flipped map of allowed field names for O(1) lookup.
* When empty, all Doctrine fields are yielded (no restriction).
*
* @var array<string, int>
*/
private array $allowedFields = [];

/**
* Restrict extraction to only the given field names.
*
* @param array<int, string> $fieldNames
*/
public function setAllowedFields(array $fieldNames): void
{
$this->allowedFields = array_flip($fieldNames);
}

/**
* Yield only the allowed subset of Doctrine field/association names.
* Falls back to all names when no restriction has been set.
*
* @return Generator<mixed, string, mixed, mixed>
*/
#[Override]
public function getFieldNames(): iterable
{
foreach (parent::getFieldNames() as $fieldName) {
if ($this->allowedFields !== [] && ! isset($this->allowedFields[$fieldName])) {
continue;
}

yield $fieldName;
}
}

/**
* Register a computed field for extraction
*
Expand Down
6 changes: 6 additions & 0 deletions src/Hydrator/HydratorContainer.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
use Override;
use ReflectionClass;

use function array_keys;
use function array_map;
use function assert;
use function class_implements;
use function in_array;
Expand Down Expand Up @@ -77,6 +79,10 @@ public function get(string $id): mixed
$object->addStrategy($fieldName, $self->get($fieldMetadata['hydratorStrategy']));
}

// Restrict extraction to only GraphQL-exposed fields
/** @psalm-suppress MixedArgument */
$object->setAllowedFields(array_map('strval', array_keys($metadata['fields'])));

// Register computed fields
if (isset($metadata['computedFields'])) {
/** @psalm-suppress MixedArrayAccess, MixedAssignment */
Expand Down
Loading