Skip to content

Commit 648723e

Browse files
committed
Add more tests
1 parent b9068c3 commit 648723e

File tree

7 files changed

+210
-18
lines changed

7 files changed

+210
-18
lines changed

src/Record.php

Lines changed: 72 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,15 @@ class Record implements \ArrayAccess
2525
private $state;
2626

2727
/** @var Record[][] */
28-
private $relations;
28+
private $references;
2929

3030
public function __construct(Schema $schema)
3131
{
3232
$this->schema = $schema;
3333
$this->values = array_fill_keys($schema->getFields(), null);
3434
$this->state = self::STATE_INSERT;
3535
$this->changed = [];
36-
$this->relations = [];
36+
$this->references = [];
3737
}
3838

3939
public function getPrimaryKey(): array
@@ -82,9 +82,71 @@ public function getModel(): Model
8282
return $this->schema->getModel($this);
8383
}
8484

85+
public function getReferredModel(string $name): Model
86+
{
87+
$reference = $this->getSchema()->getReference($name);
88+
89+
if (!$reference->isSingleRelationship()) {
90+
throw new \RuntimeException('Can only refer to single models in a single relationship');
91+
}
92+
93+
$records = $this->getReference($name);
94+
95+
if (empty($records)) {
96+
throw new \UnexpectedValueException('The single relationship does not refer to any record');
97+
}
98+
99+
return $records[0]->getModel();
100+
}
101+
102+
public function getReferredModels(string $name): array
103+
{
104+
$reference = $this->getSchema()->getReference($name);
105+
106+
if ($reference->isSingleRelationship()) {
107+
throw new \RuntimeException('Cannot refer to multiple models in a single relationship');
108+
}
109+
110+
$models = [];
111+
112+
foreach ($this->getReference($name) as $record) {
113+
$models[] = $record->getModel();
114+
}
115+
116+
return $models;
117+
}
118+
119+
public function getReferredProxyModels(string $proxy, string $name): array
120+
{
121+
$proxyReference = $this->getSchema()->getReference($proxy);
122+
$reference = $proxyReference->getReferencedSchema()->getReference($name);
123+
124+
if ($proxyReference->isSingleRelationship()) {
125+
throw new \RuntimeException('Cannot refer to multiple models in a single relationship');
126+
}
127+
128+
if (!$reference->isSingleRelationship()) {
129+
throw new \RuntimeException('Can only refer to single models in a single relationship');
130+
}
131+
132+
$models = [];
133+
134+
foreach ($this->getReference($proxy) as $record) {
135+
$records = $record->getReference($name);
136+
137+
if (empty($records)) {
138+
throw new \UnexpectedValueException('The single relationship does not refer to any record');
139+
}
140+
141+
$models[] = $records[0]->getModel();
142+
}
143+
144+
return $models;
145+
}
146+
85147
public function isReferenceLoaded(string $name): bool
86148
{
87-
return isset($this->relations[$name]);
149+
return isset($this->references[$name]);
88150
}
89151

90152
/**
@@ -93,11 +155,11 @@ public function isReferenceLoaded(string $name): bool
93155
*/
94156
public function getReference(string $name): array
95157
{
96-
if (!isset($this->relations[$name])) {
158+
if (!isset($this->references[$name])) {
97159
throw new \RuntimeException("Cannot access relation '$name' that has not been provided");
98160
}
99161

100-
return $this->relations[$name];
162+
return $this->references[$name];
101163
}
102164

103165
public function fillReference(string $name, array $records): void
@@ -114,7 +176,7 @@ public function fillReference(string $name, array $records): void
114176
throw new \InvalidArgumentException('The relationship cannot reference more than a single record');
115177
}
116178

117-
$this->relations[$name] = array_values($records);
179+
$this->references[$name] = array_values($records);
118180
}
119181

120182
private function isRelated(Reference $reference, Record $record): bool
@@ -135,13 +197,16 @@ private function isRelated(Reference $reference, Record $record): bool
135197
return true;
136198
}
137199

200+
/**
201+
* @return Record[]
202+
*/
138203
public function getMappedRecords(): array
139204
{
140205
/** @var Record[] $records */
141206
$records = [spl_object_id($this) => $this];
142207

143208
do {
144-
foreach (current($records)->relations as $relation) {
209+
foreach (current($records)->references as $relation) {
145210
foreach ($relation as $record) {
146211
$id = spl_object_id($record);
147212

src/Reference.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,15 @@ public function __construct(Schema $schema, array $fields, Schema $referencedSch
2929
$this->primaryRelation = array_diff($this->referencedSchema->getPrimaryKey(), $this->referencedFields) === [];
3030

3131
if (empty($this->fields) || \count($this->fields) !== \count($this->referencedFields)) {
32-
throw new \InvalidArgumentException('Unexpected list of fields in relationship');
32+
throw new \InvalidArgumentException('Unexpected list of fields in reference');
33+
}
34+
35+
if (array_diff($this->fields, $this->schema->getFields()) !== []) {
36+
throw new \InvalidArgumentException('The referring fields must be defined in the referring schema');
37+
}
38+
39+
if (array_diff($this->referencedFields, $this->referencedSchema->getFields()) !== []) {
40+
throw new \InvalidArgumentException('The referred fields must be defined in the referred schema');
3341
}
3442
}
3543

src/ReferenceFiller.php

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,14 @@ public function fill(array $records, array $references): void
3232

3333
$this->cache = [];
3434
$schema = reset($records)->getSchema();
35-
$schemaId = $this->getSchemaId($schema);
3635

3736
foreach ($records as $record) {
3837
if ($record->getSchema() !== $schema) {
3938
throw new \InvalidArgumentException('The provided list of records did not share the same schema');
4039
}
4140

4241
foreach ($record->getMappedRecords() as $mappedRecord) {
43-
$this->cacheRecord($schemaId, $mappedRecord);
42+
$this->cacheRecord($this->getSchemaId($mappedRecord->getSchema()), $mappedRecord);
4443
}
4544
}
4645

@@ -129,18 +128,18 @@ private function parseReferences(array $references): array
129128
return $subReferences;
130129
}
131130

132-
private function cacheRecord(string $schemaId, Record $record): void
131+
private function cacheRecord(int $schemaId, Record $record): void
133132
{
134133
$recordId = implode('-', $record->getPrimaryKey());
135134

136-
if (isset($this->cache[$schemaId][$recordId])) {
135+
if (isset($this->cache[$schemaId][$recordId]) && $this->cache[$schemaId][$recordId] !== $record) {
137136
throw new \RuntimeException('Duplicated record detected when filling references for records');
138137
}
139138

140139
$this->cache[$schemaId][$recordId] = $record;
141140
}
142141

143-
private function getCachedRecord(string $schemaId, Schema $schema, array $row): Record
142+
private function getCachedRecord(int $schemaId, Schema $schema, array $row): Record
144143
{
145144
$primaryKey = [];
146145

@@ -159,8 +158,8 @@ private function getCachedRecord(string $schemaId, Schema $schema, array $row):
159158
return $record;
160159
}
161160

162-
private function getSchemaId(Schema $schema): string
161+
private function getSchemaId(Schema $schema): int
163162
{
164-
return spl_object_hash($schema);
163+
return spl_object_id($schema);
165164
}
166165
}

src/Schema.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
* @copyright Copyright (c) 2018 Riikka Kalliomäki
1111
* @license http://opensource.org/licenses/mit-license.php MIT License
1212
*/
13-
class Schema
13+
abstract class Schema
1414
{
1515
private $container;
1616

tests/helpers/IntegrationTestCase.php

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
abstract class IntegrationTestCase extends TestCase
1616
{
1717
/** @var Connection */
18-
private $connection;
18+
protected $connection;
1919

2020
/** @var TestPersonSchema */
2121
protected $personSchema;
@@ -210,5 +210,71 @@ public function testLoadingReferences(): void
210210
foreach ($parents as $parent) {
211211
$this->assertTrue(\in_array($person->getDatabaseRecord(), $childRecords($parent), true));
212212
}
213+
214+
$repository->loadFamily($parents);
215+
216+
foreach ($parents as $parent) {
217+
$this->assertTrue(\in_array($person->getDatabaseRecord(), $childRecords($parent), true));
218+
}
219+
}
220+
221+
public function testInsertWithNoValues()
222+
{
223+
$this->expectException(\InvalidArgumentException::class);
224+
$this->connection->insert($this->personSchema->getTable(), []);
225+
}
226+
227+
public function testSelectWithNoFields()
228+
{
229+
$this->expectException(\InvalidArgumentException::class);
230+
$this->connection->select([], $this->personSchema->getTable(), []);
231+
}
232+
233+
public function testSelectWithNoTable()
234+
{
235+
$this->expectException(\InvalidArgumentException::class);
236+
$this->connection->select(['id'], '', []);
237+
}
238+
239+
public function testUpdateWithNoValues()
240+
{
241+
$this->expectException(\InvalidArgumentException::class);
242+
$this->connection->update($this->personSchema->getTable(), [], ['id' => 1]);
243+
}
244+
245+
public function testUpdateWithNoConditions()
246+
{
247+
$this->expectException(\InvalidArgumentException::class);
248+
$this->connection->update($this->personSchema->getTable(), ['first_name' => 'Jane'], []);
249+
}
250+
251+
public function testDeleteWithNoConditions()
252+
{
253+
$this->expectException(\InvalidArgumentException::class);
254+
$this->connection->delete($this->personSchema->getTable(), []);
255+
}
256+
257+
public function testUnsupportedValueType()
258+
{
259+
$this->expectException(\InvalidArgumentException::class);
260+
$this->connection->insert($this->personSchema->getTable(), ['first_name' => ['array', 'values']]);
261+
}
262+
263+
public function testInvalidSortOrder()
264+
{
265+
$this->expectException(\InvalidArgumentException::class);
266+
$this->connection->select(['id'], $this->personSchema->getTable(), [], ['id' => 0]);
267+
}
268+
269+
public function testUnlimitedWithoutSortOrder()
270+
{
271+
$repository = $this->getTestPersonRepository();
272+
273+
$repository->savePerson($repository->createPerson('Jane', 'Doe', 20));
274+
$repository->savePerson($repository->createPerson('John', 'Doe', 20));
275+
276+
$results = $this->connection->select(['id'], $this->personSchema->getTable(), [], [], 1);
277+
278+
$this->assertCount(2, iterator_to_array($results));
213279
}
214280
}

tests/tests/MySqlIntegrationTest.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,14 @@ protected function setUpDatabase(Connection $connection): void
6161
$pdo->exec($query);
6262
}
6363
}
64+
65+
public function testDSNSupport(): void
66+
{
67+
$method = new \ReflectionMethod($this->connection, 'getDataSource');
68+
$method->setAccessible(true);
69+
70+
$this->assertNotContains('port', $method->invoke($this->connection, 'localhost', 'database'));
71+
$this->assertContains('port', $method->invoke($this->connection, 'localhost:3306', 'database'));
72+
$this->assertContains('unix_socket', $method->invoke($this->connection, '/tmp/mysql.sock', 'database'));
73+
}
6474
}

tests/tests/SchemaTest.php

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use PHPUnit\Framework\TestCase;
66
use Simply\Container\Container;
7+
use Simply\Database\Test\TestParentSchema;
78
use Simply\Database\Test\TestPersonSchema;
89

910
/**
@@ -14,12 +15,55 @@
1415
*/
1516
class SchemaTest extends TestCase
1617
{
17-
public function testInvalidRererence()
18+
private function getPersonSchema(): TestPersonSchema
1819
{
1920
$container = new Container();
2021
$schema = new TestPersonSchema($container);
2122

23+
$container[TestPersonSchema::class] = $schema;
24+
$container[TestParentSchema::class] = new TestParentSchema($container);
25+
26+
return $schema;
27+
}
28+
public function testInvalidRererence()
29+
{
30+
$schema = $this->getPersonSchema();
31+
2232
$this->expectException(\InvalidArgumentException::class);
2333
$schema->getReference('not-a-valid-reference');
2434
}
35+
36+
public function testSchemaEquivalence()
37+
{
38+
$schema = $this->getPersonSchema();
39+
40+
$reference = $schema->getReference('parents');
41+
42+
$this->assertSame($schema, $reference->getSchema());
43+
$this->assertSame($schema, $reference->getReferencedSchema()->getReference('parent')->getReferencedSchema());
44+
}
45+
46+
public function testInvalidNumberOfFields(): void
47+
{
48+
$schema = $this->getPersonSchema();
49+
50+
$this->expectException(\InvalidArgumentException::class);
51+
new Reference($schema, ['first_name', 'last_name'], $schema, ['first_name']);
52+
}
53+
54+
public function testInvalidReferringFields(): void
55+
{
56+
$schema = $this->getPersonSchema();
57+
58+
$this->expectException(\InvalidArgumentException::class);
59+
new Reference($schema, ['father_id'], $schema, ['id']);
60+
}
61+
62+
public function testInvalidReferredFields(): void
63+
{
64+
$schema = $this->getPersonSchema();
65+
66+
$this->expectException(\InvalidArgumentException::class);
67+
new Reference($schema, ['id'], $schema, ['mother_id']);
68+
}
2569
}

0 commit comments

Comments
 (0)