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

Reply via email to