1
0
mirror of synced 2024-12-13 14:56:01 +03:00

New component Doctrine_EventListener_AccessorInvoker for automatic invoking of get* and set* methods

This commit is contained in:
zYne 2006-09-12 10:15:58 +00:00
parent 92b7f2a03d
commit e49319f490
6 changed files with 216 additions and 27 deletions

View File

@ -1,4 +1,23 @@
<?php <?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::autoload('Doctrine_EventListener_Interface');
/** /**
* Doctrine_EventListener all event listeners extend this base class * 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 onSave(Doctrine_Record $record) { }
public function onPreSave(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 onInsert(Doctrine_Record $record) { }
public function onPreInsert(Doctrine_Record $record) { } public function onPreInsert(Doctrine_Record $record) { }

View 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;
}
}

View File

@ -1,4 +1,4 @@
<?php <?php
/** /**
* interface for event listening, forces all classes that extend * interface for event listening, forces all classes that extend
* Doctrine_EventListener to have the same method arguments as their parent * 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 onSave(Doctrine_Record $record);
public function onPreSave(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 onInsert(Doctrine_Record $record);
public function onPreInsert(Doctrine_Record $record); public function onPreInsert(Doctrine_Record $record);

View File

@ -533,53 +533,78 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
if( ! isset($this->data[$name])) if( ! isset($this->data[$name]))
throw new InvalidKeyException(); throw new InvalidKeyException();
if($this->data[$name] == self::$null) if($this->data[$name] === self::$null)
return null; return null;
return $this->data[$name]; 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 * get
* returns a value of a property or a related component * returns a value of a property or a related component
* *
* @param $name name of the property or related component * @param mixed $name name of the property or related component
* @throws InvalidKeyException * @param boolean $invoke whether or not to invoke the onGetProperty listener
* @throws Doctrine_Exception
* @return mixed * @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])) { if(isset($this->data[$name])) {
// check if the property is null (= it is the Doctrine_Null object located in self::$null) // check if the property is null (= it is the Doctrine_Null object located in self::$null)
if($this->data[$name] === self::$null) { if($this->data[$name] === self::$null) {
// only load the data from database if the Doctrine_Record is in proxy state $this->load();
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;
}
if($this->data[$name] === self::$null) if($this->data[$name] === self::$null)
return null; $value = null;
}
return $this->data[$name]; } else
$value = $this->data[$name];
} }
if(isset($this->id[$name])) if(isset($this->id[$name]))
return $this->id[$name]; $value = $this->id[$name];
if($name === $this->table->getIdentifier()) 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])) if( ! isset($this->references[$name]))
$this->loadReference($name); $this->loadReference($name);
return $this->references[$name]; return $this->references[$name];
@ -658,9 +683,13 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
$value = $id; $value = $id;
} }
$old = $this->get($name); $old = $this->get($name, false);
if($old !== $value) { if($old !== $value) {
// invoke the onPreSetProperty listener
$value = $this->table->getAttribute(Doctrine::ATTR_LISTENER)->onPreSetProperty($this, $name, $value);
if($value === null) if($value === null)
$value = self::$null; $value = self::$null;

View File

@ -1,5 +1,20 @@
<?php <?php
require_once("UnitTestCase.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 { class Doctrine_EventListenerTestCase extends Doctrine_UnitTestCase {
public function testEvents() { public function testEvents() {
@ -9,7 +24,45 @@ class Doctrine_EventListenerTestCase extends Doctrine_UnitTestCase {
$this->assertTrue($last->getObject() instanceof Doctrine_Connection); $this->assertTrue($last->getObject() instanceof Doctrine_Connection);
$this->assertTrue($last->getCode() == Doctrine_EventListener_Debugger::EVENT_OPEN); $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 prepareData() { }
public function prepareTables() { } public function prepareTables() {
$this->tables = array('EventListenerTest');
parent::prepareTables();
}
} }
?> ?>

View File

@ -32,6 +32,8 @@ error_reporting(E_ALL);
$test = new GroupTest("Doctrine Framework Unit Tests"); $test = new GroupTest("Doctrine Framework Unit Tests");
$test->addTestCase(new Doctrine_EventListenerTestCase());
$test->addTestCase(new Doctrine_RecordTestCase()); $test->addTestCase(new Doctrine_RecordTestCase());
$test->addTestCase(new Doctrine_TableTestCase()); $test->addTestCase(new Doctrine_TableTestCase());
@ -42,8 +44,6 @@ $test->addTestCase(new Doctrine_ManagerTestCase());
$test->addTestCase(new Doctrine_AccessTestCase()); $test->addTestCase(new Doctrine_AccessTestCase());
$test->addTestCase(new Doctrine_EventListenerTestCase());
$test->addTestCase(new Doctrine_BatchIteratorTestCase()); $test->addTestCase(new Doctrine_BatchIteratorTestCase());
$test->addTestCase(new Doctrine_ConfigurableTestCase()); $test->addTestCase(new Doctrine_ConfigurableTestCase());