Skip to content

Commit bf8c511

Browse files
committed
Add refreshing method
1 parent dcefe8f commit bf8c511

15 files changed

+227
-84
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
namespace Simply\Database\Exception;
4+
5+
/**
6+
* MissingRecordException.
7+
* @author Riikka Kalliomäki <[email protected]>
8+
* @copyright Copyright (c) 2018 Riikka Kalliomäki
9+
* @license http://opensource.org/licenses/mit-license.php MIT License
10+
*/
11+
class MissingRecordException extends \RuntimeException
12+
{
13+
14+
}

src/Record.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,5 +327,9 @@ public function offsetSet($offset, $value)
327327
public function offsetUnset($offset)
328328
{
329329
$this->offsetSet($offset, null);
330+
331+
if ($this->state === self::STATE_INSERT) {
332+
unset($this->changed[$offset]);
333+
}
330334
}
331335
}

src/Repository.php

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Simply\Database;
44

55
use Simply\Database\Connection\Connection;
6+
use Simply\Database\Exception\MissingRecordException;
67

78
/**
89
* Repository.
@@ -13,7 +14,7 @@
1314
abstract class Repository
1415
{
1516
/** @var Connection */
16-
private $connection;
17+
protected $connection;
1718

1819
public function __construct(Connection $connection)
1920
{
@@ -109,7 +110,7 @@ protected function insert(Model $model): void
109110
{
110111
$record = $model->getDatabaseRecord();
111112
$schema = $record->getSchema();
112-
$values = $record->getDatabaseValues();
113+
$values = array_intersect_key($record->getDatabaseValues(), array_flip($record->getChangedFields()));
113114

114115
$primaryKeys = $schema->getPrimaryKey();
115116

@@ -130,13 +131,33 @@ protected function insert(Model $model): void
130131
$record->updateState(Record::STATE_INSERT);
131132
}
132133

134+
protected function refresh(Model $model): void
135+
{
136+
$record = $model->getDatabaseRecord();
137+
$schema = $record->getSchema();
138+
139+
$result = $this->connection->select($schema->getFields(), $schema->getTable(), $record->getPrimaryKey());
140+
$row = $result->fetch(\PDO::FETCH_ASSOC);
141+
142+
if (empty($row)) {
143+
throw new MissingRecordException('Tried to refresh a record that does not exist in the database');
144+
}
145+
146+
$record->setDatabaseValues($row);
147+
}
148+
133149
protected function update(Model $model): void
134150
{
135151
$record = $model->getDatabaseRecord();
136152
$schema = $record->getSchema();
137153
$values = array_intersect_key($record->getDatabaseValues(), array_flip($record->getChangedFields()));
138154

139-
$this->connection->update($schema->getTable(), $values, $record->getPrimaryKey());
155+
$result = $this->connection->update($schema->getTable(), $values, $record->getPrimaryKey());
156+
157+
if ($result->rowCount() !== 1) {
158+
throw new MissingRecordException('Tried to update a record that does not exist in the database');
159+
}
160+
140161
$record->updateState(Record::STATE_UPDATE);
141162
}
142163

@@ -145,7 +166,12 @@ protected function delete(Model $model): void
145166
$record = $model->getDatabaseRecord();
146167
$schema = $record->getSchema();
147168

148-
$this->connection->delete($schema->getTable(), $record->getPrimaryKey());
169+
$result = $this->connection->delete($schema->getTable(), $record->getPrimaryKey());
170+
171+
if ($result->rowCount() !== 1) {
172+
throw new MissingRecordException('Tried to delete a record that does not exist in the database');
173+
}
174+
149175
$record->updateState(Record::STATE_DELETE);
150176
}
151177

src/Schema.php

Lines changed: 20 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,6 @@
1212
*/
1313
abstract class Schema
1414
{
15-
/** @var string|Model */
16-
protected $model;
17-
18-
/** @var string */
19-
protected $table;
20-
21-
/** @var null|string|string[] */
22-
protected $primaryKey;
23-
24-
/** @var string[] */
25-
protected $fields;
26-
27-
/** @var array[] */
28-
protected $relationships = [];
29-
3015
/** @var Relationship[] */
3116
private $relationshipCache;
3217

@@ -39,20 +24,11 @@ public function __construct(ContainerInterface $container)
3924
$this->container = $container;
4025
}
4126

42-
public function getTable(): string
43-
{
44-
return $this->table;
45-
}
46-
47-
public function getPrimaryKey(): array
48-
{
49-
return $this->primaryKey === null ? [] : (array) $this->primaryKey;
50-
}
51-
52-
public function getFields(): array
53-
{
54-
return $this->fields;
55-
}
27+
abstract public function getModel(): string;
28+
abstract public function getTable(): string;
29+
abstract public function getPrimaryKey(): array;
30+
abstract public function getFields(): array;
31+
abstract public function getRelationshipDefinitions(): array;
5632

5733
/**
5834
* @return Relationship[]
@@ -61,7 +37,7 @@ public function getRelationships(): array
6137
{
6238
$relationships = [];
6339

64-
foreach (array_keys($this->relationships) as $name) {
40+
foreach (array_keys($this->getRelationshipDefinitions()) as $name) {
6541
$relationships[$name] = $this->getRelationship($name);
6642
}
6743

@@ -74,23 +50,23 @@ public function getRelationship(string $name): Relationship
7450
return $this->relationshipCache[$name];
7551
}
7652

77-
if (!isset($this->relationships[$name])) {
53+
$definition = $this->getRelationshipDefinitions()[$name] ?? null;
54+
55+
if (empty($definition)) {
7856
throw new \InvalidArgumentException("Invalid relationship '$name'");
7957
}
8058

81-
$this->relationshipCache[$name] = new Relationship(
82-
$name,
83-
$this,
84-
(array) $this->relationships[$name]['key'],
85-
$this->getSchema($this->relationships[$name]['schema']),
86-
(array) $this->relationships[$name]['field'],
87-
empty($this->relationships[$name]['unique']) ? false : true
88-
);
59+
$key = \is_array($definition['key']) ? $definition['key'] : [$definition['key']];
60+
$schema = $this->loadSchema($definition['schema']);
61+
$fields = \is_array($definition['field']) ? $definition['field'] : [$definition['field']];
62+
$unique = empty($definition['unique']) ? false : true;
63+
64+
$this->relationshipCache[$name] = new Relationship($name, $this, $key, $schema, $fields, $unique);
8965

9066
return $this->relationshipCache[$name];
9167
}
9268

93-
private function getSchema(string $name): Schema
69+
private function loadSchema(string $name): Schema
9470
{
9571
return $this->container->get($name);
9672
}
@@ -129,7 +105,10 @@ public function createRecordFromRow(array $row, string $prefix = ''): Record
129105

130106
public function createModel(Record $record): Model
131107
{
132-
return $this->model::createFromDatabaseRecord($record);
108+
/** @var Model $model */
109+
$model = $this->getModel();
110+
111+
return $model::createFromDatabaseRecord($record);
133112
}
134113

135114
public function createModelFromRow(array $row, string $prefix = '', array $relationships = []): Model

src/StaticSchema.php

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php
2+
3+
namespace Simply\Database;
4+
5+
/**
6+
* StaticSchema.
7+
* @author Riikka Kalliomäki <[email protected]>
8+
* @copyright Copyright (c) 2018 Riikka Kalliomäki
9+
* @license http://opensource.org/licenses/mit-license.php MIT License
10+
*/
11+
abstract class StaticSchema extends Schema
12+
{
13+
/** @var string */
14+
protected static $model = '';
15+
16+
/** @var string */
17+
protected static $table = '';
18+
19+
/** @var string[]|string */
20+
protected static $primaryKey = [];
21+
22+
/** @var string[] */
23+
protected static $fields = [];
24+
25+
/** @var array[] */
26+
protected static $relationships = [];
27+
28+
public function getModel(): string
29+
{
30+
return static::$model;
31+
}
32+
33+
public function getTable(): string
34+
{
35+
return static::$table;
36+
}
37+
38+
public function getPrimaryKey(): array
39+
{
40+
return \is_array(static::$primaryKey) ? static::$primaryKey : [static::$primaryKey];
41+
}
42+
43+
public function getFields(): array
44+
{
45+
return static::$fields;
46+
}
47+
48+
public function getRelationshipDefinitions(): array
49+
{
50+
return static::$relationships;
51+
}
52+
}

tests/helpers/TestCase/IntegrationTestCase.php

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use PHPUnit\Framework\TestCase;
66
use Simply\Container\Container;
77
use Simply\Database\Connection\Connection;
8+
use Simply\Database\Exception\MissingRecordException;
89
use Simply\Database\Test\TestHouseSchema;
910
use Simply\Database\Test\TestParentSchema;
1011
use Simply\Database\Test\TestPersonModel;
@@ -366,4 +367,61 @@ public function testIterationWithRelation()
366367

367368
$this->assertSame(4, $count);
368369
}
370+
371+
public function testRefreshingARecords()
372+
{
373+
$repository = $this->getTestPersonRepository();
374+
375+
$person = $repository->createPerson('Jane', 'Doe', 20);
376+
$person->setWeight(70);
377+
$repository->savePerson($person);
378+
379+
$secondInstance = $repository->findByFirstName('Jane')[0];
380+
$secondInstance->setWeight(75);
381+
$repository->savePerson($secondInstance);
382+
383+
$repository->refreshPerson($person);
384+
$this->assertSame(75.0, $person->getWeight());
385+
}
386+
387+
public function testRefreshingDeletedRecord()
388+
{
389+
$repository = $this->getTestPersonRepository();
390+
391+
$person = $repository->createPerson('Jane', 'Doe', 20);
392+
$repository->savePerson($person);
393+
394+
$repository->deletePerson($repository->findByFirstName('Jane')[0]);
395+
396+
$this->expectException(MissingRecordException::class);
397+
$repository->refreshPerson($person);
398+
}
399+
400+
public function testUpdatingDeletedRecord()
401+
{
402+
$repository = $this->getTestPersonRepository();
403+
404+
$person = $repository->createPerson('Jane', 'Doe', 20);
405+
$repository->savePerson($person);
406+
407+
$repository->deletePerson($repository->findByFirstName('Jane')[0]);
408+
409+
$person->setWeight(70);
410+
411+
$this->expectException(MissingRecordException::class);
412+
$repository->savePerson($person);
413+
}
414+
415+
public function testDeletingDeletedRecord()
416+
{
417+
$repository = $this->getTestPersonRepository();
418+
419+
$person = $repository->createPerson('Jane', 'Doe', 20);
420+
$repository->savePerson($person);
421+
422+
$repository->deletePerson($repository->findByFirstName('Jane')[0]);
423+
424+
$this->expectException(MissingRecordException::class);
425+
$repository->deletePerson($person);
426+
}
369427
}

tests/helpers/TestCase/UnitTestCase.php

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use PHPUnit\Framework\TestCase;
66
use Simply\Container\Container;
77
use Simply\Database\Schema;
8+
use Simply\Database\StaticSchema;
89
use Simply\Database\Test\TestHouseSchema;
910
use Simply\Database\Test\TestParentSchema;
1011
use Simply\Database\Test\TestPersonSchema;
@@ -32,12 +33,12 @@ protected function getPersonSchema(): TestPersonSchema
3233
protected function getCompositeForeignKeySchema(): Schema
3334
{
3435
$container = new Container();
35-
$schema = new class($container) extends Schema {
36-
protected $model = 'TestModel';
37-
protected $primaryKey = ['order_id', 'product_id'];
38-
protected $fields = ['order_id', 'product_id', 'replaced_order_id', 'replaced_product_id'];
39-
protected $table = 'test';
40-
protected $relationships = [
36+
$schema = new class($container) extends StaticSchema {
37+
protected static $model = 'TestModel';
38+
protected static $primaryKey = ['order_id', 'product_id'];
39+
protected static $fields = ['order_id', 'product_id', 'replaced_order_id', 'replaced_product_id'];
40+
protected static $table = 'test';
41+
protected static $relationships = [
4142
'replacement' => [
4243
'key' => ['order_id', 'product_id'],
4344
'schema' => 'TestSchema',

tests/helpers/TestHouseSchema.php

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,25 @@
22

33
namespace Simply\Database\Test;
44

5-
use Simply\Database\Schema;
5+
use Simply\Database\StaticSchema;
66

77
/**
88
* TestHouseSchema.
99
* @author Riikka Kalliomäki <[email protected]>
1010
* @copyright Copyright (c) 2018 Riikka Kalliomäki
1111
* @license http://opensource.org/licenses/mit-license.php MIT License
1212
*/
13-
class TestHouseSchema extends Schema
13+
class TestHouseSchema extends StaticSchema
1414
{
15-
protected $model = TestHouseModel::class;
15+
protected static $model = TestHouseModel::class;
1616

17-
protected $table = 'phpunit_tests_house';
17+
protected static $table = 'phpunit_tests_house';
1818

19-
protected $primaryKey = 'id';
19+
protected static $primaryKey = 'id';
2020

21-
protected $fields = ['id', 'street'];
21+
protected static $fields = ['id', 'street'];
2222

23-
protected $relationships = [
23+
protected static $relationships = [
2424
'residents' => [
2525
'key' => 'id',
2626
'schema' => TestPersonSchema::class,

0 commit comments

Comments
 (0)