Skip to content

Commit 6512ccc

Browse files
committed
Rename Collection to Scope, remove dead code, simplify API
- Rename Collection to Scope, CollectionIterator to ScopeIterator, move out of Collections sub-namespace - Make Scope::$name non-null, remove all null-name guards - Remove registerScope, __isset, derive (unused after simplification) - Remove unused Stylable methods: realName, remoteFromIdentifier, isRelationProperty - Simplify __call to a one-liner Scope factory - Extract applyFirstMatch helper in Plural to deduplicate loops
1 parent 0b1c694 commit 6512ccc

21 files changed

Lines changed: 269 additions & 556 deletions

phpstan.neon.dist

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ parameters:
44
- src/
55
- tests/
66
ignoreErrors:
7-
- message: '/Call to an undefined (static )?method Respect\\Data\\(AbstractMapper|InMemoryMapper|Collections\\Collection)::\w+\(\)\./'
7+
- message: '/Call to an undefined (static )?method Respect\\Data\\(AbstractMapper|InMemoryMapper|Scope)::\w+\(\)\./'
88
- message: '/Unsafe usage of new static\(\)\./'
99
-
1010
message: '/Property .+ is never read, only written\./'

src/AbstractMapper.php

Lines changed: 40 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
namespace Respect\Data;
66

7-
use Respect\Data\Collections\Collection;
87
use SplObjectStorage;
98

109
use function count;
@@ -15,18 +14,15 @@
1514

1615
abstract class AbstractMapper
1716
{
18-
/** @var SplObjectStorage<object, Collection> Maps entity → source Collection */
17+
/** @var SplObjectStorage<object, Scope> Maps entity → source Scope */
1918
protected SplObjectStorage $tracked;
2019

2120
/** @var SplObjectStorage<object, string> Maps entity → 'insert'|'update'|'delete' */
2221
protected SplObjectStorage $pending;
2322

24-
/** @var array<string, array<int|string, object>> Identity-indexed map: [collectionName][idValue] → entity */
23+
/** @var array<string, array<int|string, object>> Identity-indexed map: [scopeName][idValue] → entity */
2524
protected array $identityMap = [];
2625

27-
/** @var array<string, Collection> */
28-
private array $collections = [];
29-
3026
public EntityFactory $entityFactory { get => $this->hydrator->entityFactory; }
3127

3228
public Styles\Stylable $style { get => $this->entityFactory->style; }
@@ -40,10 +36,10 @@ public function __construct(
4036

4137
abstract public function flush(): void;
4238

43-
abstract public function fetch(Collection $collection, mixed $extra = null): mixed;
39+
abstract public function fetch(Scope $scope, mixed $extra = null): mixed;
4440

4541
/** @return array<int, mixed> */
46-
abstract public function fetchAll(Collection $collection, mixed $extra = null): array;
42+
abstract public function fetchAll(Scope $scope, mixed $extra = null): array;
4743

4844
public function reset(): void
4945
{
@@ -55,29 +51,7 @@ public function clearIdentityMap(): void
5551
$this->identityMap = [];
5652
}
5753

58-
public function trackedCount(): int
59-
{
60-
return count($this->tracked);
61-
}
62-
63-
public function identityMapCount(): int
64-
{
65-
$total = 0;
66-
foreach ($this->identityMap as $entries) {
67-
$total += count($entries);
68-
}
69-
70-
return $total;
71-
}
72-
73-
public function markTracked(object $entity, Collection $collection): bool
74-
{
75-
$this->tracked[$entity] = $collection;
76-
77-
return true;
78-
}
79-
80-
public function persist(object $object, Collection $onCollection): object
54+
public function persist(object $object, Scope $onScope): object
8155
{
8256
if ($this->isTracked($object)) {
8357
$currentOp = $this->pending[$object] ?? null;
@@ -88,45 +62,56 @@ public function persist(object $object, Collection $onCollection): object
8862
return $object;
8963
}
9064

91-
$merged = $this->tryMergeWithIdentityMap($object, $onCollection);
65+
$merged = $this->tryMergeWithIdentityMap($object, $onScope);
9266
if ($merged !== null) {
9367
return $merged;
9468
}
9569

9670
$this->pending[$object] = 'insert';
97-
$this->markTracked($object, $onCollection);
98-
$this->registerInIdentityMap($object, $onCollection);
71+
$this->markTracked($object, $onScope);
72+
$this->registerInIdentityMap($object, $onScope);
9973

10074
return $object;
10175
}
10276

103-
public function remove(object $object, Collection $fromCollection): bool
77+
public function remove(object $object, Scope $fromScope): void
10478
{
10579
$this->pending[$object] = 'delete';
10680

107-
if (!$this->isTracked($object)) {
108-
$this->markTracked($object, $fromCollection);
81+
if ($this->isTracked($object)) {
82+
return;
10983
}
11084

111-
return true;
85+
$this->markTracked($object, $fromScope);
11286
}
11387

114-
public function isTracked(object $entity): bool
88+
public function trackedCount(): int
11589
{
116-
return $this->tracked->offsetExists($entity);
90+
return count($this->tracked);
11791
}
11892

119-
public function registerCollection(string $alias, Collection $collection): void
93+
public function identityMapCount(): int
12094
{
121-
$this->collections[$alias] = $collection;
95+
$total = 0;
96+
foreach ($this->identityMap as $entries) {
97+
$total += count($entries);
98+
}
99+
100+
return $total;
122101
}
123102

124-
protected function registerInIdentityMap(object $entity, Collection $coll): void
103+
public function markTracked(object $entity, Scope $scope): void
125104
{
126-
if ($coll->name === null) {
127-
return;
128-
}
105+
$this->tracked[$entity] = $scope;
106+
}
129107

108+
public function isTracked(object $entity): bool
109+
{
110+
return $this->tracked->offsetExists($entity);
111+
}
112+
113+
protected function registerInIdentityMap(object $entity, Scope $coll): void
114+
{
130115
$idValue = $this->entityIdValue($entity, $coll->name);
131116
if ($idValue === null) {
132117
return;
@@ -135,12 +120,8 @@ protected function registerInIdentityMap(object $entity, Collection $coll): void
135120
$this->identityMap[$coll->name][$idValue] = $entity;
136121
}
137122

138-
protected function evictFromIdentityMap(object $entity, Collection $coll): void
123+
protected function evictFromIdentityMap(object $entity, Scope $coll): void
139124
{
140-
if ($coll->name === null) {
141-
return;
142-
}
143-
144125
$idValue = $this->entityIdValue($entity, $coll->name);
145126
if ($idValue === null) {
146127
return;
@@ -149,26 +130,22 @@ protected function evictFromIdentityMap(object $entity, Collection $coll): void
149130
unset($this->identityMap[$coll->name][$idValue]);
150131
}
151132

152-
protected function findInIdentityMap(Collection $collection): object|null
133+
protected function findInIdentityMap(Scope $scope): object|null
153134
{
154-
if ($collection->name === null || !is_scalar($collection->filter) || $collection->hasChildren) {
135+
if (!is_scalar($scope->filter) || $scope->hasChildren) {
155136
return null;
156137
}
157138

158-
$condition = $this->normalizeIdValue($collection->filter);
139+
$condition = $this->normalizeIdValue($scope->filter);
159140
if ($condition === null) {
160141
return null;
161142
}
162143

163-
return $this->identityMap[$collection->name][$condition] ?? null;
144+
return $this->identityMap[$scope->name][$condition] ?? null;
164145
}
165146

166-
private function tryMergeWithIdentityMap(object $entity, Collection $coll): object|null
147+
private function tryMergeWithIdentityMap(object $entity, Scope $coll): object|null
167148
{
168-
if ($coll->name === null) {
169-
return null;
170-
}
171-
172149
$entityId = $this->entityIdValue($entity, $coll->name);
173150
$idValue = $entityId ?? $this->normalizeIdValue($coll->filter);
174151

@@ -237,22 +214,9 @@ private function normalizeIdValue(mixed $value): int|string|null
237214
return null;
238215
}
239216

240-
public function __isset(string $alias): bool
217+
/** @param array<string, mixed> $arguments */
218+
public function __call(string $name, array $arguments): Scope
241219
{
242-
return isset($this->collections[$alias]);
243-
}
244-
245-
/** @param list<mixed> $arguments */
246-
public function __call(string $name, array $arguments): Collection
247-
{
248-
if (isset($this->collections[$name])) {
249-
if (empty($arguments)) {
250-
return clone $this->collections[$name];
251-
}
252-
253-
return $this->collections[$name]->derive(...$arguments); // @phpstan-ignore argument.type
254-
}
255-
256-
return new Collection($name, ...$arguments); // @phpstan-ignore argument.type
220+
return new Scope($name, ...$arguments); // @phpstan-ignore argument.type
257221
}
258222
}

src/EntityFactory.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -203,17 +203,17 @@ public function extractProperties(object $entity): array
203203
}
204204

205205
/**
206-
* Enumerate persistable fields for a collection, mapping DB column names to styled property names.
206+
* Enumerate persistable fields for a scope, mapping DB column names to styled property names.
207207
*
208208
* @return array<string, string> DB column name → styled property name
209209
*/
210-
public function enumerateFields(string $collectionName): array
210+
public function enumerateFields(string $scopeName): array
211211
{
212-
if (isset($this->fieldCache[$collectionName])) {
213-
return $this->fieldCache[$collectionName];
212+
if (isset($this->fieldCache[$scopeName])) {
213+
return $this->fieldCache[$scopeName];
214214
}
215215

216-
$class = $this->resolveClass($collectionName);
216+
$class = $this->resolveClass($scopeName);
217217
$relations = $this->detectRelationProperties($class);
218218
$fields = [];
219219

@@ -225,7 +225,7 @@ public function enumerateFields(string $collectionName): array
225225
$fields[$this->style->realProperty($name)] = $name;
226226
}
227227

228-
return $this->fieldCache[$collectionName] = $fields;
228+
return $this->fieldCache[$scopeName] = $fields;
229229
}
230230

231231
/**

src/Hydrator.php

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,22 @@
44

55
namespace Respect\Data;
66

7-
use Respect\Data\Collections\Collection;
87
use SplObjectStorage;
98

10-
/** Transforms raw backend data into entity instances mapped to their collections */
9+
/** Transforms raw backend data into entity instances mapped to their scopes */
1110
interface Hydrator
1211
{
1312
public EntityFactory $entityFactory { get; }
1413

1514
/** Returns just the root entity */
1615
public function hydrate(
1716
mixed $raw,
18-
Collection $collection,
17+
Scope $scope,
1918
): object|false;
2019

21-
/** @return SplObjectStorage<object, Collection>|false */
20+
/** @return SplObjectStorage<object, Scope>|false */
2221
public function hydrateAll(
2322
mixed $raw,
24-
Collection $collection,
23+
Scope $scope,
2524
): SplObjectStorage|false;
2625
}

src/Hydrators/Base.php

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@
55
namespace Respect\Data\Hydrators;
66

77
use DomainException;
8-
use Respect\Data\Collections\Collection;
98
use Respect\Data\EntityFactory;
109
use Respect\Data\Hydrator;
10+
use Respect\Data\Scope;
1111
use SplObjectStorage;
1212

13-
/** Base hydrator providing collection-tree entity wiring */
13+
/** Base hydrator providing scope-tree entity wiring */
1414
abstract class Base implements Hydrator
1515
{
1616
public function __construct(
@@ -20,52 +20,52 @@ public function __construct(
2020

2121
public function hydrate(
2222
mixed $raw,
23-
Collection $collection,
23+
Scope $scope,
2424
): object|false {
25-
$entities = $this->hydrateAll($raw, $collection);
25+
$entities = $this->hydrateAll($raw, $scope);
2626
if ($entities === false) {
2727
return false;
2828
}
2929

3030
foreach ($entities as $entity) {
31-
if ($entities[$entity] === $collection) {
31+
if ($entities[$entity] === $scope) {
3232
return $entity;
3333
}
3434
}
3535

3636
throw new DomainException(
37-
'Hydration produced no entity for collection "' . $collection->name . '"',
37+
'Hydration produced no entity for scope "' . $scope->name . '"',
3838
);
3939
}
4040

41-
/** @param SplObjectStorage<object, Collection> $entities */
41+
/** @param SplObjectStorage<object, Scope> $entities */
4242
protected function wireRelationships(SplObjectStorage $entities): void
4343
{
4444
$style = $this->entityFactory->style;
4545
$others = clone $entities;
4646

4747
foreach ($entities as $entity) {
48-
$coll = $entities[$entity];
48+
$scope = $entities[$entity];
4949

5050
foreach ($others as $other) {
5151
if ($other === $entity) {
5252
continue;
5353
}
5454

55-
$otherColl = $others[$other];
56-
if ($otherColl->parent !== $coll || $otherColl->name === null) {
55+
$otherScope = $others[$other];
56+
if ($otherScope->parent !== $scope) {
5757
continue;
5858
}
5959

6060
$relationName = $style->relationProperty(
61-
$style->remoteIdentifier($otherColl->name),
61+
$style->remoteIdentifier($otherScope->name),
6262
);
6363

6464
if ($relationName === null) {
6565
continue;
6666
}
6767

68-
$id = $this->entityFactory->get($other, $style->identifier($otherColl->name));
68+
$id = $this->entityFactory->get($other, $style->identifier($otherScope->name));
6969
if ($id === null) {
7070
continue;
7171
}

0 commit comments

Comments
 (0)