Skip to content

Commit 8fe033d

Browse files
committed
Adopt immutable Collection DSL from Data
Replace chaining, __get, ArrayAccess, and proxy methods with constructor composition via with/filter/required params. Remove Filtered support, simplify persist and query building.
1 parent ef89a8a commit 8fe033d

3 files changed

Lines changed: 192 additions & 461 deletions

File tree

phpstan.neon.dist

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@ parameters:
55
- tests/
66
ignoreErrors:
77
- message: '/Call to an undefined (static )?method Respect\\Relational\\(Sql|Db|Mapper)::\w+\(\)\./'
8-
- message: '/Call to an undefined (static )?method Respect\\Data\\Collections\\(Collection|Filtered|Composite|Typed)::\w+\(\)\./'
9-
- message: '/Access to an undefined property Respect\\Relational\\Mapper::\$\w+\./'
8+
- message: '/Call to an undefined (static )?method Respect\\Data\\Collections\\(Collection|Composite|Typed)::\w+\(\)\./'
109
- message: '/Unsafe usage of new static\(\)\./'
1110
- message: '/Cannot unset property .+ because it might have hooks in a subclass\./'
11+
-
12+
message: '/(Access to an undefined property object|Cannot access property .+ on mixed)/'
13+
path: tests/
1214
-
1315
message: '/Parameter #1 .+ of class Respect\\Relational\\Mapper constructor expects .+, string given\./'
1416
path: tests/MapperTest.php

src/Mapper.php

Lines changed: 25 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
use Respect\Data\CollectionIterator;
1212
use Respect\Data\Collections\Collection;
1313
use Respect\Data\Collections\Composite;
14-
use Respect\Data\Collections\Filtered;
1514
use Respect\Data\Hydrator;
1615
use Respect\Data\Hydrators\PrestyledAssoc;
1716
use SplObjectStorage;
@@ -70,28 +69,18 @@ public function fetchAll(Collection $collection, mixed $extra = null): array
7069

7170
public function persist(object $object, Collection $onCollection): object
7271
{
73-
if ($onCollection instanceof Filtered) {
74-
return parent::persist($object, $onCollection);
75-
}
76-
7772
if ($this->persisting->offsetExists($object)) {
7873
return parent::persist($object, $onCollection);
7974
}
8075

8176
$this->persisting[$object] = true;
8277

8378
try {
84-
$connectsTo = $onCollection->connectsTo;
85-
86-
if ($connectsTo) {
87-
$remote = $this->style->remoteIdentifier($connectsTo->name);
88-
$related = $this->getRelatedEntity($object, $remote);
89-
if ($related !== null) {
90-
$this->persist($related, $connectsTo);
79+
foreach ($onCollection->with as $child) {
80+
if ($child->name === null) {
81+
continue;
9182
}
92-
}
9383

94-
foreach ($onCollection->children as $child) {
9584
$remote = $this->style->remoteIdentifier($child->name);
9685
$related = $this->getRelatedEntity($object, $remote);
9786
if ($related === null) {
@@ -347,13 +336,8 @@ private function generateQuery(Collection $collection): Sql
347336
/** @return array<string, mixed> */
348337
private function extractColumns(object $entity, Collection $collection): array
349338
{
350-
$cols = $this->filterColumns(
351-
$this->entityFactory->extractColumns($entity),
352-
$collection,
353-
);
354-
355339
$dbCols = [];
356-
foreach ($cols as $key => $value) {
340+
foreach ($this->entityFactory->extractColumns($entity) as $key => $value) {
357341
$dbCols[$this->style->realProperty($key)] = $value;
358342
}
359343

@@ -365,29 +349,8 @@ private function buildSelectStatement(Sql $sql, array $collections): Sql
365349
{
366350
$selectTable = [];
367351
foreach ($collections as $tableSpecifier => $c) {
368-
if ($c instanceof Filtered) {
369-
$filters = $c->filters;
370-
if ($filters) {
371-
$fields = $this->entityFactory->enumerateFields($c->name);
372-
$pk = $this->style->identifier($c->name);
373-
$selectTable[] = self::aliasedColumn($tableSpecifier, $pk, $fields[$pk] ?? $pk);
374-
375-
if (!$c->identifierOnly) {
376-
foreach ($filters as $f) {
377-
$selectTable[] = self::aliasedColumn($tableSpecifier, $f, $fields[$f] ?? $f);
378-
}
379-
}
380-
381-
$connectedName = $c->connectsTo?->name;
382-
if ($connectedName !== null) {
383-
$fk = $this->style->remoteIdentifier($connectedName);
384-
$selectTable[] = self::aliasedColumn($tableSpecifier, $fk, $fields[$fk] ?? $fk);
385-
}
386-
}
387-
} else {
388-
foreach ($this->entityFactory->enumerateFields($c->name) as $dbCol => $styledProp) {
389-
$selectTable[] = self::aliasedColumn($tableSpecifier, $dbCol, $styledProp);
390-
}
352+
foreach ($this->entityFactory->enumerateFields($c->name) as $dbCol => $styledProp) {
353+
$selectTable[] = self::aliasedColumn($tableSpecifier, $dbCol, $styledProp);
391354
}
392355

393356
// Composition columns come after entity columns so they override on collision
@@ -440,10 +403,10 @@ private function parseConditions(array &$conditions, Collection $collection, str
440403
$parsedConditions = [];
441404
$aliasedPk = $alias . '.' . $this->style->identifier($collection->name);
442405

443-
if (is_scalar($collection->condition)) {
444-
$parsedConditions[] = [$aliasedPk, '=', $collection->condition];
445-
} elseif (is_array($collection->condition)) {
446-
foreach ($collection->condition as $column => $value) {
406+
if (is_scalar($collection->filter)) {
407+
$parsedConditions[] = [$aliasedPk, '=', $collection->filter];
408+
} elseif (is_array($collection->filter)) {
409+
foreach ($collection->filter as $column => $value) {
447410
if (!empty($parsedConditions)) {
448411
$parsedConditions[] = 'AND';
449412
}
@@ -486,7 +449,6 @@ private function parseCollection(
486449
$s = $this->style;
487450
$entity = $collection->name;
488451
$parent = $collection->parent?->name;
489-
$connected = $collection->connectsTo?->name;
490452

491453
$parentAlias = $parent ? $aliases[$parent] : null;
492454
$aliases[$entity] = $alias;
@@ -526,7 +488,7 @@ private function parseCollection(
526488
$aliasedPk = $alias . '.' . $s->identifier($entity);
527489
$aliasedParentPk = $parentAlias . '.' . $s->identifier($parent);
528490

529-
if ($this->hasComposition($entity, $connected, $parent)) {
491+
if ($this->isCompositionJoin($collection, $entity, $parent)) {
530492
$onName = $alias . '.' . $s->remoteIdentifier($parent);
531493
$onAlias = $aliasedParentPk;
532494
} else {
@@ -537,14 +499,23 @@ private function parseCollection(
537499
$sql->on([$onName => $onAlias]);
538500
}
539501

540-
private function hasComposition(string $entity, string|null $connected, string|null $parent): bool
502+
private function isCompositionJoin(Collection $collection, string $entity, string $parent): bool
541503
{
542-
if ($connected === null || $parent === null) {
543-
return false;
504+
foreach ($collection->with as $child) {
505+
$connected = $child->name;
506+
if ($connected === null) {
507+
continue;
508+
}
509+
510+
if (
511+
$entity === $this->style->composed($parent, $connected)
512+
|| $entity === $this->style->composed($connected, $parent)
513+
) {
514+
return true;
515+
}
544516
}
545517

546-
return $entity === $this->style->composed($parent, $connected)
547-
|| $entity === $this->style->composed($connected, $parent);
518+
return false;
548519
}
549520

550521
/** @param SplObjectStorage<object, Collection> $hydrated */

0 commit comments

Comments
 (0)