Author: ts Date: Wed Dec 26 14:13:08 2007 New Revision: 7038 Log: - Integrated property conversions on load, save and update.
Added: trunk/PersistentObject/tests/data/persistent_test_object_conversion.php (with props) trunk/PersistentObject/tests/data/persistenttestobjectconversion.php (with props) Modified: trunk/PersistentObject/src/interfaces/property_conversion.php trunk/PersistentObject/src/internal/state_transformer.php trunk/PersistentObject/src/object/persistent_object_property.php trunk/PersistentObject/src/object/property_conversions/date.php trunk/PersistentObject/src/persistent_session.php trunk/PersistentObject/tests/date_time_conversion_test.php trunk/PersistentObject/tests/object_property_test.php trunk/PersistentObject/tests/persistent_session_test.php Modified: trunk/PersistentObject/src/interfaces/property_conversion.php ============================================================================== --- trunk/PersistentObject/src/interfaces/property_conversion.php [iso-8859-1] (original) +++ trunk/PersistentObject/src/interfaces/property_conversion.php [iso-8859-1] Wed Dec 26 14:13:08 2007 @@ -38,6 +38,10 @@ * This method is called right after a column value has been read from the * database, given the $databaseValue. The value returned by this method is * then assigned to the persistent objects property. + * + * For all implementations it should be made sure, that null is accepted + * and handled correctly here, to indicate that the database field + * contained a null value. * * @param mixed $databaseValue Column value. * @return mixed Property value. @@ -50,6 +54,10 @@ * This method is called right before a property value is written to the * database, given the $propertyValue. The value returned by this method is * then written back to the database. + * + * Cases where fields may be left empty (null) should always be considered + * in this method, The default way to handle a null value should be to + * return null again, except if excplicitly desired differently. * * @param mixed $propertyValue Property value. * @return mixed Column value. Modified: trunk/PersistentObject/src/internal/state_transformer.php ============================================================================== --- trunk/PersistentObject/src/internal/state_transformer.php [iso-8859-1] (original) +++ trunk/PersistentObject/src/internal/state_transformer.php [iso-8859-1] Wed Dec 26 14:13:08 2007 @@ -46,7 +46,10 @@ } else { - $result[$def->columns[$key]->propertyName] = $value; + $result[$def->columns[$key]->propertyName] = ( + !is_null( $def->columns[$key]->conversion ) + ? $def->columns[$key]->conversion->fromDatabase( $value ) + : $value ); } } return $result; Modified: trunk/PersistentObject/src/object/persistent_object_property.php ============================================================================== --- trunk/PersistentObject/src/object/persistent_object_property.php [iso-8859-1] (original) +++ trunk/PersistentObject/src/object/persistent_object_property.php [iso-8859-1] Wed Dec 26 14:13:08 2007 @@ -17,12 +17,17 @@ * * @see ezcPersisentObjectDefinition * - * @property string $columnName The name of the database field that stores the - * value. - * @property string $propertyName The name of the PersistentObject property - * that holds the value in the PHP object. - * @property int $propertyType The type of the PHP property. See class - * constants PHP_TYPE_*. + * @property string $columnName + * The name of the database field that stores the value. + * @property string $propertyName + * The name of the PersistentObject property that holds the value in + * the PHP object. + * @property int $propertyType + * The type of the PHP property. See class constants PHP_TYPE_*. + * @property ezcPersistentObjectPropertyConversion|null $conversion + * A conversion object that will automatically perform conversions on + * load and save of a property value. + * * @package PersistentObject * @version //autogen// */ @@ -44,6 +49,7 @@ 'columnName' => null, 'propertyName' => null, 'propertyType' => self::PHP_TYPE_STRING, + 'conversion' => null, ); /** @@ -52,9 +58,8 @@ * Creates a new property definition object from the given values. The * $columnName refers to the name of the database column that, the * $propertyName to the name of the PHP object property it refers to. - * - * The $type defines the type of the resulting PHP property, but is - * currently not taken into account anywhere. + * The $type defines the type of the resulting PHP property, the database + * value will be casted accordingly after load. * * @param string $columnName * @param string $propertyName @@ -62,11 +67,13 @@ */ public function __construct( $columnName = null, $propertyName = null, - $type = self::PHP_TYPE_STRING ) + $type = self::PHP_TYPE_STRING, + $conversion = null ) { $this->columnName = $columnName; $this->propertyName = $propertyName; $this->propertyType = $type; + $this->conversion = $conversion; } /** @@ -88,14 +95,16 @@ { return new ezcPersistentObjectProperty( $array['properties']['columnName'], $array['properties']['propertyName'], - $array['properties']['propertyType'] ); + $array['properties']['propertyType'], + ( isset( $array['properties']['conversion'] ) ? $array['properties']['conversion'] : null ) ); } else { // Old style exports return new ezcPersistentObjectProperty( $array['columnName'], $array['propertyName'], - $array['propertyType'] ); + $array['propertyType'], + ( isset( $array['conversion'] ) ? $array['conversion'] : null ) ); } } @@ -155,6 +164,16 @@ ); } break; + case 'conversion': + if ( !( $propertyValue instanceof ezcPersistentObjectPropertyConversion ) && !is_null( $propertyValue ) ) + { + throw new ezcBaseValueException( + $propertyName, + $propertyValue, + 'ezcPersistentObjectPropertyConversion or null' + ); + } + break; default: throw new ezcBasePropertyNotFoundException( $propertyName ); break; Modified: trunk/PersistentObject/src/object/property_conversions/date.php ============================================================================== --- trunk/PersistentObject/src/object/property_conversions/date.php [iso-8859-1] (original) +++ trunk/PersistentObject/src/object/property_conversions/date.php [iso-8859-1] Wed Dec 26 14:13:08 2007 @@ -19,7 +19,7 @@ * @package PersistentObject * @version //autogen// */ -class ezcPersistentObjectPropertyDateTimeConversion +class ezcPersistentObjectPropertyDateTimeConversion implements ezcPersistentObjectPropertyConversion { /** * Converts unix timestamp to DateTime instance. @@ -32,14 +32,18 @@ * in unix timestamp representation. A corresponding DateTime object is * returned, representing the same date/time value. * - * @param int $databaseValue - * @return DateTime + * @param int|null $databaseValue + * @return DateTime|null * * @throws ezcBaseValueException * if the given $databaseValue is not an integer. */ public function fromDatabase( $databaseValue ) { + if ( $databaseValue === null ) + { + return null; + } if ( !is_int( $databaseValue ) && !is_numeric( $databaseValue ) ) { throw new ezcBaseValueException( 'databaseValue', $databaseValue, 'int' ); @@ -58,20 +62,38 @@ * date/time value represented by it as an integer value in unix timestamp * format. * - * @param DateTime $propertyValue - * @return int + * @param DateTime|null $propertyValue + * @return int|null * * @throws ezcBaseValueException * if the given $propertyValue is not an instance of DateTime. */ public function toDatabase( $propertyValue ) { + if ( $propertyValue === null ) + { + return null; + } if ( !( $propertyValue instanceof DateTime ) ) { throw new ezcBaseValueException( 'propertyValue', $propertyValue, 'DateTime' ); } return $propertyValue->format( 'U' ); } + + /** + * Method for de-serialization after var_export(). + * + * This methid must be implemented to allow proper de-serialization of + * conversion objects, when they are exported using [EMAIL PROTECTED] var_export()}. + * + * @param array $state + * @return ezcPersistentObjectPropertyConversion + */ + public static function __set_state( array $state ) + { + return new ezcPersistentObjectPropertyDateTimeConversion(); + } } ?> Modified: trunk/PersistentObject/src/persistent_session.php ============================================================================== --- trunk/PersistentObject/src/persistent_session.php [iso-8859-1] (original) +++ trunk/PersistentObject/src/persistent_session.php [iso-8859-1] Wed Dec 26 14:13:08 2007 @@ -1181,6 +1181,7 @@ if ( $name == $def->idProperty->propertyName ) { $type = $def->idProperty->propertyType; + $conv = null; } else { @@ -1189,10 +1190,15 @@ continue; } $type = $def->properties[$name]->propertyType; + $conv = $def->properties[$name]->conversion; } if ( !is_null( $value ) ) { + if ( !is_null( $conv ) ) + { + $value = $conv->toDatabase( $value ); + } switch ( $type ) { case ezcPersistentObjectProperty::PHP_TYPE_INT: @@ -1206,6 +1212,8 @@ break; } } + + $typedState[$name] = $value; } return $typedState; Added: trunk/PersistentObject/tests/data/persistent_test_object_conversion.php ============================================================================== --- trunk/PersistentObject/tests/data/persistent_test_object_conversion.php (added) +++ trunk/PersistentObject/tests/data/persistent_test_object_conversion.php [iso-8859-1] Wed Dec 26 14:13:08 2007 @@ -1,0 +1,10 @@ +<?php + +require_once 'persistent_test_object.php'; + +class PersistentTestObjectConversion extends PersistentTestObject +{ + +} + +?> Propchange: trunk/PersistentObject/tests/data/persistent_test_object_conversion.php ------------------------------------------------------------------------------ svn:eol-style = native Added: trunk/PersistentObject/tests/data/persistenttestobjectconversion.php ============================================================================== --- trunk/PersistentObject/tests/data/persistenttestobjectconversion.php (added) +++ trunk/PersistentObject/tests/data/persistenttestobjectconversion.php [iso-8859-1] Wed Dec 26 14:13:08 2007 @@ -1,0 +1,42 @@ +<?php +/* + * Holds the definition for PersistentTestObject + * This definition is used by the code manager for + * various tests in the system. + */ +// build definition +$def = new ezcPersistentObjectDefinition(); +$def->table = "PO_test"; +$def->class = "PersistentTestObjectConversion"; + +$def->idProperty = new ezcPersistentObjectIdProperty; +$def->idProperty->columnName = 'id'; +$def->idProperty->propertyName = 'id'; +$def->idProperty->generator = new ezcPersistentGeneratorDefinition( + 'ezcPersistentSequenceGenerator', + array( 'sequence' => 'PO_test_id_seq' ) +); + +$def->properties['varchar'] = new ezcPersistentObjectProperty; +$def->properties['varchar']->columnName = 'type_varchar'; +$def->properties['varchar']->propertyName = 'varchar'; +$def->properties['varchar']->propertyType = ezcPersistentObjectProperty::PHP_TYPE_STRING; + +$def->properties['integer'] = new ezcPersistentObjectProperty; +$def->properties['integer']->columnName = 'type_integer'; +$def->properties['integer']->propertyName = 'integer'; +$def->properties['integer']->propertyType = ezcPersistentObjectProperty::PHP_TYPE_INT; +$def->properties['integer']->conversion = new ezcPersistentObjectPropertyDateTimeConversion(); + +$def->properties['decimal'] = new ezcPersistentObjectProperty; +$def->properties['decimal']->columnName = 'type_decimal'; +$def->properties['decimal']->propertyName = 'decimal'; +$def->properties['decimal']->propertyType = ezcPersistentObjectProperty::PHP_TYPE_FLOAT;; + +$def->properties['text'] = new ezcPersistentObjectProperty; +$def->properties['text']->columnName = 'type_text'; +$def->properties['text']->propertyName = 'text'; +$def->properties['text']->propertyType = ezcPersistentObjectProperty::PHP_TYPE_STRING;; +return $def; + +?> Propchange: trunk/PersistentObject/tests/data/persistenttestobjectconversion.php ------------------------------------------------------------------------------ svn:eol-style = native Modified: trunk/PersistentObject/tests/date_time_conversion_test.php ============================================================================== --- trunk/PersistentObject/tests/date_time_conversion_test.php [iso-8859-1] (original) +++ trunk/PersistentObject/tests/date_time_conversion_test.php [iso-8859-1] Wed Dec 26 14:13:08 2007 @@ -42,6 +42,11 @@ $conv->fromDatabase( '327535200' ), 'Conversion of positive time stamp as string from database failed.' ); + + $this->assertNull( + $conv->fromDatabase( null ), + 'Conversion of null value failed.' + ); } public function testFromDatabaseFailure() @@ -82,6 +87,11 @@ $conv->toDatabase( new DateTime( '@-1000' ) ), 'Conversion of positive time stamp to database failed.' ); + + $this->assertNull( + $conv->toDatabase( null ), + 'Conversion of null value failed.' + ); } public function testToDatabaseFailure() Modified: trunk/PersistentObject/tests/object_property_test.php ============================================================================== --- trunk/PersistentObject/tests/object_property_test.php [iso-8859-1] (original) +++ trunk/PersistentObject/tests/object_property_test.php [iso-8859-1] Wed Dec 26 14:13:08 2007 @@ -37,6 +37,7 @@ 'columnName' => null, 'propertyName' => null, 'propertyType' => ezcPersistentObjectProperty::PHP_TYPE_STRING, + 'conversion' => null ), 'properties', $property @@ -46,13 +47,15 @@ $property = new ezcPersistentObjectProperty( 'column', 'property', - ezcPersistentObjectProperty::PHP_TYPE_INT + ezcPersistentObjectProperty::PHP_TYPE_INT, + new ezcPersistentObjectPropertyDateTimeConversion() ); $this->assertAttributeEquals( array( 'columnName' => 'column', 'propertyName' => 'property', 'propertyType' => ezcPersistentObjectProperty::PHP_TYPE_INT, + 'conversion' => new ezcPersistentObjectPropertyDateTimeConversion(), ), 'properties', $property @@ -66,7 +69,8 @@ $property = new ezcPersistentObjectProperty( 23, 'foo', - ezcPersistentObjectProperty::PHP_TYPE_INT + ezcPersistentObjectProperty::PHP_TYPE_INT, + new ezcPersistentObjectPropertyDateTimeConversion() ); $this->fail( 'ezcBaseValueException not thrown on invalid value for parameter $columnName.' ); } @@ -76,7 +80,8 @@ $property = new ezcPersistentObjectProperty( 'foo', 23, - ezcPersistentObjectProperty::PHP_TYPE_INT + ezcPersistentObjectProperty::PHP_TYPE_INT, + new ezcPersistentObjectPropertyDateTimeConversion() ); $this->fail( 'ezcBaseValueException not thrown on invalid value for parameter $propertyName.' ); } @@ -86,11 +91,23 @@ $property = new ezcPersistentObjectProperty( 'foo', 'bar', - 'baz' + 'baz', + new ezcPersistentObjectPropertyDateTimeConversion() ); $this->fail( 'ezcBaseValueException not thrown on invalid value of type string for parameter $type.' ); } catch ( ezcBaseValueException $e ) {} + try + { + $property = new ezcPersistentObjectProperty( + 'foo', + 'bar', + 'baz', + 'bam' + ); + $this->fail( 'ezcBaseValueException not thrown on invalid value of type string for parameter $type.' ); + } + catch ( ezcBaseValueException $e ) {} } public function testGetAccessSuccess() @@ -98,7 +115,8 @@ $property = new ezcPersistentObjectProperty( 'column', 'property', - ezcPersistentObjectProperty::PHP_TYPE_INT + ezcPersistentObjectProperty::PHP_TYPE_INT, + new ezcPersistentObjectPropertyDateTimeConversion() ); $this->assertEquals( @@ -113,6 +131,10 @@ ezcPersistentObjectProperty::PHP_TYPE_INT, $property->propertyType ); + $this->assertEquals( + new ezcPersistentObjectPropertyDateTimeConversion(), + $property->conversion + ); } public function testGetAccessFailure() @@ -120,7 +142,8 @@ $property = new ezcPersistentObjectProperty( 'column', 'property', - ezcPersistentObjectProperty::PHP_TYPE_INT + ezcPersistentObjectProperty::PHP_TYPE_INT, + new ezcPersistentObjectPropertyDateTimeConversion() ); try { @@ -139,6 +162,7 @@ $property->columnName = 'column'; $property->propertyName ='property'; $property->propertyType = ezcPersistentObjectProperty::PHP_TYPE_INT; + $property->conversion = new ezcPersistentObjectPropertyDateTimeConversion(); $this->assertEquals( 'column', @@ -151,6 +175,15 @@ $this->assertEquals( ezcPersistentObjectProperty::PHP_TYPE_INT, $property->propertyType + ); + $this->assertEquals( + new ezcPersistentObjectPropertyDateTimeConversion(), + $property->conversion + ); + + $property->conversion = null; + $this->assertNull( + $property->conversion ); } @@ -172,6 +205,11 @@ 'propertyType', array( true, false, 'foo', 23.42, array(), new stdClass() ) ); + $this->assertSetPropertyFails( + $property, + 'conversion', + array( true, false, 'foo', 23.42, array(), new stdClass() ) + ); } public function testIssetAccessSuccess() @@ -188,6 +226,10 @@ $this->assertTrue( isset( $property->propertyType ), 'Property $propertyType seems not to be set.' + ); + $this->assertTrue( + isset( $property->conversion ), + 'Property $conversion seems not to be set.' ); } Modified: trunk/PersistentObject/tests/persistent_session_test.php ============================================================================== --- trunk/PersistentObject/tests/persistent_session_test.php [iso-8859-1] (original) +++ trunk/PersistentObject/tests/persistent_session_test.php [iso-8859-1] Wed Dec 26 14:13:08 2007 @@ -10,6 +10,7 @@ require_once "data/persistent_test_object.php"; require_once "data/persistent_test_object_no_id.php"; +require_once "data/persistent_test_object_conversion.php"; require_once "data/relation_test_address.php"; require_once "data/relation_test_person.php"; @@ -788,6 +789,217 @@ $this->removeTempDir(); } + + public function testConversionOnLoad() + { + $q = $this->session->createFindQuery( 'PersistentTestObjectConversion' ); + $q->where( + $q->expr->eq( + $this->session->database->quoteIdentifier( 'type_varchar' ), + $q->bindValue( 'Germany' ) + ) + ); + $arr = $this->session->find( $q, 'PersistentTestObjectConversion' ); + + $this->assertEquals( + 1, + count( $arr ) + ); + + $this->assertType( + 'DateTime', + $arr[0]->integer + ); + + $this->assertEquals( + '82443000', + $arr[0]->integer->format( 'U' ) + ); + } + + public function testConversionOnSave() + { + $obj = new PersistentTestObjectConversion(); + + $obj->varchar = 'Foo Bar'; + $obj->integer = new DateTime( '@327535200' ); + $obj->decimal = 23.42; + $obj->text = 'Foo Bar Baz'; + + $this->session->save( $obj ); + + $q = $this->session->createFindQuery( 'PersistentTestObjectConversion' ); + $q->where( + $q->expr->eq( + $this->session->database->quoteIdentifier( 'type_varchar' ), + $q->bindValue( 'Foo Bar' ) + ) + ); + $arr = $this->session->find( $q, 'PersistentTestObjectConversion' ); + + $this->assertEquals( + 1, + count( $arr ) + ); + + $this->assertType( + 'DateTime', + $arr[0]->integer + ); + + $this->assertEquals( + '327535200', + $arr[0]->integer->format( 'U' ) + ); + } + + public function testNoConversionOnSave() + { + $obj = new PersistentTestObjectConversion(); + + $obj->varchar = 'Foo Bar'; + // Leave null + // $obj->integer = new DateTime( '@327535200' ); + $obj->decimal = 23.42; + $obj->text = 'Foo Bar Baz'; + + $this->session->save( $obj ); + + $q = $this->session->createFindQuery( 'PersistentTestObjectConversion' ); + $q->where( + $q->expr->eq( + $this->session->database->quoteIdentifier( 'type_varchar' ), + $q->bindValue( 'Foo Bar' ) + ) + ); + $arr = $this->session->find( $q, 'PersistentTestObjectConversion' ); + + $this->assertEquals( + 1, + count( $arr ) + ); + + $this->assertNull( + $arr[0]->integer + ); + } + + public function testConversionOnUpdate() + { + $obj = new PersistentTestObjectConversion(); + + $obj->varchar = 'Foo Bar'; + // Leave null + // $obj->integer = new DateTime( '@327535200' ); + $obj->decimal = 23.42; + $obj->text = 'Foo Bar Baz'; + + $this->session->save( $obj ); + + $q = $this->session->createFindQuery( 'PersistentTestObjectConversion' ); + $q->where( + $q->expr->eq( + $this->session->database->quoteIdentifier( 'type_varchar' ), + $q->bindValue( 'Foo Bar' ) + ) + ); + $arr = $this->session->find( $q, 'PersistentTestObjectConversion' ); + + $this->assertEquals( + 1, + count( $arr ) + ); + + $this->assertNull( + $arr[0]->integer + ); + + $arr[0]->integer = new DateTime( '@327535200' ); + + $this->session->update( $arr[0] ); + + $q = $this->session->createFindQuery( 'PersistentTestObjectConversion' ); + $q->where( + $q->expr->eq( + $this->session->database->quoteIdentifier( 'type_varchar' ), + $q->bindValue( 'Foo Bar' ) + ) + ); + $arr = $this->session->find( $q, 'PersistentTestObjectConversion' ); + + $this->assertEquals( + 1, + count( $arr ) + ); + + $this->assertType( + 'DateTime', + $arr[0]->integer + ); + + $this->assertEquals( + '327535200', + $arr[0]->integer->format( 'U' ) + ); + } + + public function testNoConversionOnUpdate() + { + $obj = new PersistentTestObjectConversion(); + + $obj->varchar = 'Foo Bar'; + $obj->integer = new DateTime( '@327535200' ); + $obj->decimal = 23.42; + $obj->text = 'Foo Bar Baz'; + + $this->session->save( $obj ); + + $q = $this->session->createFindQuery( 'PersistentTestObjectConversion' ); + $q->where( + $q->expr->eq( + $this->session->database->quoteIdentifier( 'type_varchar' ), + $q->bindValue( 'Foo Bar' ) + ) + ); + $arr = $this->session->find( $q, 'PersistentTestObjectConversion' ); + + $this->assertEquals( + 1, + count( $arr ) + ); + + $this->assertType( + 'DateTime', + $arr[0]->integer + ); + + $this->assertEquals( + '327535200', + $arr[0]->integer->format( 'U' ) + ); + + $arr[0]->integer = null; + + $this->session->update( $arr[0] ); + + $q = $this->session->createFindQuery( 'PersistentTestObjectConversion' ); + $q->where( + $q->expr->eq( + $this->session->database->quoteIdentifier( 'type_varchar' ), + $q->bindValue( 'Foo Bar' ) + ) + ); + $arr = $this->session->find( $q, 'PersistentTestObjectConversion' ); + + $this->assertEquals( + 1, + count( $arr ) + ); + + $this->assertNull( + $arr[0]->integer + ); + } } ?> -- svn-components mailing list svn-components@lists.ez.no http://lists.ez.no/mailman/listinfo/svn-components