Author: ts Date: Fri Jan 18 14:40:08 2008 New Revision: 7183 Log: - Started implementing multi-relation support (#10373).
Added: trunk/PersistentObject/src/exceptions/undeterministic_relation.php (with props) trunk/PersistentObject/src/object/relation_collection.php (with props) trunk/PersistentObject/tests/data/multi_relation.dba trunk/PersistentObject/tests/data/multi_relation.sql trunk/PersistentObject/tests/data/multi_relation_test_person.php (with props) trunk/PersistentObject/tests/data/multirelationtestperson.php (with props) trunk/PersistentObject/tests/multi_relation_test.php (with props) Modified: trunk/PersistentObject/design/class_diagram.png trunk/PersistentObject/src/exceptions/relation_not_found.php trunk/PersistentObject/src/handlers/load_handler.php trunk/PersistentObject/src/object/persistent_object_relations.php trunk/PersistentObject/src/persistent_autoload.php trunk/PersistentObject/src/persistent_session.php Modified: trunk/PersistentObject/design/class_diagram.png ============================================================================== Binary files - no diff available. Modified: trunk/PersistentObject/src/exceptions/relation_not_found.php ============================================================================== --- trunk/PersistentObject/src/exceptions/relation_not_found.php [iso-8859-1] (original) +++ trunk/PersistentObject/src/exceptions/relation_not_found.php [iso-8859-1] Fri Jan 18 14:40:08 2008 @@ -25,9 +25,12 @@ * @param string $relatedClass * @return void */ - public function __construct( $class, $relatedClass ) + public function __construct( $class, $relatedClass, $relationName = null ) { - parent::__construct( "Class '{$class}' does not have a relation to '{$relatedClass}'" ); + parent::__construct( + "Class '{$class}' does not have a relation to '{$relatedClass}'" + . ( $relationName !== null ? " with name '$relationName'." : '.' ) + ); } } ?> Added: trunk/PersistentObject/src/exceptions/undeterministic_relation.php ============================================================================== --- trunk/PersistentObject/src/exceptions/undeterministic_relation.php (added) +++ trunk/PersistentObject/src/exceptions/undeterministic_relation.php [iso-8859-1] Fri Jan 18 14:40:08 2008 @@ -1,0 +1,32 @@ +<?php +/** + * File containing the ezcPersistentUndeterministicRelationException class + * + * @package PersistentObject + * @version //autogen// + * @copyright Copyright (C) 2005-2008 eZ systems as. All rights reserved. + * @license http://ez.no/licenses/new_bsd New BSD License + */ + +/** + * Exception thrown, if an operation on a multi-relation class missed the relation name. + * + * @package PersistentObject + * @version //autogen// + */ +class ezcPersistentUndeterministicRelationException extends ezcPersistentObjectException +{ + + /** + * Constructs a new ezcPersistentUndeterministicRelationException for the given + * relation class $class. + * + * @param string $class + * @return void + */ + public function __construct( $class ) + { + parent::__construct( "There are multiple relations defined for class $class, but the neccessary relation name was missing for the desired operation." ); + } +} +?> Propchange: trunk/PersistentObject/src/exceptions/undeterministic_relation.php ------------------------------------------------------------------------------ svn:eol-style = native Modified: trunk/PersistentObject/src/handlers/load_handler.php ============================================================================== --- trunk/PersistentObject/src/handlers/load_handler.php [iso-8859-1] (original) +++ trunk/PersistentObject/src/handlers/load_handler.php [iso-8859-1] Fri Jan 18 14:40:08 2008 @@ -285,17 +285,23 @@ * </ul> * For other relation types [EMAIL PROTECTED] getRelatedObject()} is recommended. * + * If multiple relations are defined for the $relatedClass (using [EMAIL PROTECTED] + * ezcPersistentRelationCollection}), the parameter $relationName becomes + * mandatory to determine which relation definition to use. For normal + * relations, this parameter is silently ignored. + * * @param object $object * @param string $relatedClass + * @param string $relationName * * @return array(int=>object($relatedClass)) * * @throws ezcPersistentRelationNotFoundException * if the given $object does not have a relation to $relatedClass. */ - public function getRelatedObjects( $object, $relatedClass ) - { - $query = $this->createRelationFindQuery( $object, $relatedClass ); + public function getRelatedObjects( $object, $relatedClass, $relationName = null ) + { + $query = $this->createRelationFindQuery( $object, $relatedClass, $relationName ); return $this->find( $query, $relatedClass ); } @@ -323,17 +329,23 @@ * </ul> * For other relation types [EMAIL PROTECTED] getRelatedObjects()} is recommended. * + * If multiple relations are defined for the $relatedClass (using [EMAIL PROTECTED] + * ezcPersistentRelationCollection}), the parameter $relationName becomes + * mandatory to determine which relation definition to use. For normal + * relations, this parameter is silently ignored. + * * @param object $object * @param string $relatedClass + * @param string $relationName * * @return object($relatedClass) * * @throws ezcPersistentRelationNotFoundException * if the given $object does not have a relation to $relatedClass. */ - public function getRelatedObject( $object, $relatedClass ) - { - $query = $this->createRelationFindQuery( $object, $relatedClass ); + public function getRelatedObject( $object, $relatedClass, $relationName = null ) + { + $query = $this->createRelationFindQuery( $object, $relatedClass, $relationName ); // This method only needs to return 1 object $query->limit( 1 ); @@ -393,15 +405,22 @@ * [EMAIL PROTECTED] find()} and the related class name, to retrieve a sub-set of * related objects. * + * If multiple relations exist to the same PHP class (defined using a + * [EMAIL PROTECTED] ezcPersistentRelationCollection}), the optional parameter + * $relationName becomes mandatory to determine the relation to use for + * fetching objects. If the parameter is not submitted, an exception will + * be thrown. For normal relations this parameter will be silently ignored. + * * @param object $object * @param string $relatedClass + * @param string $relationName * * @return ezcDbSelectQuery * * @throws ezcPersistentRelationNotFoundException * if the given $object does not have a relation to $relatedClass. */ - public function createRelationFindQuery( $object, $relatedClass ) + public function createRelationFindQuery( $object, $relatedClass, $relationName = null ) { $class = get_class( $object ); $def = $this->definitionManager->fetchDefinition( $class ); @@ -414,6 +433,25 @@ ); } $relation = $def->relations[$relatedClass]; + + // New multi-relations for a single class + if ( $relation instanceof ezcPersistentRelationCollection ) + { + if ( $relationName === null ) + { + throw new ezcPersistentUndeterministicRelationException( $relatedClass ); + } + if ( !isset( $relation[$relationName] ) ) + { + throw new ezcPersistentRelationNotFoundException( + $class, + $relatedClass, + $relationName + ); + } + $relation = $relation[$relationName]; + } + $query = $this->createFindQuery( $relatedClass ); $objectState = $this->session->getObjectState( $object ); Modified: trunk/PersistentObject/src/object/persistent_object_relations.php ============================================================================== --- trunk/PersistentObject/src/object/persistent_object_relations.php [iso-8859-1] (original) +++ trunk/PersistentObject/src/object/persistent_object_relations.php [iso-8859-1] Fri Jan 18 14:40:08 2008 @@ -46,9 +46,9 @@ */ public function offsetSet( $offset, $value ) { - if ( ( $value instanceof ezcPersistentRelation ) === false ) + if ( !( $value instanceof ezcPersistentRelation ) && !( $value instanceof ezcPersistentRelationCollection ) ) { - throw new ezcBaseValueException( 'value', $value, 'ezcPersistentRelation' ); + throw new ezcBaseValueException( 'value', $value, 'ezcPersistentRelation or ezcPersistentRelationCollection' ); } if ( !is_string( $offset ) || strlen( $offset ) < 1 ) { @@ -68,9 +68,9 @@ { foreach ( $array as $offset => $value ) { - if ( ( $value instanceof ezcPersistentRelation ) === false ) + if ( !( $value instanceof ezcPersistentRelation ) && !( $value instanceof ezcPersistentRelationCollection ) ) { - throw new ezcBaseValueException( 'value', $value, 'ezcPersistentRelation' ); + throw new ezcBaseValueException( 'value', $value, 'ezcPersistentRelation or ezcPersistentRelationCollection' ); } if ( !is_string( $offset ) || strlen( $offset ) < 1 ) { @@ -114,17 +114,17 @@ */ public static function __set_state( array $state ) { - $columns = new ezcPersistentObjectRelations(); + $relations = new ezcPersistentObjectRelations(); if ( isset( $state['columns'] ) && count( $state ) === 1 ) { - $columns->exchangeArray( $state['columns'] ); + $relations->exchangeArray( $state['columns'] ); } else { // Old exported objects. - $columns->exchangeArray( $state ); + $relations->exchangeArray( $state ); } - return $columns; + return $relations; } } Added: trunk/PersistentObject/src/object/relation_collection.php ============================================================================== --- trunk/PersistentObject/src/object/relation_collection.php (added) +++ trunk/PersistentObject/src/object/relation_collection.php [iso-8859-1] Fri Jan 18 14:40:08 2008 @@ -1,0 +1,123 @@ +<?php +/** + * File containing the ezcPersistentRelationCollection class. + * + * @package PersistentObject + * @version //autogentag// + * @copyright Copyright (C) 2005-2008 eZ systems as. All rights reserved. + * @license http://ez.no/licenses/new_bsd New BSD License + */ + +/** + * ezcPersistentRelationCollection class. + * + * @access private + * + * @package PersistentObject + * @version //autogen// + */ +class ezcPersistentRelationCollection extends ArrayObject +{ + /** + * Stores the relation objects. + * + * @var array(ezcPersistentRelation) + */ + private $relations; + + /** + * Create a new instance. + * Implicitly done in constructor of + * + * @return void + */ + public function __construct() + { + $this->relations = array(); + parent::__construct( $this->relations ); + } + + /** + * See SPL interface ArrayAccess. + * + * @param string $offset + * @param ezcPersistentRelation $value + * @return void + */ + public function offsetSet( $offset, $value ) + { + if ( ( $value instanceof ezcPersistentRelation ) === false ) + { + throw new ezcBaseValueException( 'value', $value, 'ezcPersistentRelation' ); + } + if ( !is_string( $offset ) || strlen( $offset ) < 1 ) + { + throw new ezcBaseValueException( 'offset', $offset, 'string, length > 0' ); + } + parent::offsetSet( $offset, $value ); + } + + /** + * See SPL class ArrayObject. + * Performs additional value checks on the array. + * + * @param array(ezcPersistentRelation) $array New relations array. + * @return void + */ + public function exchangeArray( $array ) + { + foreach ( $array as $offset => $value ) + { + if ( ( $value instanceof ezcPersistentRelation ) === false ) + { + throw new ezcBaseValueException( 'value', $value, 'ezcPersistentRelation' ); + } + if ( !is_string( $offset ) || strlen( $offset ) < 1 ) + { + throw new ezcBaseValueException( 'offset', $offset, 'string, length > 0' ); + } + } + parent::exchangeArray( $array ); + } + + /** + * See SPL class ArrayObject. + * Performs check if only 0 is used as a flag. + * + * @param int $flags Must be 0. + * @return void + */ + public function setFlags( $flags ) + { + if ( $flags !== 0 ) + { + throw new ezcBaseValueException( 'flags', $flags, '0' ); + } + } + + /** + * Appending is not supported. + * + * @param mixed $value + * @return void + */ + public function append( $value ) + { + throw new Exception( 'Operation append is not supported by this object.' ); + } + + /** + * Sets the state on deserialization. + * + * @param array $state + * @return ezcPersistentRelationCollection + */ + public static function __set_state( array $state ) + { + $relations = new ezcPersistentRelationCollection(); + $relations->exchangeArray( $state ); + return $relations; + } +} + +?> Propchange: trunk/PersistentObject/src/object/relation_collection.php ------------------------------------------------------------------------------ svn:eol-style = native Modified: trunk/PersistentObject/src/persistent_autoload.php ============================================================================== --- trunk/PersistentObject/src/persistent_autoload.php [iso-8859-1] (original) +++ trunk/PersistentObject/src/persistent_autoload.php [iso-8859-1] Fri Jan 18 14:40:08 2008 @@ -14,15 +14,16 @@ 'ezcPersistentDefinitionMissingIdPropertyException' => 'PersistentObject/exceptions/definition_missing_id_property.php', 'ezcPersistentDefinitionNotFoundException' => 'PersistentObject/exceptions/definition_not_found.php', 'ezcPersistentIdentifierGenerationException' => 'PersistentObject/exceptions/identifier_generation.php', + 'ezcPersistentInvalidObjectStateException' => 'PersistentObject/exceptions/invalid_object_state.php', 'ezcPersistentObjectAlreadyPersistentException' => 'PersistentObject/exceptions/already_persistent.php', 'ezcPersistentObjectNotPersistentException' => 'PersistentObject/exceptions/not_persistent.php', - 'ezcPersistentInvalidObjectStateException' => 'PersistentObject/exceptions/invalid_object_state.php', 'ezcPersistentQueryException' => 'PersistentObject/exceptions/query_exception.php', 'ezcPersistentRelatedObjectNotFoundException' => 'PersistentObject/exceptions/related_object_not_found.php', 'ezcPersistentRelationInvalidException' => 'PersistentObject/exceptions/relation_invalid.php', 'ezcPersistentRelationNotFoundException' => 'PersistentObject/exceptions/relation_not_found.php', 'ezcPersistentRelationOperationNotSupportedException' => 'PersistentObject/exceptions/relation_operation_not_supported.php', 'ezcPersistentSessionNotFoundException' => 'PersistentObject/exceptions/session_not_found.php', + 'ezcPersistentUndeterministicRelationException' => 'PersistentObject/exceptions/undeterministic_relation.php', 'ezcPersistentDefinitionManager' => 'PersistentObject/interfaces/definition_manager.php', 'ezcPersistentIdentifierGenerator' => 'PersistentObject/interfaces/identifier_generator.php', 'ezcPersistentPropertyConverter' => 'PersistentObject/interfaces/property_converter.php', @@ -50,6 +51,7 @@ 'ezcPersistentOneToManyRelation' => 'PersistentObject/relations/one_to_many.php', 'ezcPersistentOneToOneRelation' => 'PersistentObject/relations/one_to_one.php', 'ezcPersistentPropertyDateTimeConverter' => 'PersistentObject/object/property_converters/date.php', + 'ezcPersistentRelationCollection' => 'PersistentObject/object/relation_collection.php', 'ezcPersistentSaveHandler' => 'PersistentObject/handlers/save_handler.php', 'ezcPersistentSequenceGenerator' => 'PersistentObject/generators/sequence_generator.php', 'ezcPersistentSession' => 'PersistentObject/persistent_session.php', 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] Fri Jan 18 14:40:08 2008 @@ -222,17 +222,23 @@ * </ul> * For other relation types [EMAIL PROTECTED] getRelatedObject()} is recommended. * + * If multiple relations are defined for the $relatedClass (using [EMAIL PROTECTED] + * ezcPersistentRelationCollection}), the parameter $relationName becomes + * mandatory to determine which relation definition to use. For normal + * relations, this parameter is silently ignored. + * * @param object $object * @param string $relatedClass + * @param string $relationName * * @return array(int=>object($relatedClass)) * * @throws ezcPersistentRelationNotFoundException * if the given $object does not have a relation to $relatedClass. */ - public function getRelatedObjects( $object, $relatedClass ) - { - return $this->loadHandler->getRelatedObjects( $object, $relatedClass ); + public function getRelatedObjects( $object, $relatedClass, $relationName = null ) + { + return $this->loadHandler->getRelatedObjects( $object, $relatedClass, $relationName ); } /** @@ -259,17 +265,23 @@ * </ul> * For other relation types [EMAIL PROTECTED] getRelatedObjects()} is recommended. * + * If multiple relations are defined for the $relatedClass (using [EMAIL PROTECTED] + * ezcPersistentRelationCollection}), the parameter $relationName becomes + * mandatory to determine which relation definition to use. For normal + * relations, this parameter is silently ignored. + * * @param object $object * @param string $relatedClass + * @param string $relationName * * @return object($relatedClass) * * @throws ezcPersistentRelationNotFoundException * if the given $object does not have a relation to $relatedClass. */ - public function getRelatedObject( $object, $relatedClass ) - { - return $this->loadHandler->getRelatedObject( $object, $relatedClass ); + public function getRelatedObject( $object, $relatedClass, $relationName = null ) + { + return $this->loadHandler->getRelatedObject( $object, $relatedClass, $relationName ); } /** Added: trunk/PersistentObject/tests/data/multi_relation.dba ============================================================================== --- trunk/PersistentObject/tests/data/multi_relation.dba (added) +++ trunk/PersistentObject/tests/data/multi_relation.dba [iso-8859-1] Fri Jan 18 14:40:08 2008 @@ -1,0 +1,108 @@ +<?php return array ( + 0 => + array ( + 'PO_person' => + ezcDbSchemaTable::__set_state(array( + 'fields' => + array ( + 'father' => + ezcDbSchemaField::__set_state(array( + 'type' => 'integer', + 'length' => 0, + 'notNull' => false, + 'default' => NULL, + 'autoIncrement' => false, + 'unsigned' => false, + )), + 'id' => + ezcDbSchemaField::__set_state(array( + 'type' => 'integer', + 'length' => 0, + 'notNull' => true, + 'default' => NULL, + 'autoIncrement' => true, + 'unsigned' => false, + )), + 'mother' => + ezcDbSchemaField::__set_state(array( + 'type' => 'integer', + 'length' => 0, + 'notNull' => false, + 'default' => NULL, + 'autoIncrement' => false, + 'unsigned' => false, + )), + 'name' => + ezcDbSchemaField::__set_state(array( + 'type' => 'text', + 'length' => 100, + 'notNull' => true, + 'default' => NULL, + 'autoIncrement' => false, + 'unsigned' => false, + )), + ), + 'indexes' => + array ( + 'primary' => + ezcDbSchemaIndex::__set_state(array( + 'indexFields' => + array ( + 'id' => + ezcDbSchemaIndexField::__set_state(array( + 'sorting' => NULL, + )), + ), + 'primary' => true, + 'unique' => true, + )), + ), + )), + 'PO_sibling' => + ezcDbSchemaTable::__set_state(array( + 'fields' => + array ( + 'person' => + ezcDbSchemaField::__set_state(array( + 'type' => 'integer', + 'length' => 0, + 'notNull' => true, + 'default' => NULL, + 'autoIncrement' => false, + 'unsigned' => false, + )), + 'sibling' => + ezcDbSchemaField::__set_state(array( + 'type' => 'integer', + 'length' => 0, + 'notNull' => true, + 'default' => NULL, + 'autoIncrement' => false, + 'unsigned' => false, + )), + ), + 'indexes' => + array ( + 'primary' => + ezcDbSchemaIndex::__set_state(array( + 'indexFields' => + array ( + 'person' => + ezcDbSchemaIndexField::__set_state(array( + 'sorting' => NULL, + )), + 'sibling' => + ezcDbSchemaIndexField::__set_state(array( + 'sorting' => NULL, + )), + ), + 'primary' => true, + 'unique' => true, + )), + ), + )), + ), + 1 => + array ( + ), +); ?> Added: trunk/PersistentObject/tests/data/multi_relation.sql ============================================================================== --- trunk/PersistentObject/tests/data/multi_relation.sql (added) +++ trunk/PersistentObject/tests/data/multi_relation.sql [iso-8859-1] Fri Jan 18 14:40:08 2008 @@ -1,0 +1,22 @@ +-- +-- Table structure for table `PO_person` +-- + +CREATE TABLE `PO_person` ( + `id` int(11) NOT NULL auto_increment, + `name` varchar(100) NOT NULL, + `mother` int(11), + `father` int(11), + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + +-- +-- Table structure for table `PO_sibling` +-- + +CREATE TABLE `PO_sibling` ( + `person` int(11) NOT NULL, + `sibling` int(11) NOT NULL, + PRIMARY KEY (`person`,`sibling`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; Added: trunk/PersistentObject/tests/data/multi_relation_test_person.php ============================================================================== --- trunk/PersistentObject/tests/data/multi_relation_test_person.php (added) +++ trunk/PersistentObject/tests/data/multi_relation_test_person.php [iso-8859-1] Fri Jan 18 14:40:08 2008 @@ -1,0 +1,125 @@ +<?php +/** +CREATE TABLE PO_test +( + id integer unsigned not null auto_increment, + type_varchar varchar(20), + type_integer integer, + type_decimal decimal(10,2), + type_text text, + + PRIMARY KEY (id) +) TYPE=InnoDB; + + type_date date, +*/ + +class MultiRelationTestPerson +{ + public $id = null; + public $name = null; + public $mother = null; + public $father = null; + + /** + * Inserts some data to use for testing. + */ + public static function insertData() + { + $db = ezcDbInstance::get(); + $db->exec( "insert into " . $db->quoteIdentifier( "PO_person" ) . " (" + . $db->quoteIdentifier( "name" ) . " ) + VALUES ('Root mother without parents.')" ); + $db->exec( "insert into " . $db->quoteIdentifier( "PO_person" ) . " (" + . $db->quoteIdentifier( "name" ) . " ) + VALUES ('Root father without parents.')" ); + + $db->exec( "insert into " . $db->quoteIdentifier( "PO_person" ) . " (" + . $db->quoteIdentifier( "name" ) . ", " . $db->quoteIdentifier( "mother" ) . ", " + . $db->quoteIdentifier( "father" ) . " ) + VALUES ('First level child.', 1, 2)" ); + $db->exec( "insert into " . $db->quoteIdentifier( "PO_person" ) . " (" + . $db->quoteIdentifier( "name" ) . ", " . $db->quoteIdentifier( "mother" ) . ", " + . $db->quoteIdentifier( "father" ) . " ) + VALUES ('Second first level child.', 1, 2)" ); + $db->exec( "insert into " . $db->quoteIdentifier( "PO_person" ) . " (" + . $db->quoteIdentifier( "name" ) . ", " . $db->quoteIdentifier( "mother" ) . ", " + . $db->quoteIdentifier( "father" ) . " ) + VALUES ('Third first level child.', 1, 2)" ); + + $db->exec( "insert into " . $db->quoteIdentifier( "PO_sibling" ) . " (" + . $db->quoteIdentifier( "person" ) . ", " . $db->quoteIdentifier( "sibling" ) . " ) + VALUES (3, 4)" ); + $db->exec( "insert into " . $db->quoteIdentifier( "PO_sibling" ) . " (" + . $db->quoteIdentifier( "person" ) . ", " . $db->quoteIdentifier( "sibling" ) . " ) + VALUES (3, 5)" ); + $db->exec( "insert into " . $db->quoteIdentifier( "PO_sibling" ) . " (" + . $db->quoteIdentifier( "person" ) . ", " . $db->quoteIdentifier( "sibling" ) . " ) + VALUES (4, 3)" ); + $db->exec( "insert into " . $db->quoteIdentifier( "PO_sibling" ) . " (" + . $db->quoteIdentifier( "person" ) . ", " . $db->quoteIdentifier( "sibling" ) . " ) + VALUES (4, 5)" ); + $db->exec( "insert into " . $db->quoteIdentifier( "PO_sibling" ) . " (" + . $db->quoteIdentifier( "person" ) . ", " . $db->quoteIdentifier( "sibling" ) . " ) + VALUES (5, 3)" ); + $db->exec( "insert into " . $db->quoteIdentifier( "PO_sibling" ) . " (" + . $db->quoteIdentifier( "person" ) . ", " . $db->quoteIdentifier( "sibling" ) . " ) + VALUES (5, 4)" ); + } + + /** + * Saves the schema from database to file. + * + * Use this method if you have changed the definition of the persistent object + * and need to update the file on disk. + */ + public function saveSchema() + { + $db = ezcDbInstance::get(); + $schema = ezcDbSchema::createFromDb( $db ); + $schema->writeToFile( 'array', dirname( __FILE__ ) . '/multi_relation.dba' ); + } + + /** + * Loads the schema from file into the database. + * + * If autoIncrement is set to false a schema with the id field not set to autoincrement is used. + */ + public static function setupTables( $autoIncrement = true ) + { + $db = ezcDbInstance::get(); + $schema = ezcDbSchema::createFromFile( 'array', dirname( __FILE__ ) . '/multi_relation.dba' ); + $schema->writeToDb( $db ); + } + + public static function cleanup() + { + $db = ezcDbInstance::get(); + if ( $db->getName() == "oracle" ) + { + $db->exec( "DROP SEQUENCE " . $db->quoteIdentifier( "PO_person_id_seq" ) ); + } + $db->exec( "DROP TABLE " . $db->quoteIdentifier( "PO_person" ) ); + $db->exec( "DROP TABLE " . $db->quoteIdentifier( "PO_sibling" ) ); + } + + public function setState( array $state ) + { + foreach ( $state as $key => $value ) + { + $this->$key = $value; + } + } + + public function getState() + { + $result = array(); + $result['id'] = $this->id; + $result['name'] = $this->name; + $result['mother'] = $this->mother; + $result['father'] = $this->father; + return $result; + } +} + +?> Propchange: trunk/PersistentObject/tests/data/multi_relation_test_person.php ------------------------------------------------------------------------------ svn:eol-style = native Added: trunk/PersistentObject/tests/data/multirelationtestperson.php ============================================================================== --- trunk/PersistentObject/tests/data/multirelationtestperson.php (added) +++ trunk/PersistentObject/tests/data/multirelationtestperson.php [iso-8859-1] Fri Jan 18 14:40:08 2008 @@ -1,0 +1,88 @@ +<?php +/* + * Holds the definition for MultiRelationTestPerson + * This definition is used by the code manager for + * various tests in the system. + */ + +$def = new ezcPersistentObjectDefinition(); +$def->table = "PO_person"; +$def->class = "MultiRelationTestPerson"; + +$def->idProperty = new ezcPersistentObjectIdProperty; +$def->idProperty->columnName = 'id'; +$def->idProperty->propertyName = 'id'; +$def->idProperty->generator = new ezcPersistentGeneratorDefinition( + 'ezcPersistentSequenceGenerator', + array( 'sequence' => 'PO_person_id_seq' ) +); + +$def->properties['name'] = new ezcPersistentObjectProperty; +$def->properties['name']->columnName = 'name'; +$def->properties['name']->propertyName = 'name'; +$def->properties['name']->propertyType = ezcPersistentObjectProperty::PHP_TYPE_STRING; + +$def->properties['mother'] = new ezcPersistentObjectProperty; +$def->properties['mother']->columnName = 'mother'; +$def->properties['mother']->propertyName = 'mother'; +$def->properties['mother']->propertyType = ezcPersistentObjectProperty::PHP_TYPE_INT; + +$def->properties['father'] = new ezcPersistentObjectProperty; +$def->properties['father']->columnName = 'father'; +$def->properties['father']->propertyName = 'father'; +$def->properties['father']->propertyType = ezcPersistentObjectProperty::PHP_TYPE_INT; + +$relations = new ezcPersistentRelationCollection(); + +// Mother relation + +$relations['mothers_children'] = new ezcPersistentOneToManyRelation( + 'PO_person', + 'PO_person' +); +$relations['mothers_children']->columnMap = array( + new ezcPersistentSingleTableMap( 'id', 'mother' ) +); + +$relations['mother'] = new ezcPersistentManyToOneRelation( + 'PO_person', + 'PO_person' +); +$relations['mother']->columnMap = array( + new ezcPersistentSingleTableMap( 'mother', 'id' ) +); + +// Father relation + +$relations['fathers_children'] = new ezcPersistentOneToManyRelation( + 'PO_person', + 'PO_person' +); +$relations['fathers_children']->columnMap = array( + new ezcPersistentSingleTableMap( 'id', 'father' ) +); + +$relations['father'] = new ezcPersistentManyToOneRelation( + 'PO_person', + 'PO_person' +); +$relations['father']->columnMap = array( + new ezcPersistentSingleTableMap( 'father', 'id' ) +); + +// Sibling relation + +$relations['siblings'] = new ezcPersistentManyToManyRelation( + "PO_person", + "PO_person", + "PO_sibling" +); +$relations['siblings']->columnMap = array( + new ezcPersistentDoubleTableMap( "id", "person", "sibling", "id" ), +); + +$def->relations['MultiRelationTestPerson'] = $relations; + +return $def; + +?> Propchange: trunk/PersistentObject/tests/data/multirelationtestperson.php ------------------------------------------------------------------------------ svn:eol-style = native Added: trunk/PersistentObject/tests/multi_relation_test.php ============================================================================== --- trunk/PersistentObject/tests/multi_relation_test.php (added) +++ trunk/PersistentObject/tests/multi_relation_test.php [iso-8859-1] Fri Jan 18 14:40:08 2008 @@ -1,0 +1,222 @@ +<?php +/** + * @copyright Copyright (C) 2005-2008 eZ systems as. All rights reserved. + * @license http://ez.no/licenses/new_bsd New BSD License + * @version //autogentag// + * @filesource + * @package PersistentObject + * @subpackage Tests + */ + +require_once dirname( __FILE__ ) . "/data/multi_relation_test_person.php"; + +/** + * Tests ezcPersistentManyToManyRelation class. + * + * @package PersistentObject + * @subpackage Tests + */ +class ezcPersistentMultiRelationTest extends ezcTestCase +{ + + private $session; + + public static function suite() + { + return new PHPUnit_Framework_TestSuite( __CLASS__ ); + } + + public function setup() + { + try + { + $this->db = ezcDbInstance::get(); + } + catch ( Exception $e ) + { + $this->markTestSkipped( 'There was no database configured' ); + } + MultiRelationTestPerson::setupTables(); + MultiRelationTestPerson::insertData(); + $this->session = new ezcPersistentSession( + ezcDbInstance::get(), + new ezcPersistentCodeManager( dirname( __FILE__ ) . "/data/" ) + ); + } + + public function teardown() + { + // MultiRelationTestPerson::cleanup(); + } + + public function testLoad() + { + $rootMother = $this->session->load( 'MultiRelationTestPerson', 1 ); + $this->assertEquals( + 'Root mother without parents.', + $rootMother->name, + 'MultiRelationTestPerson with ID 1 not loaded correctly.' + ); + + $rootFather = $this->session->load( 'MultiRelationTestPerson', 2 ); + $this->assertEquals( + 'Root father without parents.', + $rootFather->name, + 'MultiRelationTestPerson with ID 2 not loaded correctly.' + ); + } + + public function testFind() + { + $q = $this->session->createFindQuery( 'MultiRelationTestPerson' ); + $q->where( + $q->expr->gt( + $this->session->database->quoteIdentifier( 'id' ), + $q->bindValue( 2 ) + ), + $q->expr->lt( + $this->session->database->quoteIdentifier( 'id' ), + $q->bindValue( 5 ) + ) + ); + $persons = $this->session->find( $q, 'MultiRelationTestPerson' ); + + $this->assertEquals( + 2, + count( $persons ), + 'MultiRelationTestPerson object not found correctly.' + ); + + $this->assertEquals( + 3, + $persons[0]->id, + 'First MultiRelationTestPerson object not found correctly.' + ); + + $this->assertEquals( + 4, + $persons[1]->id, + 'First MultiRelationTestPerson object not found correctly.' + ); + } + + public function testGetRelatedObjectsFailureWithoutRelationName() + { + $mother = $this->session->load( 'MultiRelationTestPerson', 1 ); + try + { + $this->session->getRelatedObjects( $mother, 'MultiRelationTestPerson' ); + $this->fail( 'Exception not thrown on getRelatedObjects() without relation name.' ); + } + catch ( ezcPersistentUndeterministicRelationException $e ) {} + } + + public function testGetRelatedObjectFailureWithoutRelationName() + { + $mother = $this->session->load( 'MultiRelationTestPerson', 1 ); + try + { + $this->session->getRelatedObject( $mother, 'MultiRelationTestPerson' ); + $this->fail( 'Exception not thrown on getRelatedObjects() without relation name.' ); + } + catch ( ezcPersistentUndeterministicRelationException $e ) {} + } + + public function testGetRelatedObjectsSuccessMotherChild() + { + $mother = $this->session->load( 'MultiRelationTestPerson', 1 ); + $children = $this->session->getRelatedObjects( $mother, 'MultiRelationTestPerson', 'mothers_children' ); + + $this->assertEquals( + 3, + count( $children ), + 'Number of found children incorrect.' + ); + + $this->assertEquals( + 3, + $children[0]->id, + 'First child fetched incorrect.' + ); + + $this->assertEquals( + 4, + $children[1]->id, + 'First child fetched incorrect.' + ); + + $this->assertEquals( + 5, + $children[2]->id, + 'First child fetched incorrect.' + ); + } + + public function testGetRelatedObjectSuccessFatherChild() + { + $father = $this->session->load( 'MultiRelationTestPerson', 2 ); + $children = $this->session->getRelatedObjects( $father, 'MultiRelationTestPerson', 'fathers_children' ); + + $this->assertEquals( + 3, + count( $children ), + 'Number of found children incorrect.' + ); + + $this->assertEquals( + 3, + $children[0]->id, + 'First child fetched incorrect.' + ); + + $this->assertEquals( + 4, + $children[1]->id, + 'First child fetched incorrect.' + ); + + $this->assertEquals( + 5, + $children[2]->id, + 'First child fetched incorrect.' + ); + } + + public function testGetRelatedObjectSuccessChildMother() + { + $child = $this->session->load( 'MultiRelationTestPerson', 3 ); + $mother = $this->session->getRelatedObject( $child, 'MultiRelationTestPerson', 'mother' ); + + $this->assertEquals( + 1, + $mother->id, + 'Mother fetched incorrectly for child 3' + ); + } + + public function testGetRelatedObjectSuccessChildFather() + { + $child = $this->session->load( 'MultiRelationTestPerson', 4 ); + $father = $this->session->getRelatedObject( $child, 'MultiRelationTestPerson', 'father' ); + + $this->assertEquals( + 2, + $father->id, + 'Father fetched incorrectly for MultiRelationTestPerson 4' + ); + } + + public function testGetRelatedObjectsSuccessSiblings() + { + $child = $this->session->load( 'MultiRelationTestPerson', 3 ); + $siblings = $this->session->getRelatedObjects( $child, 'MultiRelationTestPerson', 'siblings' ); + + $this->assertEquals( + 2, + count( $siblings ), + 'Siblings not correctly found for MultiRelationTestPerson 3' + ); + } +} + +?> Propchange: trunk/PersistentObject/tests/multi_relation_test.php ------------------------------------------------------------------------------ svn:eol-style = native -- svn-components mailing list svn-components@lists.ez.no http://lists.ez.no/mailman/listinfo/svn-components