New component Doctrine_EventListener_AccessorInvoker for automatic invoking of get* and set* methods
This commit is contained in:
parent
92b7f2a03d
commit
e49319f490
@ -1,4 +1,23 @@
|
||||
<?php
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.phpdoctrine.com>.
|
||||
*/
|
||||
Doctrine::autoload('Doctrine_EventListener_Interface');
|
||||
/**
|
||||
* Doctrine_EventListener all event listeners extend this base class
|
||||
@ -30,6 +49,13 @@ abstract class Doctrine_EventListener implements Doctrine_EventListener_Interfac
|
||||
public function onSave(Doctrine_Record $record) { }
|
||||
public function onPreSave(Doctrine_Record $record) { }
|
||||
|
||||
public function onGetProperty(Doctrine_Record $record, $property, $value) {
|
||||
return $value;
|
||||
}
|
||||
public function onPreSetProperty(Doctrine_Record $record, $property, $value) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function onInsert(Doctrine_Record $record) { }
|
||||
public function onPreInsert(Doctrine_Record $record) { }
|
||||
|
||||
|
78
Doctrine/EventListener/AccessorInvoker.php
Normal file
78
Doctrine/EventListener/AccessorInvoker.php
Normal file
@ -0,0 +1,78 @@
|
||||
<?php
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.phpdoctrine.com>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Doctrine_EventListener_AccessorInvoker
|
||||
*
|
||||
* @author Konsta Vesterinen
|
||||
* @package Doctrine ORM
|
||||
* @url www.phpdoctrine.com
|
||||
* @license LGPL
|
||||
*/
|
||||
class Doctrine_EventListener_AccessorInvoker extends Doctrine_EventListener {
|
||||
/**
|
||||
* @var boolean $lockGetCall a simple variable to prevent recursion
|
||||
*/
|
||||
private $lockGetCall = false;
|
||||
/**
|
||||
* @var boolean $lockSetCall a simple variable to prevent recursion
|
||||
*/
|
||||
private $lockSetCall = false;
|
||||
/**
|
||||
* onGetProperty
|
||||
*
|
||||
* @param Doctrine_Record $record
|
||||
* @param string $property
|
||||
* @param mixed $value
|
||||
* @return mixed
|
||||
*/
|
||||
public function onGetProperty(Doctrine_Record $record, $property, $value) {
|
||||
$method = 'get' . ucwords($property);
|
||||
|
||||
if (method_exists($record, $method) && ! $this->lockGetCall) {
|
||||
$this->lockGetCall = true;
|
||||
|
||||
$value = $record->$method($value);
|
||||
$this->lockGetCall = false;
|
||||
return $value;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
/**
|
||||
* onPreSetProperty
|
||||
*
|
||||
* @param Doctrine_Record $record
|
||||
* @param string $property
|
||||
* @param mixed $value
|
||||
* @return mixed
|
||||
*/
|
||||
public function onPreSetProperty(Doctrine_Record $record, $property, $value) {
|
||||
$method = 'set' . ucwords($property);
|
||||
|
||||
if (method_exists($record, $method) && ! $this->lockSetCall) {
|
||||
$this->lockSetCall = true;
|
||||
$value = $record->$method($value);
|
||||
$this->lockSetCall = false;
|
||||
return $value;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
<?php
|
||||
<?php
|
||||
/**
|
||||
* interface for event listening, forces all classes that extend
|
||||
* Doctrine_EventListener to have the same method arguments as their parent
|
||||
@ -17,6 +17,9 @@ interface Doctrine_EventListener_Interface {
|
||||
public function onSave(Doctrine_Record $record);
|
||||
public function onPreSave(Doctrine_Record $record);
|
||||
|
||||
public function onGetProperty(Doctrine_Record $record, $property, $value);
|
||||
public function onPreSetProperty(Doctrine_Record $record, $property, $value);
|
||||
|
||||
public function onInsert(Doctrine_Record $record);
|
||||
public function onPreInsert(Doctrine_Record $record);
|
||||
|
||||
|
@ -533,53 +533,78 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
|
||||
if( ! isset($this->data[$name]))
|
||||
throw new InvalidKeyException();
|
||||
|
||||
if($this->data[$name] == self::$null)
|
||||
if($this->data[$name] === self::$null)
|
||||
return null;
|
||||
|
||||
return $this->data[$name];
|
||||
}
|
||||
/**
|
||||
* load
|
||||
* loads all the unitialized properties from the database
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function load() {
|
||||
// only load the data from database if the Doctrine_Record is in proxy state
|
||||
if($this->state == Doctrine_Record::STATE_PROXY) {
|
||||
if( ! empty($this->collections)) {
|
||||
// delegate the loading operation to collections in which this record resides
|
||||
foreach($this->collections as $collection) {
|
||||
$collection->load($this);
|
||||
}
|
||||
} else {
|
||||
$this->refresh();
|
||||
}
|
||||
$this->state = Doctrine_Record::STATE_CLEAN;
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* get
|
||||
* returns a value of a property or a related component
|
||||
*
|
||||
* @param $name name of the property or related component
|
||||
* @throws InvalidKeyException
|
||||
* @param mixed $name name of the property or related component
|
||||
* @param boolean $invoke whether or not to invoke the onGetProperty listener
|
||||
* @throws Doctrine_Exception
|
||||
* @return mixed
|
||||
*/
|
||||
public function get($name) {
|
||||
public function get($name, $invoke = true) {
|
||||
$listener = $this->table->getAttribute(Doctrine::ATTR_LISTENER);
|
||||
|
||||
$value = self::$null;
|
||||
|
||||
if(isset($this->data[$name])) {
|
||||
|
||||
// check if the property is null (= it is the Doctrine_Null object located in self::$null)
|
||||
if($this->data[$name] === self::$null) {
|
||||
|
||||
// only load the data from database if the Doctrine_Record is in proxy state
|
||||
if($this->state == Doctrine_Record::STATE_PROXY) {
|
||||
if( ! empty($this->collections)) {
|
||||
// delegate the loading operation to collections in which this record resides
|
||||
foreach($this->collections as $collection) {
|
||||
$collection->load($this);
|
||||
}
|
||||
} else {
|
||||
$this->refresh();
|
||||
}
|
||||
$this->state = Doctrine_Record::STATE_CLEAN;
|
||||
}
|
||||
$this->load();
|
||||
|
||||
if($this->data[$name] === self::$null)
|
||||
return null;
|
||||
}
|
||||
return $this->data[$name];
|
||||
$value = null;
|
||||
|
||||
} else
|
||||
$value = $this->data[$name];
|
||||
}
|
||||
|
||||
if(isset($this->id[$name]))
|
||||
return $this->id[$name];
|
||||
$value = $this->id[$name];
|
||||
|
||||
if($name === $this->table->getIdentifier())
|
||||
return null;
|
||||
$value = null;
|
||||
|
||||
if($value !== self::$null) {
|
||||
if($invoke) {
|
||||
|
||||
return $this->table->getAttribute(Doctrine::ATTR_LISTENER)->onGetProperty($this, $name, $value);
|
||||
} else
|
||||
return $value;
|
||||
}
|
||||
|
||||
if( ! isset($this->references[$name]))
|
||||
$this->loadReference($name);
|
||||
$this->loadReference($name);
|
||||
|
||||
|
||||
return $this->references[$name];
|
||||
@ -658,9 +683,13 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
|
||||
$value = $id;
|
||||
}
|
||||
|
||||
$old = $this->get($name);
|
||||
$old = $this->get($name, false);
|
||||
|
||||
if($old !== $value) {
|
||||
|
||||
// invoke the onPreSetProperty listener
|
||||
$value = $this->table->getAttribute(Doctrine::ATTR_LISTENER)->onPreSetProperty($this, $name, $value);
|
||||
|
||||
if($value === null)
|
||||
$value = self::$null;
|
||||
|
||||
|
@ -1,5 +1,20 @@
|
||||
<?php
|
||||
require_once("UnitTestCase.php");
|
||||
class EventListenerTest extends Doctrine_Record {
|
||||
public function setTableDefinition() {
|
||||
$this->hasColumn("name", "string", 100);
|
||||
$this->hasColumn("password", "string", 8);
|
||||
}
|
||||
public function setUp() {
|
||||
$this->setAttribute(Doctrine::ATTR_LISTENER, new Doctrine_EventListener_AccessorInvoker());
|
||||
}
|
||||
public function getName($name) {
|
||||
return strtoupper($name);
|
||||
}
|
||||
public function setPassword($password) {
|
||||
return md5($password);
|
||||
}
|
||||
}
|
||||
|
||||
class Doctrine_EventListenerTestCase extends Doctrine_UnitTestCase {
|
||||
public function testEvents() {
|
||||
@ -9,7 +24,45 @@ class Doctrine_EventListenerTestCase extends Doctrine_UnitTestCase {
|
||||
$this->assertTrue($last->getObject() instanceof Doctrine_Connection);
|
||||
$this->assertTrue($last->getCode() == Doctrine_EventListener_Debugger::EVENT_OPEN);
|
||||
}
|
||||
public function testAccessorInvoker() {
|
||||
$e = new EventListenerTest;
|
||||
$e->name = "something";
|
||||
$e->password = "123";
|
||||
|
||||
|
||||
$this->assertEqual($e->get('name'), 'SOMETHING');
|
||||
// test repeated calls
|
||||
$this->assertEqual($e->get('name'), 'SOMETHING');
|
||||
|
||||
$this->assertEqual($e->rawGet('name'), 'something');
|
||||
$this->assertEqual($e->password, '202cb962ac59075b964b07152d234b70');
|
||||
|
||||
$e->save();
|
||||
|
||||
$this->assertEqual($e->name, 'SOMETHING');
|
||||
$this->assertEqual($e->rawGet('name'), 'something');
|
||||
$this->assertEqual($e->password, '202cb962ac59075b964b07152d234b70');
|
||||
|
||||
$this->connection->clear();
|
||||
|
||||
$e->refresh();
|
||||
|
||||
$this->assertEqual($e->name, 'SOMETHING');
|
||||
$this->assertEqual($e->rawGet('name'), 'something');
|
||||
$this->assertEqual($e->password, '202cb962ac59075b964b07152d234b70');
|
||||
|
||||
$this->connection->clear();
|
||||
|
||||
$e = $e->getTable()->find($e->id);
|
||||
|
||||
$this->assertEqual($e->name, 'SOMETHING');
|
||||
$this->assertEqual($e->rawGet('name'), 'something');
|
||||
$this->assertEqual($e->password, '202cb962ac59075b964b07152d234b70');
|
||||
}
|
||||
public function prepareData() { }
|
||||
public function prepareTables() { }
|
||||
public function prepareTables() {
|
||||
$this->tables = array('EventListenerTest');
|
||||
parent::prepareTables();
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
@ -32,6 +32,8 @@ error_reporting(E_ALL);
|
||||
|
||||
$test = new GroupTest("Doctrine Framework Unit Tests");
|
||||
|
||||
$test->addTestCase(new Doctrine_EventListenerTestCase());
|
||||
|
||||
$test->addTestCase(new Doctrine_RecordTestCase());
|
||||
|
||||
$test->addTestCase(new Doctrine_TableTestCase());
|
||||
@ -42,8 +44,6 @@ $test->addTestCase(new Doctrine_ManagerTestCase());
|
||||
|
||||
$test->addTestCase(new Doctrine_AccessTestCase());
|
||||
|
||||
$test->addTestCase(new Doctrine_EventListenerTestCase());
|
||||
|
||||
$test->addTestCase(new Doctrine_BatchIteratorTestCase());
|
||||
|
||||
$test->addTestCase(new Doctrine_ConfigurableTestCase());
|
||||
|
Loading…
Reference in New Issue
Block a user