Skip to content

Commit 7ebe584

Browse files
committed
Implemented Entity::dirty() to mark changes in properties, this will
help at later point to only save those properties that were actually changed
1 parent e3c0867 commit 7ebe584

File tree

3 files changed

+94
-6
lines changed

3 files changed

+94
-6
lines changed

Cake/ORM/Entity.php

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,14 @@ class Entity implements \ArrayAccess, \JsonSerializable {
3939
*/
4040
protected $_className;
4141

42+
/**
43+
* Holds a list of the properties that where modified after that where added or
44+
* modified after this object was originally created.
45+
*
46+
* @var array
47+
*/
48+
protected $_dirty = [];
49+
4250
/**
4351
* Holds a cached list of methods that exist in the instanced class
4452
*
@@ -151,12 +159,21 @@ public function set($property, $value = true, $useSetters = true) {
151159
$useSetters = $value;
152160
}
153161

154-
if (!$useSetters) {
155-
$this->_properties = $property + $this->_properties;
156-
return $this;
157-
}
158-
159162
foreach ($property as $p => $value) {
163+
$markDirty = true;
164+
if (isset($this->_properties[$p])) {
165+
$markDirty = $value !== $this->_properties[$p];
166+
}
167+
168+
if ($markDirty) {
169+
$this->dirty($p, true);
170+
}
171+
172+
if (!$useSetters) {
173+
$this->_properties[$p] = $value;
174+
continue;
175+
}
176+
160177
$setter = 'set' . Inflector::camelize($p);
161178
if ($this->_methodExists($setter)) {
162179
$value = $this->{$setter}($value);
@@ -320,4 +337,29 @@ public function extract(array $properties) {
320337
return $result;
321338
}
322339

340+
/**
341+
* Sets the dirty status of a single property. If called with no second
342+
* argument, it will return whether the property was modified or not
343+
* after the object creation.
344+
*
345+
* @param string $property the field to set or check status for
346+
* @param null|boolean true means the property was changed, false means
347+
* it was not changed and null will make the function return current state
348+
* for that property
349+
* @return boolean whether the property was changed or not
350+
*/
351+
public function dirty($property, $isDirty = null) {
352+
if ($isDirty === null) {
353+
return isset($this->_dirty[$property]);
354+
}
355+
356+
if (!$isDirty) {
357+
unset($this->_dirty[$property]);
358+
return false;
359+
}
360+
361+
$this->_dirty[$property] = true;
362+
return true;
363+
}
364+
323365
}

Cake/Test/TestCase/ORM/EntityTest.php

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,4 +447,49 @@ public function testExtract() {
447447
$expected = ['id' => 1, 'crazyness' => null];
448448
$this->assertEquals($expected, $entity->extract(['id', 'crazyness']));
449449
}
450+
451+
/**
452+
* Tests dirty() method on a newly created object
453+
*
454+
* @return void
455+
*/
456+
public function testDirty() {
457+
$entity = new \Cake\ORM\Entity([
458+
'id' => 1,
459+
'title' => 'Foo',
460+
'author_id' => 3
461+
]);
462+
$this->assertTrue($entity->dirty('id'));
463+
$this->assertTrue($entity->dirty('title'));
464+
$this->assertTrue($entity->dirty('author_id'));
465+
466+
$entity->dirty('id', false);
467+
$this->assertFalse($entity->dirty('id'));
468+
$this->assertTrue($entity->dirty('title'));
469+
$entity->dirty('title', false);
470+
$this->assertFalse($entity->dirty('title'));
471+
}
472+
473+
/**
474+
* Tests dirty() when altering properties values and adding new ones
475+
*
476+
* @return void
477+
*/
478+
public function testDirtyChangingProperties() {
479+
$entity = new \Cake\ORM\Entity([
480+
'title' => 'Foo',
481+
]);
482+
$entity->dirty('title', false);
483+
$this->assertFalse($entity->dirty('title'));
484+
$entity->set('title', 'Foo');
485+
$this->assertFalse($entity->dirty('title'));
486+
$entity->set('title', 'Foo');
487+
$this->assertFalse($entity->dirty('title'));
488+
$entity->set('title', 'Something Else');
489+
$this->assertTrue($entity->dirty('title'));
490+
491+
$entity->set('something', 'else');
492+
$this->assertTrue($entity->dirty('something'));
493+
}
494+
450495
}

Cake/Test/TestCase/ORM/TableTest.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1235,7 +1235,8 @@ public function testAtomicSaveRollbackOnFailure() {
12351235
->will($this->returnValue($query));
12361236

12371237
$statement = $this->getMock('\Cake\Database\Statement\StatementDecorator');
1238-
$statement->expects($this->once())->method('rowCount')->will($this->returnValue(0));
1238+
$statement->expects($this->once())->method('rowCount')
1239+
->will($this->returnValue(0));
12391240
$connection->expects($this->once())->method('begin');
12401241
$connection->expects($this->once())->method('rollback');
12411242
$query->expects($this->once())->method('executeStatement')

0 commit comments

Comments
 (0)