From 95b032891d6617525636cc7b680117dbb14afba7 Mon Sep 17 00:00:00 2001
From: "christophe.boulain" <>
Date: Wed, 19 Jan 2011 14:56:01 +0000
Subject: Merge last changes on "Data" from trunk

---
 .../Relations/TActiveRecordRelation.php            | 508 ++++++++++-----------
 .../Data/ActiveRecord/Scaffold/TScaffoldBase.php   |   3 +-
 framework/Data/ActiveRecord/TActiveRecord.php      |   3 +-
 .../Data/ActiveRecord/TActiveRecordConfig.php      |   2 +-
 .../Data/ActiveRecord/TActiveRecordGateway.php     |   7 +-
 5 files changed, 263 insertions(+), 260 deletions(-)

(limited to 'framework/Data/ActiveRecord')

diff --git a/framework/Data/ActiveRecord/Relations/TActiveRecordRelation.php b/framework/Data/ActiveRecord/Relations/TActiveRecordRelation.php
index 7e584514..b291cbf3 100644
--- a/framework/Data/ActiveRecord/Relations/TActiveRecordRelation.php
+++ b/framework/Data/ActiveRecord/Relations/TActiveRecordRelation.php
@@ -1,254 +1,254 @@
-<?php
-/**
- * TActiveRecordRelation class file.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @link http://www.pradosoft.com/
- * @copyright Copyright &copy; 2005-2008 PradoSoft
- * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Data.ActiveRecord.Relations
- */
-
-/**
- * Load active record relationship context.
- */
-Prado::using('System.Data.ActiveRecord.Relations.TActiveRecordRelationContext');
-
-/**
- * Base class for active record relationships.
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.ActiveRecord.Relations
- * @since 3.1
- */
-abstract class TActiveRecordRelation
-{
-	private $_context;
-	private $_criteria;
-
-	public function __construct(TActiveRecordRelationContext $context, $criteria)
-	{
-		$this->_context = $context;
-		$this->_criteria = $criteria;
-	}
-
-	/**
-	 * @return TActiveRecordRelationContext
-	 */
-	protected function getContext()
-	{
-		return $this->_context;
-	}
-
-	/**
-	 * @return TActiveRecordCriteria
-	 */
-	protected function getCriteria()
-	{
-		return $this->_criteria;
-	}
-
-	/**
-	 * @return TActiveRecord
-	 */
-	protected function getSourceRecord()
-	{
-		return $this->getContext()->getSourceRecord();
-	}
-
-	abstract protected function collectForeignObjects(&$results);
-
-	/**
-	 * Dispatch the method calls to the source record finder object. When
-	 * an instance of TActiveRecord or an array of TActiveRecord is returned
-	 * the corresponding foreign objects are also fetched and assigned.
-	 *
-	 * Multiple relationship calls can be chain together.
-	 *
-	 * @param string method name called
-	 * @param array method arguments
-	 * @return mixed TActiveRecord or array of TActiveRecord results depending on the method called.
-	 */
-	public function __call($method,$args)
-	{
-		static $stack=array();
-
-		$results = call_user_func_array(array($this->getSourceRecord(),$method),$args);
-		$validArray = is_array($results) && count($results) > 0;
-		if($validArray || $results instanceof ArrayAccess || $results instanceof TActiveRecord)
-		{
-			$this->collectForeignObjects($results);
-			while($obj = array_pop($stack))
-				$obj->collectForeignObjects($results);
-		}
-		else if($results instanceof TActiveRecordRelation)
-			$stack[] = $this; //call it later
-		else if($results === null || !$validArray)
-			$stacks=array();
-		return $results;
-	}
-
-	/**
-	 * Fetch results for current relationship.
-	 * @return boolean always true.
-	 */
-	public function fetchResultsInto($obj)
-	{
-		$this->collectForeignObjects($obj);
-		return true;
-	}
-
-	/**
-	 * Returns foreign keys in $fromRecord with source column names as key
-	 * and foreign column names in the corresponding $matchesRecord as value.
-	 * The method returns the first matching foreign key between these 2 records.
-	 * @param TActiveRecord $fromRecord
-	 * @param TActiveRecord $matchesRecord
-	 * @return array foreign keys with source column names as key and foreign column names as value.
-	 */
-	protected function findForeignKeys($from, $matchesRecord, $loose=false)
-	{
-		$gateway = $matchesRecord->getRecordGateway();
-		$recordTableInfo = $gateway->getRecordTableInfo($matchesRecord);
-		$matchingTableName = strtolower($recordTableInfo->getTableName());
-		$matchingFullTableName = strtolower($recordTableInfo->getTableFullName());
-		$tableInfo=$from;
-		if($from instanceof TActiveRecord)
-			$tableInfo = $gateway->getRecordTableInfo($from);
-		//find first non-empty FK
-		foreach($tableInfo->getForeignKeys() as $fkeys)
-		{
-			$fkTable = strtolower($fkeys['table']);
-			if($fkTable===$matchingTableName || $fkTable===$matchingFullTableName)
-			{
-				$hasFkField = !$loose && $this->getContext()->hasFkField();
-				$key = $hasFkField ? $this->getFkFields($fkeys['keys']) : $fkeys['keys'];
-				if(!empty($key))
-					return $key;
-			}
-		}
-
-		//none found
-		$matching = $gateway->getRecordTableInfo($matchesRecord)->getTableFullName();
-		throw new TActiveRecordException('ar_relations_missing_fk',
-			$tableInfo->getTableFullName(), $matching);
-	}
-
-	/**
-	 * @return array foreign key field names as key and object properties as value.
-	 * @since 3.1.2
-	 */
-	abstract public function getRelationForeignKeys();
-
-	/**
-	 * Find matching foreign key fields from the 3rd element of an entry in TActiveRecord::$RELATION.
-	 * Assume field names consist of [\w-] character sets. Prefix to the field names ending with a dot
-	 * are ignored.
-	 */
-	private function getFkFields($fkeys)
-	{
-		$matching = array();
-		preg_match_all('/\s*(\S+\.)?([\w-]+)\s*/', $this->getContext()->getFkField(), $matching);
-		$fields = array();
-		foreach($fkeys as $fkName => $field)
-		{
-			if(in_array($fkName, $matching[2]))
-				$fields[$fkName] = $field;
-		}
-		return $fields;
-	}
-
-	/**
-	 * @param mixed object or array to be hashed
-	 * @param array name of property for hashing the properties.
-	 * @return string object hash using crc32 and serialize.
-	 */
-	protected function getObjectHash($obj, $properties)
-	{
-		$ids=array();
-		foreach($properties as $property)
-			$ids[] = is_object($obj) ? (string)$obj->getColumnValue($property) : (string)$obj[$property];
-		return serialize($ids);
-	}
-
-	/**
-	 * Fetches the foreign objects using TActiveRecord::findAllByIndex()
-	 * @param array field names
-	 * @param array foreign key index values.
-	 * @return TActiveRecord[] foreign objects.
-	 */
-	protected function findForeignObjects($fields, $indexValues)
-	{
-		$finder = $this->getContext()->getForeignRecordFinder();
-		return $finder->findAllByIndex($this->_criteria, $fields, $indexValues);
-	}
-
-	/**
-	 * Obtain the foreign key index values from the results.
-	 * @param array property names
-	 * @param array TActiveRecord results
-	 * @return array foreign key index values.
-	 */
-	protected function getIndexValues($keys, $results)
-	{
-		if(!is_array($results) && !$results instanceof ArrayAccess)
-			$results = array($results);
-		$values=array();
-		foreach($results as $result)
-		{
-			$value = array();
-			foreach($keys as $name)
-				$value[] = $result->getColumnValue($name);
-			$values[] = $value;
-		}
-		return $values;
-	}
-
-	/**
-	 * Populate the results with the foreign objects found.
-	 * @param array source results
-	 * @param array source property names
-	 * @param array foreign objects
-	 * @param array foreign object field names.
-	 */
-	protected function populateResult(&$results,$properties,&$fkObjects,$fields)
-	{
-		$collections=array();
-		foreach($fkObjects as $fkObject)
-			$collections[$this->getObjectHash($fkObject, $fields)][]=$fkObject;
-		$this->setResultCollection($results, $collections, $properties);
-	}
-
-	/**
-	 * Populates the result array with foreign objects (matched using foreign key hashed property values).
-	 * @param array $results
-	 * @param array $collections
-	 * @param array property names
-	 */
-	protected function setResultCollection(&$results, &$collections, $properties)
-	{
-		if(is_array($results) || $results instanceof ArrayAccess)
-		{
-			for($i=0,$k=count($results);$i<$k;$i++)
-				$this->setObjectProperty($results[$i], $properties, $collections);
-		}
-		else
-			$this->setObjectProperty($results, $properties, $collections);
-	}
-
-	/**
-	 * Sets the foreign objects to the given property on the source object.
-	 * @param TActiveRecord source object.
-	 * @param array source properties
-	 * @param array foreign objects.
-	 */
-	protected function setObjectProperty($source, $properties, &$collections)
-	{
-		$hash = $this->getObjectHash($source, $properties);
-		$prop = $this->getContext()->getProperty();
-		$source->$prop=isset($collections[$hash]) ? $collections[$hash] : array();
-	}
-}
-
+<?php
+/**
+ * TActiveRecordRelation class file.
+ *
+ * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2005-2008 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Id$
+ * @package System.Data.ActiveRecord.Relations
+ */
+
+/**
+ * Load active record relationship context.
+ */
+Prado::using('System.Data.ActiveRecord.Relations.TActiveRecordRelationContext');
+
+/**
+ * Base class for active record relationships.
+ *
+ * @author Wei Zhuo <weizho[at]gmail[dot]com>
+ * @version $Id$
+ * @package System.Data.ActiveRecord.Relations
+ * @since 3.1
+ */
+abstract class TActiveRecordRelation
+{
+	private $_context;
+	private $_criteria;
+
+	public function __construct(TActiveRecordRelationContext $context, $criteria)
+	{
+		$this->_context = $context;
+		$this->_criteria = $criteria;
+	}
+
+	/**
+	 * @return TActiveRecordRelationContext
+	 */
+	protected function getContext()
+	{
+		return $this->_context;
+	}
+
+	/**
+	 * @return TActiveRecordCriteria
+	 */
+	protected function getCriteria()
+	{
+		return $this->_criteria;
+	}
+
+	/**
+	 * @return TActiveRecord
+	 */
+	protected function getSourceRecord()
+	{
+		return $this->getContext()->getSourceRecord();
+	}
+
+	abstract protected function collectForeignObjects(&$results);
+
+	/**
+	 * Dispatch the method calls to the source record finder object. When
+	 * an instance of TActiveRecord or an array of TActiveRecord is returned
+	 * the corresponding foreign objects are also fetched and assigned.
+	 *
+	 * Multiple relationship calls can be chain together.
+	 *
+	 * @param string method name called
+	 * @param array method arguments
+	 * @return mixed TActiveRecord or array of TActiveRecord results depending on the method called.
+	 */
+	public function __call($method,$args)
+	{
+		static $stack=array();
+
+		$results = call_user_func_array(array($this->getSourceRecord(),$method),$args);
+		$validArray = is_array($results) && count($results) > 0;
+		if($validArray || $results instanceof ArrayAccess || $results instanceof TActiveRecord)
+		{
+			$this->collectForeignObjects($results);
+			while($obj = array_pop($stack))
+				$obj->collectForeignObjects($results);
+		}
+		else if($results instanceof TActiveRecordRelation)
+			$stack[] = $this; //call it later
+		else if($results === null || !$validArray)
+			$stack = array();
+		return $results;
+	}
+
+	/**
+	 * Fetch results for current relationship.
+	 * @return boolean always true.
+	 */
+	public function fetchResultsInto($obj)
+	{
+		$this->collectForeignObjects($obj);
+		return true;
+	}
+
+	/**
+	 * Returns foreign keys in $fromRecord with source column names as key
+	 * and foreign column names in the corresponding $matchesRecord as value.
+	 * The method returns the first matching foreign key between these 2 records.
+	 * @param TActiveRecord $fromRecord
+	 * @param TActiveRecord $matchesRecord
+	 * @return array foreign keys with source column names as key and foreign column names as value.
+	 */
+	protected function findForeignKeys($from, $matchesRecord, $loose=false)
+	{
+		$gateway = $matchesRecord->getRecordGateway();
+		$recordTableInfo = $gateway->getRecordTableInfo($matchesRecord);
+		$matchingTableName = strtolower($recordTableInfo->getTableName());
+		$matchingFullTableName = strtolower($recordTableInfo->getTableFullName());
+		$tableInfo=$from;
+		if($from instanceof TActiveRecord)
+			$tableInfo = $gateway->getRecordTableInfo($from);
+		//find first non-empty FK
+		foreach($tableInfo->getForeignKeys() as $fkeys)
+		{
+			$fkTable = strtolower($fkeys['table']);
+			if($fkTable===$matchingTableName || $fkTable===$matchingFullTableName)
+			{
+				$hasFkField = !$loose && $this->getContext()->hasFkField();
+				$key = $hasFkField ? $this->getFkFields($fkeys['keys']) : $fkeys['keys'];
+				if(!empty($key))
+					return $key;
+			}
+		}
+
+		//none found
+		$matching = $gateway->getRecordTableInfo($matchesRecord)->getTableFullName();
+		throw new TActiveRecordException('ar_relations_missing_fk',
+			$tableInfo->getTableFullName(), $matching);
+	}
+
+	/**
+	 * @return array foreign key field names as key and object properties as value.
+	 * @since 3.1.2
+	 */
+	abstract public function getRelationForeignKeys();
+
+	/**
+	 * Find matching foreign key fields from the 3rd element of an entry in TActiveRecord::$RELATION.
+	 * Assume field names consist of [\w-] character sets. Prefix to the field names ending with a dot
+	 * are ignored.
+	 */
+	private function getFkFields($fkeys)
+	{
+		$matching = array();
+		preg_match_all('/\s*(\S+\.)?([\w-]+)\s*/', $this->getContext()->getFkField(), $matching);
+		$fields = array();
+		foreach($fkeys as $fkName => $field)
+		{
+			if(in_array($fkName, $matching[2]))
+				$fields[$fkName] = $field;
+		}
+		return $fields;
+	}
+
+	/**
+	 * @param mixed object or array to be hashed
+	 * @param array name of property for hashing the properties.
+	 * @return string object hash using crc32 and serialize.
+	 */
+	protected function getObjectHash($obj, $properties)
+	{
+		$ids=array();
+		foreach($properties as $property)
+			$ids[] = is_object($obj) ? (string)$obj->getColumnValue($property) : (string)$obj[$property];
+		return serialize($ids);
+	}
+
+	/**
+	 * Fetches the foreign objects using TActiveRecord::findAllByIndex()
+	 * @param array field names
+	 * @param array foreign key index values.
+	 * @return TActiveRecord[] foreign objects.
+	 */
+	protected function findForeignObjects($fields, $indexValues)
+	{
+		$finder = $this->getContext()->getForeignRecordFinder();
+		return $finder->findAllByIndex($this->_criteria, $fields, $indexValues);
+	}
+
+	/**
+	 * Obtain the foreign key index values from the results.
+	 * @param array property names
+	 * @param array TActiveRecord results
+	 * @return array foreign key index values.
+	 */
+	protected function getIndexValues($keys, $results)
+	{
+		if(!is_array($results) && !$results instanceof ArrayAccess)
+			$results = array($results);
+		$values=array();
+		foreach($results as $result)
+		{
+			$value = array();
+			foreach($keys as $name)
+				$value[] = $result->getColumnValue($name);
+			$values[] = $value;
+		}
+		return $values;
+	}
+
+	/**
+	 * Populate the results with the foreign objects found.
+	 * @param array source results
+	 * @param array source property names
+	 * @param array foreign objects
+	 * @param array foreign object field names.
+	 */
+	protected function populateResult(&$results,$properties,&$fkObjects,$fields)
+	{
+		$collections=array();
+		foreach($fkObjects as $fkObject)
+			$collections[$this->getObjectHash($fkObject, $fields)][]=$fkObject;
+		$this->setResultCollection($results, $collections, $properties);
+	}
+
+	/**
+	 * Populates the result array with foreign objects (matched using foreign key hashed property values).
+	 * @param array $results
+	 * @param array $collections
+	 * @param array property names
+	 */
+	protected function setResultCollection(&$results, &$collections, $properties)
+	{
+		if(is_array($results) || $results instanceof ArrayAccess)
+		{
+			for($i=0,$k=count($results);$i<$k;$i++)
+				$this->setObjectProperty($results[$i], $properties, $collections);
+		}
+		else
+			$this->setObjectProperty($results, $properties, $collections);
+	}
+
+	/**
+	 * Sets the foreign objects to the given property on the source object.
+	 * @param TActiveRecord source object.
+	 * @param array source properties
+	 * @param array foreign objects.
+	 */
+	protected function setObjectProperty($source, $properties, &$collections)
+	{
+		$hash = $this->getObjectHash($source, $properties);
+		$prop = $this->getContext()->getProperty();
+		$source->$prop=isset($collections[$hash]) ? $collections[$hash] : array();
+	}
+}
+
diff --git a/framework/Data/ActiveRecord/Scaffold/TScaffoldBase.php b/framework/Data/ActiveRecord/Scaffold/TScaffoldBase.php
index 9c548308..b41a593e 100644
--- a/framework/Data/ActiveRecord/Scaffold/TScaffoldBase.php
+++ b/framework/Data/ActiveRecord/Scaffold/TScaffoldBase.php
@@ -4,7 +4,7 @@
  *
  * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
  * @link http://www.pradosoft.com/
- * @copyright Copyright &copy; 2005-2008 PradoSoft
+ * @copyright Copyright &copy; 2005-2008 PradoSoft
  * @license http://www.pradosoft.com/license/
  * @version $Id$
  * @package System.Data.ActiveRecord.Scaffold
@@ -65,6 +65,7 @@ abstract class TScaffoldBase extends TTemplateControl
 	 */
 	protected function getRecordPkValues($record)
 	{
+		$data=array();
 		foreach($this->getTableInfo()->getColumns() as $name=>$column)
 		{
 			if($column->getIsPrimaryKey())
diff --git a/framework/Data/ActiveRecord/TActiveRecord.php b/framework/Data/ActiveRecord/TActiveRecord.php
index af171bbd..34de431b 100644
--- a/framework/Data/ActiveRecord/TActiveRecord.php
+++ b/framework/Data/ActiveRecord/TActiveRecord.php
@@ -4,7 +4,7 @@
  *
  * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
  * @link http://www.pradosoft.com/
- * @copyright Copyright &copy; 2005-2008 PradoSoft
+ * @copyright Copyright &copy; 2005-2010 PradoSoft
  * @license http://www.pradosoft.com/license/
  * @version $Id$
  * @package System.Data.ActiveRecord
@@ -225,6 +225,7 @@ abstract class TActiveRecord extends TComponent
 	 */
 	public function __construct($data=array(), $connection=null)
 	{
+		parent::__construct();
 		if($connection!==null)
 			$this->setDbConnection($connection);
 		$this->setupColumnMapping();
diff --git a/framework/Data/ActiveRecord/TActiveRecordConfig.php b/framework/Data/ActiveRecord/TActiveRecordConfig.php
index fb57fd33..51278fc9 100644
--- a/framework/Data/ActiveRecord/TActiveRecordConfig.php
+++ b/framework/Data/ActiveRecord/TActiveRecordConfig.php
@@ -134,4 +134,4 @@ class TActiveRecordConfig extends TDataSourceConfig
 	{
 		$this->_invalidFinderResult = TPropertyValue::ensureEnum($value, 'TActiveRecordInvalidFinderResult');
 	}
-}
\ No newline at end of file
+}
diff --git a/framework/Data/ActiveRecord/TActiveRecordGateway.php b/framework/Data/ActiveRecord/TActiveRecordGateway.php
index e588b976..534bd253 100644
--- a/framework/Data/ActiveRecord/TActiveRecordGateway.php
+++ b/framework/Data/ActiveRecord/TActiveRecordGateway.php
@@ -4,7 +4,7 @@
  *
  * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
  * @link http://www.pradosoft.com/
- * @copyright Copyright &copy; 2005-2008 PradoSoft
+ * @copyright Copyright &copy; 2005-2010 PradoSoft
  * @license http://www.pradosoft.com/license/
  * @version $Id$
  * @package System.Data.ActiveRecord
@@ -42,6 +42,7 @@ class TActiveRecordGateway extends TComponent
 	 */
 	public function __construct(TActiveRecordManager $manager)
 	{
+		parent::__construct();
 		$this->_manager=$manager;
 	}
 
@@ -306,7 +307,7 @@ class TActiveRecordGateway extends TComponent
 			if($column->getIsExcluded())
 				continue;
 			$value = $record->getColumnValue($name);
-			if(!$column->getAllowNull() && $value===null && !$column->hasSequence() && !$column->getDefaultValue())
+			if(!$column->getAllowNull() && $value===null && !$column->hasSequence() && ($column->getDefaultValue() === TDbTableColumn::UNDEFINED_VALUE))
 			{
 				throw new TActiveRecordException(
 					'ar_value_must_not_be_null', get_class($record),
@@ -342,7 +343,7 @@ class TActiveRecordGateway extends TComponent
 			if($column->getIsExcluded())
 				continue;
 			$value = $record->getColumnValue($name);
-			if(!$column->getAllowNull() && $value===null)
+			if(!$column->getAllowNull() && $value===null && ($column->getDefaultValue() === TDbTableColumn::UNDEFINED_VALUE))
 			{
 				throw new TActiveRecordException(
 					'ar_value_must_not_be_null', get_class($record),
-- 
cgit v1.2.3