moving towards transparent persistence.
This commit is contained in:
parent
2aea62a498
commit
9971057076
519
lib/Doctrine.php
519
lib/Doctrine.php
@ -36,70 +36,6 @@
|
||||
*/
|
||||
final class Doctrine
|
||||
{
|
||||
/**
|
||||
* DEPRECATED ATTRIBUTE CONSTANT NAMES AND VALUES
|
||||
*
|
||||
* REMOVE BEFORE 1.0
|
||||
* These were deprecated either because they are not used anymore or because they didn't follow the naming pattern required
|
||||
* by Doctrine attributes
|
||||
*
|
||||
* Attribute names must be ATTR_{ATTR_NAME} and the values must be {ATTR_NAME}_NAME_OF_VALUE
|
||||
*/
|
||||
const LIMIT_ROWS = 1;
|
||||
const LIMIT_RECORDS = 2;
|
||||
const FETCH_IMMEDIATE = 0;
|
||||
const FETCH_BATCH = 1;
|
||||
const FETCH_OFFSET = 3;
|
||||
const FETCH_LAZY_OFFSET = 4;
|
||||
const FETCH_VHOLDER = 1;
|
||||
const FETCH_RECORD = 2;
|
||||
const FETCH_ARRAY = 3;
|
||||
|
||||
/**
|
||||
* VERSION
|
||||
*/
|
||||
const VERSION = '2.0.0';
|
||||
|
||||
/**
|
||||
* ERROR CONSTANTS
|
||||
*/
|
||||
const ERR = -1;
|
||||
const ERR_SYNTAX = -2;
|
||||
const ERR_CONSTRAINT = -3;
|
||||
const ERR_NOT_FOUND = -4;
|
||||
const ERR_ALREADY_EXISTS = -5;
|
||||
const ERR_UNSUPPORTED = -6;
|
||||
const ERR_MISMATCH = -7;
|
||||
const ERR_INVALID = -8;
|
||||
const ERR_NOT_CAPABLE = -9;
|
||||
const ERR_TRUNCATED = -10;
|
||||
const ERR_INVALID_NUMBER = -11;
|
||||
const ERR_INVALID_DATE = -12;
|
||||
const ERR_DIVZERO = -13;
|
||||
const ERR_NODBSELECTED = -14;
|
||||
const ERR_CANNOT_CREATE = -15;
|
||||
const ERR_CANNOT_DELETE = -16;
|
||||
const ERR_CANNOT_DROP = -17;
|
||||
const ERR_NOSUCHTABLE = -18;
|
||||
const ERR_NOSUCHFIELD = -19;
|
||||
const ERR_NEED_MORE_DATA = -20;
|
||||
const ERR_NOT_LOCKED = -21;
|
||||
const ERR_VALUE_COUNT_ON_ROW = -22;
|
||||
const ERR_INVALID_DSN = -23;
|
||||
const ERR_CONNECT_FAILED = -24;
|
||||
const ERR_EXTENSION_NOT_FOUND = -25;
|
||||
const ERR_NOSUCHDB = -26;
|
||||
const ERR_ACCESS_VIOLATION = -27;
|
||||
const ERR_CANNOT_REPLACE = -28;
|
||||
const ERR_CONSTRAINT_NOT_NULL = -29;
|
||||
const ERR_DEADLOCK = -30;
|
||||
const ERR_CANNOT_ALTER = -31;
|
||||
const ERR_MANAGER = -32;
|
||||
const ERR_MANAGER_PARSE = -33;
|
||||
const ERR_LOADMODULE = -34;
|
||||
const ERR_INSUFFICIENT_DATA = -35;
|
||||
const ERR_CLASS_NAME = -36;
|
||||
|
||||
/**
|
||||
* PDO derived constants
|
||||
*/
|
||||
@ -142,14 +78,6 @@ final class Doctrine
|
||||
const PARAM_NULL = 0;
|
||||
const PARAM_STMT = 4;
|
||||
const PARAM_STR = 2;
|
||||
|
||||
/**
|
||||
* ATTRIBUTE CONSTANTS
|
||||
*/
|
||||
|
||||
/**
|
||||
* PDO derived attributes
|
||||
*/
|
||||
const ATTR_AUTOCOMMIT = 0;
|
||||
const ATTR_PREFETCH = 1;
|
||||
const ATTR_TIMEOUT = 2;
|
||||
@ -170,387 +98,6 @@ final class Doctrine
|
||||
const ATTR_STRINGIFY_FETCHES = 17;
|
||||
const ATTR_MAX_COLUMN_LEN = 18;
|
||||
|
||||
/**
|
||||
* Doctrine constants
|
||||
*/
|
||||
const ATTR_LISTENER = 100;
|
||||
const ATTR_QUOTE_IDENTIFIER = 101; // manager/session attribute
|
||||
const ATTR_FIELD_CASE = 102; // manager/session attribute
|
||||
const ATTR_IDXNAME_FORMAT = 103; // manager/session attribute
|
||||
const ATTR_SEQNAME_FORMAT = 104; // manager/session attribute
|
||||
const ATTR_SEQCOL_NAME = 105; // class attribute
|
||||
const ATTR_CMPNAME_FORMAT = 118; // ??
|
||||
const ATTR_DBNAME_FORMAT = 117; // manager/session attribute
|
||||
const ATTR_TBLCLASS_FORMAT = 119; // manager/session attribute
|
||||
const ATTR_TBLNAME_FORMAT = 120; // manager/session attribute
|
||||
const ATTR_EXPORT = 140; // manager/session attribute
|
||||
const ATTR_DECIMAL_PLACES = 141; // manager/session attribute
|
||||
const ATTR_PORTABILITY = 106; // manager/session attribute
|
||||
const ATTR_COLL_KEY = 108; // class attribute
|
||||
const ATTR_QUERY_LIMIT = 109; // manager/session attribute
|
||||
const ATTR_DEFAULT_TABLE_TYPE = 112; // manager/session attribute
|
||||
const ATTR_DEF_TEXT_LENGTH = 113; // manager/session attribute
|
||||
const ATTR_DEF_VARCHAR_LENGTH = 114; // manager/session attribute
|
||||
const ATTR_DEF_TABLESPACE = 115; // manager/session attribute
|
||||
const ATTR_EMULATE_DATABASE = 116; // manager/session attribute
|
||||
const ATTR_USE_NATIVE_ENUM = 117; // manager/session attribute
|
||||
const ATTR_DEFAULT_SEQUENCE = 133; // ??
|
||||
const ATTR_FETCHMODE = 118; // deprecated? might use them again for associations
|
||||
const ATTR_NAME_PREFIX = 121; // ??
|
||||
const ATTR_CREATE_TABLES = 122; // manager/session attribute
|
||||
const ATTR_COLL_LIMIT = 123; // manager/session attribute
|
||||
const ATTR_RESULT_CACHE = 150; // manager/session attribute
|
||||
const ATTR_RESULT_CACHE_LIFESPAN = 151; // manager/session attribute
|
||||
const ATTR_LOAD_REFERENCES = 153; // class attribute
|
||||
const ATTR_RECORD_LISTENER = 154;
|
||||
const ATTR_THROW_EXCEPTIONS = 155; // manager/session attribute
|
||||
const ATTR_DEFAULT_PARAM_NAMESPACE = 156; // ??
|
||||
const ATTR_QUERY_CACHE = 157; // manager/session attribute
|
||||
const ATTR_QUERY_CACHE_LIFESPAN = 158; // manager/session attribute
|
||||
const ATTR_MODEL_LOADING = 161; // manager/session attribute
|
||||
const ATTR_HYDRATE = 163; // ??
|
||||
const ATTR_IDENTIFIER = 164; // ??
|
||||
const ATTR_METADATA_CACHE = 165; // manager/session attribute
|
||||
const ATTR_METADATA_CACHE_LIFESPAN = 166; // manager/session attribute
|
||||
|
||||
/**
|
||||
* QUERY_LIMIT CONSTANTS
|
||||
*/
|
||||
|
||||
/**
|
||||
* QUERY_LIMIT_ROWS
|
||||
*
|
||||
* constant for row limiting
|
||||
*
|
||||
* @see self::ATTR_QUERY_LIMIT
|
||||
*/
|
||||
const QUERY_LIMIT_ROWS = 1;
|
||||
|
||||
/**
|
||||
* constant for record limiting
|
||||
* @see self::ATTR_QUERY_LIMIT
|
||||
*/
|
||||
const QUERY_LIMIT_RECORDS = 2;
|
||||
|
||||
/**
|
||||
* FETCHMODE CONSTANTS
|
||||
*/
|
||||
|
||||
/**
|
||||
* IMMEDIATE FETCHING
|
||||
* mode for immediate fetching
|
||||
* @see self::ATTR_FETCHMODE
|
||||
* @deprecated???
|
||||
*/
|
||||
const FETCHMODE_IMMEDIATE = 0;
|
||||
|
||||
/**
|
||||
* FETCHMODE_BATCH
|
||||
*
|
||||
* mode for batch fetching
|
||||
*
|
||||
* @see self::ATTR_FETCHMODE
|
||||
* @deprecated???
|
||||
*/
|
||||
const FETCHMODE_BATCH = 1;
|
||||
|
||||
/**
|
||||
* FETCHMODE_OFFSET
|
||||
*
|
||||
* mode for offset fetching
|
||||
*
|
||||
* @see self::ATTR_FETCHMODE
|
||||
* @deprecated???
|
||||
*/
|
||||
const FETCHMODE_OFFSET = 3;
|
||||
|
||||
/**
|
||||
* FETCHMODE_LAZY_OFFSET
|
||||
*
|
||||
* mode for lazy offset fetching
|
||||
*
|
||||
* @see self::ATTR_FETCHMODE
|
||||
* @deprecated???
|
||||
*/
|
||||
const FETCHMODE_LAZY_OFFSET = 4;
|
||||
|
||||
/**
|
||||
* FETCHMODE CONSTANTS
|
||||
*/
|
||||
|
||||
/**
|
||||
* FETCHMODE_VHOLDER
|
||||
*
|
||||
* @see self::ATTR_FETCHMODE
|
||||
* @deprecated???
|
||||
*/
|
||||
const FETCHMODE_VHOLDER = 1;
|
||||
|
||||
/**
|
||||
* FETCHMODE_RECORD
|
||||
*
|
||||
* Specifies that the fetch method shall return Doctrine_Entity
|
||||
* objects as the elements of the result set.
|
||||
*
|
||||
* This is the default fetchmode.
|
||||
*
|
||||
* @see self::ATTR_FETCHMODE
|
||||
* @deprecated???
|
||||
*/
|
||||
const FETCHMODE_RECORD = 2;
|
||||
|
||||
/**
|
||||
* FETCHMODE_ARRAY
|
||||
*
|
||||
* @see self::ATTR_FETCHMODE
|
||||
* @deprecated???
|
||||
*/
|
||||
const FETCHMODE_ARRAY = 3;
|
||||
|
||||
/**
|
||||
* PORTABILITY CONSTANTS
|
||||
*/
|
||||
|
||||
/**
|
||||
* PORTABILITY_NONE
|
||||
*
|
||||
* Portability: turn off all portability features.
|
||||
*
|
||||
* @see self::ATTR_PORTABILITY
|
||||
*/
|
||||
const PORTABILITY_NONE = 0;
|
||||
|
||||
/**
|
||||
* PORTABILITY_FIX_CASE
|
||||
*
|
||||
* Portability: convert names of tables and fields to case defined in the
|
||||
* "field_case" option when using the query*(), fetch*() methods.
|
||||
*
|
||||
* @see self::ATTR_PORTABILITY
|
||||
*/
|
||||
const PORTABILITY_FIX_CASE = 1;
|
||||
|
||||
/**
|
||||
* PORTABILITY_RTRIM
|
||||
*
|
||||
* Portability: right trim the data output by query*() and fetch*().
|
||||
*
|
||||
* @see self::ATTR_PORTABILITY
|
||||
*/
|
||||
const PORTABILITY_RTRIM = 2;
|
||||
|
||||
/**
|
||||
* PORTABILITY_DELETE_COUNT
|
||||
*
|
||||
* Portability: force reporting the number of rows deleted.
|
||||
*
|
||||
* @see self::ATTR_PORTABILITY
|
||||
*/
|
||||
const PORTABILITY_DELETE_COUNT = 4;
|
||||
|
||||
/**
|
||||
* PORTABILITY_EMPTY_TO_NULL
|
||||
*
|
||||
* Portability: convert empty values to null strings in data output by
|
||||
* query*() and fetch*().
|
||||
*
|
||||
* @see self::ATTR_PORTABILITY
|
||||
*/
|
||||
const PORTABILITY_EMPTY_TO_NULL = 8;
|
||||
|
||||
/**
|
||||
* PORTABILITY_FIX_ASSOC_FIELD_NAMES
|
||||
*
|
||||
* Portability: removes database/table qualifiers from associative indexes
|
||||
*
|
||||
* @see self::ATTR_PORTABILITY
|
||||
*/
|
||||
const PORTABILITY_FIX_ASSOC_FIELD_NAMES = 16;
|
||||
|
||||
/**
|
||||
* PORTABILITY_EXPR
|
||||
*
|
||||
* Portability: makes Doctrine_Expression throw exception for unportable RDBMS expressions
|
||||
*
|
||||
* @see self::ATTR_PORTABILITY
|
||||
*/
|
||||
const PORTABILITY_EXPR = 32;
|
||||
|
||||
/**
|
||||
* PORTABILITY_ALL
|
||||
*
|
||||
* Portability: turn on all portability features.
|
||||
*
|
||||
* @see self::ATTR_PORTABILITY
|
||||
*/
|
||||
const PORTABILITY_ALL = 63;
|
||||
|
||||
/**
|
||||
* LOCK CONSTANTS
|
||||
*/
|
||||
|
||||
/**
|
||||
* LOCK_OPTIMISTIC
|
||||
*
|
||||
* mode for optimistic locking
|
||||
* @see self::ATTR_LOCK
|
||||
* @deprecated???
|
||||
*/
|
||||
const LOCK_OPTIMISTIC = 0;
|
||||
|
||||
/**
|
||||
* LOCK_PESSIMISTIC
|
||||
*
|
||||
* mode for pessimistic locking
|
||||
*
|
||||
* @see self::ATTR_LOCK
|
||||
* @deprecated???
|
||||
*/
|
||||
const LOCK_PESSIMISTIC = 1;
|
||||
|
||||
/**
|
||||
* EXPORT CONSTANTS
|
||||
*/
|
||||
|
||||
/**
|
||||
* EXPORT_NONE
|
||||
*
|
||||
* @see self::ATTR_EXPORT
|
||||
*/
|
||||
const EXPORT_NONE = 0;
|
||||
|
||||
/**
|
||||
* EXPORT_TABLES
|
||||
*
|
||||
* @see self::ATTR_EXPORT
|
||||
*/
|
||||
const EXPORT_TABLES = 1;
|
||||
|
||||
/**
|
||||
* EXPORT_CONSTRAINTS
|
||||
*
|
||||
* @see self::ATTR_EXPORT
|
||||
*/
|
||||
const EXPORT_CONSTRAINTS = 2;
|
||||
|
||||
/**
|
||||
* EXPORT_PLUGINS
|
||||
*
|
||||
* @see self::ATTR_EXPORT
|
||||
*/
|
||||
const EXPORT_PLUGINS = 4;
|
||||
|
||||
/**
|
||||
* EXPORT_ALL
|
||||
*
|
||||
* @see self::ATTR_EXPORT
|
||||
*/
|
||||
const EXPORT_ALL = 7;
|
||||
|
||||
/**
|
||||
* HYDRATE CONSTANTS
|
||||
*/
|
||||
|
||||
/**
|
||||
* HYDRATE_RECORD
|
||||
*
|
||||
* @see self::ATTR_HYDRATE
|
||||
*/
|
||||
const HYDRATE_RECORD = 2;
|
||||
|
||||
/**
|
||||
* HYDRATE_ARRAY
|
||||
*
|
||||
* @see self::ATTR_HYDRATE
|
||||
*/
|
||||
const HYDRATE_ARRAY = 3;
|
||||
|
||||
/**
|
||||
* HYDRATE_NONE
|
||||
*
|
||||
* @see self::ATTR_HYDRATE
|
||||
*/
|
||||
const HYDRATE_NONE = 4;
|
||||
|
||||
/* new hydration modes. move to Query class when it's time. */
|
||||
const HYDRATE_IDENTITY_OBJECT = 2; // default, auto-adds PKs, produces object graphs
|
||||
const HYDRATE_IDENTITY_ARRAY = 3; // auto-adds PKs, produces array graphs
|
||||
const HYDRATE_SCALAR = 5; // produces flat result list with scalar values
|
||||
const HYDRATE_SINGLE_SCALAR = 6; // produces a single scalar value
|
||||
//const HYDRATE_NONE = 4; // produces a result set as it's returned by the db
|
||||
|
||||
|
||||
/**
|
||||
* VALIDATE CONSTANTS
|
||||
*
|
||||
* @see self::ATTR_VALIDATE
|
||||
*/
|
||||
const VALIDATE_NONE = 0;
|
||||
|
||||
/**
|
||||
* VALIDATE_LENGTHS
|
||||
*
|
||||
* @see self::ATTR_VALIDATE
|
||||
*/
|
||||
const VALIDATE_LENGTHS = 1;
|
||||
|
||||
/**
|
||||
* VALIDATE_TYPES
|
||||
*
|
||||
* @see self::ATTR_VALIDATE
|
||||
*/
|
||||
const VALIDATE_TYPES = 2;
|
||||
|
||||
/**
|
||||
* VALIDATE_CONSTRAINTS
|
||||
*
|
||||
* @see self::ATTR_VALIDATE
|
||||
* Not used? Purpose?
|
||||
*/
|
||||
const VALIDATE_CONSTRAINTS = 4;
|
||||
|
||||
/**
|
||||
* VALIDATE_ALL
|
||||
*
|
||||
* @see self::ATTR_VALIDATE
|
||||
*/
|
||||
const VALIDATE_ALL = 7;
|
||||
|
||||
/**
|
||||
* IDENTIFIER_AUTOINC
|
||||
*
|
||||
* constant for auto_increment identifier
|
||||
*
|
||||
* @see self::ATTR_IDENTIFIER
|
||||
*/
|
||||
const IDENTIFIER_AUTOINC = 1;
|
||||
|
||||
/**
|
||||
* IDENTIFIER_SEQUENCE
|
||||
*
|
||||
* constant for sequence identifier
|
||||
*
|
||||
* @see self::ATTR_IDENTIFIER
|
||||
*/
|
||||
const IDENTIFIER_SEQUENCE = 2;
|
||||
|
||||
/**
|
||||
* IDENTIFIER_NATURAL
|
||||
*
|
||||
* constant for normal identifier
|
||||
*
|
||||
* @see self::ATTR_IDENTIFIER
|
||||
*/
|
||||
const IDENTIFIER_NATURAL = 3;
|
||||
|
||||
/**
|
||||
* IDENTIFIER_COMPOSITE
|
||||
*
|
||||
* constant for composite identifier
|
||||
* @see self::ATTR_IDENTIFIER
|
||||
*/
|
||||
const IDENTIFIER_COMPOSITE = 4;
|
||||
|
||||
/**
|
||||
* MODEL_LOADING_AGGRESSIVE
|
||||
*
|
||||
@ -572,33 +119,6 @@ final class Doctrine
|
||||
*/
|
||||
const MODEL_LOADING_CONSERVATIVE = 2;
|
||||
|
||||
/**
|
||||
* INHERITANCE TYPE CONSTANTS.
|
||||
*/
|
||||
const INHERITANCE_TYPE_NONE = 0;
|
||||
|
||||
/**
|
||||
* Constant for Single Table Inheritance.
|
||||
*
|
||||
* @see http://martinfowler.com/eaaCatalog/singleTableInheritance.html
|
||||
*/
|
||||
const INHERITANCE_TYPE_SINGLE_TABLE = 1;
|
||||
|
||||
/**
|
||||
* Constant for Class Table Inheritance.
|
||||
*
|
||||
* @see http://martinfowler.com/eaaCatalog/classTableInheritance.html
|
||||
*/
|
||||
const INHERITANCE_TYPE_JOINED = 2;
|
||||
|
||||
/**
|
||||
* Constant for Concrete Table Inheritance.
|
||||
*
|
||||
* @see http://martinfowler.com/eaaCatalog/concreteTableInheritance.html
|
||||
*/
|
||||
const INHERITANCE_TYPE_TABLE_PER_CLASS = 3;
|
||||
|
||||
|
||||
/**
|
||||
* Path
|
||||
*
|
||||
@ -614,7 +134,6 @@ final class Doctrine
|
||||
* @var array
|
||||
*/
|
||||
private static $_loadedModelFiles = array();
|
||||
|
||||
private static $_pathModels = array();
|
||||
|
||||
/**
|
||||
@ -1115,44 +634,6 @@ final class Doctrine
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* dump
|
||||
*
|
||||
* dumps a given variable
|
||||
*
|
||||
* @param mixed $var a variable of any type
|
||||
* @param boolean $output whether to output the content
|
||||
* @param string $indent indention string
|
||||
* @return void|string
|
||||
*/
|
||||
public static function dump($var, $output = true, $indent = "")
|
||||
{
|
||||
$ret = array();
|
||||
switch (gettype($var)) {
|
||||
case 'array':
|
||||
$ret[] = 'Array(';
|
||||
$indent .= " ";
|
||||
foreach ($var as $k => $v) {
|
||||
|
||||
$ret[] = $indent . $k . ' : ' . self::dump($v, false, $indent);
|
||||
}
|
||||
$indent = substr($indent,0, -4);
|
||||
$ret[] = $indent . ")";
|
||||
break;
|
||||
case 'object':
|
||||
$ret[] = 'Object(' . get_class($var) . ')';
|
||||
break;
|
||||
default:
|
||||
$ret[] = var_export($var, true);
|
||||
}
|
||||
|
||||
if ($output) {
|
||||
print implode("\n", $ret);
|
||||
}
|
||||
|
||||
return implode("\n", $ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* tableize
|
||||
*
|
||||
|
@ -6,9 +6,10 @@
|
||||
* Usage recommendation:
|
||||
* 1) Use only 1 class loader instance.
|
||||
* 2) Prepend the base paths to your class libraries (including Doctrine's) to your include path.
|
||||
* 3) DO NOT setCheckFileExists(true). Doing so is expensive.
|
||||
* 3) DO NOT setCheckFileExists(true). Doing so is expensive in terms of performance.
|
||||
*
|
||||
* @since 2.0
|
||||
* @author romanb <roman@code-factory.org>
|
||||
*/
|
||||
class Doctrine_Common_ClassLoader
|
||||
{
|
||||
@ -79,12 +80,13 @@ class Doctrine_Common_ClassLoader
|
||||
|
||||
/**
|
||||
* Registers this class loader using spl_autoload_register().
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
spl_autoload_register(array($this, 'loadClass'));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
139
lib/Doctrine/Common/ClassMetadata.php
Normal file
139
lib/Doctrine/Common/ClassMetadata.php
Normal file
@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
#namespace Doctrine\Common;
|
||||
|
||||
/**
|
||||
* The ClassMetadata class represents a generic container for metadata of a class.
|
||||
*
|
||||
* @author robo
|
||||
*/
|
||||
class Doctrine_Common_ClassMetadata
|
||||
{
|
||||
/** The metadata that applies to the class. */
|
||||
protected $_classMetadata = array();
|
||||
/** The metadata that applies to properties of the class. */
|
||||
protected $_fieldMetadata = array();
|
||||
protected $_entityName;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param <type> $className
|
||||
*/
|
||||
public function __construct($className)
|
||||
{
|
||||
$this->_entityName = $className;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds metadata to a property of the class.
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @param array $fieldMetadata
|
||||
*/
|
||||
public function addFieldMetadata($fieldName, array $fieldMetadata)
|
||||
{
|
||||
$this->_fieldMetadata[$fieldName] = array_merge(
|
||||
isset($this->_fieldMetadata[$fieldName]) ? $this->_fieldMetadata[$fieldName] : array(),
|
||||
$fieldMetadata);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param <type> $fieldName
|
||||
* @param <type> $metadata
|
||||
*/
|
||||
public function setFieldMetadata($fieldName, array $metadata)
|
||||
{
|
||||
$this->_fieldMetadata[$fieldName] = $metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param <type> $fieldName
|
||||
* @param <type> $metadataKey
|
||||
* @param <type> $value
|
||||
*/
|
||||
public function setFieldMetadataEntry($fieldName, $metadataKey, $value)
|
||||
{
|
||||
$this->_fieldMetadata[$fieldName][$metadataKey] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets metadata of a property of the class.
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @param string $metadataKey
|
||||
* @return mixed
|
||||
*/
|
||||
public function getFieldMetadata($fieldName)
|
||||
{
|
||||
return $this->_fieldMetadata[$fieldName];
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param <type> $fieldName
|
||||
* @param <type> $metadataKey
|
||||
* @return <type>
|
||||
*/
|
||||
public function getFieldMetadataEntry($fieldName, $metadataKey)
|
||||
{
|
||||
return isset($this->_fieldMetadata[$fieldName][$metadataKey]) ?
|
||||
$this->_fieldMetadata[$fieldName][$metadataKey] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets metadata of the class.
|
||||
*
|
||||
* @param string $metadataKey
|
||||
* @return mixed
|
||||
*/
|
||||
public function getClassMetadata()
|
||||
{
|
||||
return $this->_classMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param <type> $metadataKey
|
||||
*/
|
||||
public function getClassMetadataEntry($metadataKey)
|
||||
{
|
||||
return isset($this->_classMetadata[$metadataKey]) ?
|
||||
$this->_classMetadata[$metadataKey] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds metadata to the class.
|
||||
*
|
||||
* @param array $classMetadata
|
||||
*/
|
||||
public function addClassMetadata(array $classMetadata)
|
||||
{
|
||||
$this->_classMetadata = array_merge($this->_classMetadata, $classMetadata);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param <type> $metadata
|
||||
*/
|
||||
public function setClassMetadata(array $metadata)
|
||||
{
|
||||
$this->_classMetadata = $metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param <type> $metadataKey
|
||||
* @param <type> $value
|
||||
*/
|
||||
public function setClassMetadataEntry($metadataKey, $value)
|
||||
{
|
||||
$this->_classMetadata[$metadataKey] = $value;
|
||||
}
|
||||
}
|
||||
?>
|
59
lib/Doctrine/Common/ClassMetadataFactory.php
Normal file
59
lib/Doctrine/Common/ClassMetadataFactory.php
Normal file
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
#namespace Doctrine\Common;
|
||||
|
||||
/**
|
||||
* Description of ClassMetadataFactory
|
||||
*
|
||||
* @author robo
|
||||
*/
|
||||
class Doctrine_Common_ClassMetadataFactory {
|
||||
|
||||
/** The factory driver. */
|
||||
protected $_driver;
|
||||
/** Map of the already loaded ClassMetadata instances, indexed by class name. */
|
||||
protected $_loadedMetadata = array();
|
||||
|
||||
/**
|
||||
* Creates a new factory instance that uses the given metadata driver implementation.
|
||||
*
|
||||
* @param $driver The metadata driver to use.
|
||||
*/
|
||||
public function __construct($driver)
|
||||
{
|
||||
$this->_driver = $driver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the metadata object for a class.
|
||||
*
|
||||
* @param string $className The name of the class.
|
||||
* @return Doctrine_Metadata
|
||||
*/
|
||||
public function getMetadataFor($className)
|
||||
{
|
||||
if ( ! isset($this->_loadedMetadata[$className])) {
|
||||
$this->_loadMetadata($className);
|
||||
$this->_validateAndCompleteMetadata($className);
|
||||
}
|
||||
return $this->_loadedMetadata[$className];
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the metadata for the given class.
|
||||
*
|
||||
* @param <type> $className
|
||||
* @return <type>
|
||||
*/
|
||||
protected function _loadMetadata($className)
|
||||
{
|
||||
$classMetadata = new Doctrine_Common_ClassMetadata();
|
||||
$this->_driver->loadMetadataForClass($className, $classMetadata);
|
||||
return $classMetadata;
|
||||
}
|
||||
|
||||
/** Template method for subclasses */
|
||||
protected function _validateAndCompleteMetadata($className)
|
||||
{ /*empty*/ }
|
||||
}
|
||||
?>
|
372
lib/Doctrine/Common/Collections/Collection.php
Normal file
372
lib/Doctrine/Common/Collections/Collection.php
Normal file
@ -0,0 +1,372 @@
|
||||
<?php
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
#namespace Doctrine\Common\Collections;
|
||||
|
||||
#use \Countable;
|
||||
#use \IteratorAggregate;
|
||||
#use \Serializable;
|
||||
#use \ArrayAccess;
|
||||
|
||||
/**
|
||||
* A Collection is a wrapper around a php array and just like a php array a
|
||||
* collection instance can be a list, a map or a hashmap, depending on how it
|
||||
* is used.
|
||||
*
|
||||
* @author robo
|
||||
*/
|
||||
class Doctrine_Common_Collection implements Countable, IteratorAggregate, Serializable, ArrayAccess {
|
||||
/**
|
||||
* An array containing the entries of this collection.
|
||||
* This is the wrapped php array.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_data = array();
|
||||
|
||||
/**
|
||||
* Unwraps the array contained in the Collection instance.
|
||||
*
|
||||
* @return array The wrapped array.
|
||||
*/
|
||||
public function unwrap()
|
||||
{
|
||||
return $this->_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the first record in the collection
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getFirst()
|
||||
{
|
||||
return reset($this->_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the last record in the collection
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getLast()
|
||||
{
|
||||
return end($this->_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the last record in the collection
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function end()
|
||||
{
|
||||
return end($this->_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the current key
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function key()
|
||||
{
|
||||
return key($this->_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an entry from the collection.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @return boolean
|
||||
*/
|
||||
public function remove($key)
|
||||
{
|
||||
$removed = $this->_data[$key];
|
||||
unset($this->_data[$key]);
|
||||
return $removed;
|
||||
}
|
||||
|
||||
/**
|
||||
* __isset()
|
||||
*
|
||||
* @param string $name
|
||||
* @return boolean whether or not this object contains $name
|
||||
*/
|
||||
public function __isset($key)
|
||||
{
|
||||
return $this->containsKey($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* __unset()
|
||||
*
|
||||
* @param string $name
|
||||
* @since 1.0
|
||||
* @return mixed
|
||||
*/
|
||||
public function __unset($key)
|
||||
{
|
||||
return $this->remove($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an offsetExists.
|
||||
*
|
||||
* Part of the ArrayAccess implementation.
|
||||
*
|
||||
* @param mixed $offset
|
||||
* @return boolean whether or not this object contains $offset
|
||||
*/
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
return $this->containsKey($offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* offsetGet an alias of get()
|
||||
*
|
||||
* Part of the ArrayAccess implementation.
|
||||
*
|
||||
* @see get, __get
|
||||
* @param mixed $offset
|
||||
* @return mixed
|
||||
*/
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
return $this->get($offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the ArrayAccess implementation.
|
||||
*
|
||||
* sets $offset to $value
|
||||
* @see set, __set
|
||||
* @param mixed $offset
|
||||
* @param mixed $value
|
||||
* @return void
|
||||
*/
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
if ( ! isset($offset)) {
|
||||
return $this->add($value);
|
||||
}
|
||||
return $this->set($offset, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the ArrayAccess implementation.
|
||||
*
|
||||
* unset a given offset
|
||||
* @see set, offsetSet, __set
|
||||
* @param mixed $offset
|
||||
*/
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
return $this->remove($offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the collection contains an entity.
|
||||
*
|
||||
* @param mixed $key the key of the element
|
||||
* @return boolean
|
||||
*/
|
||||
public function containsKey($key)
|
||||
{
|
||||
return isset($this->_data[$key]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enter description here...
|
||||
*
|
||||
* @param unknown_type $entity
|
||||
* @return unknown
|
||||
*/
|
||||
public function contains($entity)
|
||||
{
|
||||
return in_array($entity, $this->_data, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enter description here...
|
||||
*
|
||||
* @param unknown_type $otherColl
|
||||
* @todo Impl
|
||||
*/
|
||||
public function containsAll($otherColl)
|
||||
{
|
||||
//...
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function search(Doctrine_ORM_Entity $record)
|
||||
{
|
||||
return array_search($record, $this->_data, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a record for given key
|
||||
*
|
||||
* Collection also maps referential information to newly created records
|
||||
*
|
||||
* @param mixed $key the key of the element
|
||||
* @return Doctrine_Entity return a specified record
|
||||
*/
|
||||
public function get($key)
|
||||
{
|
||||
if (isset($this->_data[$key])) {
|
||||
return $this->_data[$key];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all keys.
|
||||
* (Map method)
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getKeys()
|
||||
{
|
||||
return array_keys($this->_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all values.
|
||||
* (Map method)
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getValues()
|
||||
{
|
||||
return array_values($this->_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of records in this collection.
|
||||
*
|
||||
* Implementation of the Countable interface.
|
||||
*
|
||||
* @return integer The number of records in the collection.
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
return count($this->_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* When the collection is a Map this is like put(key,value)/add(key,value).
|
||||
* When the collection is a List this is like add(position,value).
|
||||
*
|
||||
* @param integer $key
|
||||
* @param mixed $value
|
||||
* @return void
|
||||
*/
|
||||
public function set($key, $value)
|
||||
{
|
||||
if ( ! $value instanceof Doctrine_ORM_Entity) {
|
||||
throw new Doctrine_Collection_Exception('Value variable in set is not an instance of Doctrine_Entity');
|
||||
}
|
||||
$this->_data[$key] = $value;
|
||||
//TODO: Register collection as dirty with the UoW if necessary
|
||||
$this->_changed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an entry to the collection.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @param string $key
|
||||
* @return boolean
|
||||
*/
|
||||
public function add($value, $key = null)
|
||||
{
|
||||
//TODO: really only allow entities?
|
||||
if ( ! $value instanceof Doctrine_ORM_Entity) {
|
||||
throw new Doctrine_Record_Exception('Value variable in collection is not an instance of Doctrine_Entity.');
|
||||
}
|
||||
|
||||
// TODO: Really prohibit duplicates?
|
||||
if (in_array($value, $this->_data, true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isset($key)) {
|
||||
if (isset($this->_data[$key])) {
|
||||
return false;
|
||||
}
|
||||
$this->_data[$key] = $value;
|
||||
} else {
|
||||
$this->_data[] = $value;
|
||||
}
|
||||
|
||||
if ($this->_hydrationFlag) {
|
||||
if ($this->_backRefFieldName) {
|
||||
// set back reference to owner
|
||||
$value->_internalSetReference($this->_backRefFieldName, $this->_owner);
|
||||
}
|
||||
} else {
|
||||
//TODO: Register collection as dirty with the UoW if necessary
|
||||
$this->_changed();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds all entities of the other collection to this collection.
|
||||
*
|
||||
* @param unknown_type $otherCollection
|
||||
* @todo Impl
|
||||
*/
|
||||
public function addAll($otherCollection)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the collection is empty.
|
||||
*
|
||||
* @return boolean TRUE if the collection is empty, FALSE otherwise.
|
||||
*/
|
||||
public function isEmpty()
|
||||
{
|
||||
// Note: Little "trick". Empty arrays evaluate to FALSE. No need to count().
|
||||
return ! (bool)$this->_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* getIterator
|
||||
*
|
||||
* @return object ArrayIterator
|
||||
*/
|
||||
public function getIterator()
|
||||
{
|
||||
$data = $this->_data;
|
||||
return new ArrayIterator($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a string representation of this object
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return Doctrine_Lib::getCollectionAsString($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the collection.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
$this->_data = array();
|
||||
}
|
||||
}
|
||||
?>
|
@ -140,7 +140,7 @@ class Doctrine_Common_Configuration
|
||||
public function setTypeOverrides(array $overrides)
|
||||
{
|
||||
foreach ($override as $name => $typeClassName) {
|
||||
Doctrine_DataType::overrideType($name, $typeClassName);
|
||||
Doctrine_DBAL_Types_Type::overrideType($name, $typeClassName);
|
||||
}
|
||||
}
|
||||
}
|
@ -92,11 +92,7 @@ class Doctrine_Common_EventManager
|
||||
public function addEventListener($events, $listener)
|
||||
{
|
||||
// TODO: maybe check for duplicate registrations?
|
||||
if ( ! is_array($events)) {
|
||||
$events = array($events);
|
||||
}
|
||||
|
||||
foreach ($events as $event) {
|
||||
foreach ((array)$events as $event) {
|
||||
$this->_listeners[$event] = $listener;
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@
|
||||
#namespace Doctrine::Common;
|
||||
|
||||
/**
|
||||
* An EventSubscriber knows itself what events it is interested in.
|
||||
* An EventSubscriber knows himself what events he is interested in.
|
||||
* If an EventSubscriber is added to an EventManager, the manager invokes
|
||||
* getSubscribedEvents() and registers the subscriber as a listener for all
|
||||
* returned events.
|
||||
|
@ -39,7 +39,6 @@ class Doctrine_Common_Events_Event
|
||||
const postDelete = 'postDelete';
|
||||
//...more
|
||||
|
||||
|
||||
protected $_type;
|
||||
protected $_target;
|
||||
protected $_defaultPrevented;
|
||||
|
@ -17,7 +17,7 @@ class Doctrine_Common_Exceptions_DoctrineException extends Exception
|
||||
|
||||
public static function notImplemented($method, $class)
|
||||
{
|
||||
return new self("The method '$method' is not implemented in the class '$class'.");
|
||||
return new self("The method '$method' is not implemented in class '$class'.");
|
||||
}
|
||||
}
|
||||
|
||||
|
260
lib/Doctrine/Common/VirtualPropertyObject.php
Normal file
260
lib/Doctrine/Common/VirtualPropertyObject.php
Normal file
@ -0,0 +1,260 @@
|
||||
<?php
|
||||
|
||||
#namespace Doctrine\Common;
|
||||
|
||||
#use \ArrayAccess;
|
||||
|
||||
/**
|
||||
* Base class for classes that use the virtual property system.
|
||||
*
|
||||
* @author robo
|
||||
*/
|
||||
class Doctrine_Common_VirtualPropertyObject implements ArrayAccess
|
||||
{
|
||||
protected $_data = array();
|
||||
protected $_entityName;
|
||||
|
||||
/**
|
||||
* Initializes a new instance of a class derived from VirtualPropertyObject.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->_entityName = get_class($this);
|
||||
if ( ! Doctrine_Common_VirtualPropertySystem::isInitialized($this->_entityName)) {
|
||||
Doctrine_Common_VirtualPropertySystem::initialize($this->_entityName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic getter for virtual properties.
|
||||
*
|
||||
* @param string $fieldName Name of the field.
|
||||
* @return mixed
|
||||
*/
|
||||
final public function get($fieldName)
|
||||
{
|
||||
if ( ! Doctrine_Common_VirtualPropertySystem::hasProperty($this->_entityName, $fieldName)) {
|
||||
throw new Doctrine_Exception("Access of undefined property '$fieldName'.");
|
||||
}
|
||||
$getter = $this->_getCustomAccessor($fieldName);
|
||||
if ($getter) {
|
||||
return $this->$getter();
|
||||
}
|
||||
return $this->_get($fieldName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic setter for virtual properties.
|
||||
*
|
||||
* @param string $name The name of the field to set.
|
||||
* @param mixed $value The value of the field.
|
||||
*/
|
||||
final public function set($fieldName, $value)
|
||||
{
|
||||
if ( ! Doctrine_Common_VirtualPropertySystem::hasProperty($this->_entityName, $fieldName)) {
|
||||
throw new Doctrine_Exception("Access of undefined property '$fieldName'.");
|
||||
}
|
||||
if (Doctrine_Common_VirtualPropertySystem::isTypeCheckEnabled()) {
|
||||
$this->_checkType($fieldName, $value);
|
||||
}
|
||||
$setter = $this->_getCustomMutator($fieldName);
|
||||
if ($setter) {
|
||||
return $this->$setter($value);
|
||||
}
|
||||
$this->_set($fieldName, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the type of a virtual property.
|
||||
*
|
||||
* @param <type> $fieldName
|
||||
* @param <type> $value
|
||||
*/
|
||||
protected function _checkType($fieldName, $value)
|
||||
{
|
||||
$type = Doctrine_Common_VirtualPropertySystem::getType($this->_entityName, $fieldName);
|
||||
if (Doctrine_Common_VirtualPropertySystem::isSimplePHPType($type)) {
|
||||
$is_type = "is_$type";
|
||||
if ( ! $is_type($value)) {
|
||||
throw new Doctrine_Exception("'$value' is of an invalid type. Expected: $type.");
|
||||
}
|
||||
} else if ($type == 'array') {
|
||||
if ( ! is_array($value)) {
|
||||
throw new Doctrine_Exception("'$value' is of an invalid type. Expected: array.");
|
||||
}
|
||||
} else {
|
||||
if ( ! $value instanceof $type) {
|
||||
throw new Doctrine_Exception("'$value' is of an invalid type. Expected: $type.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function _get($fieldName)
|
||||
{
|
||||
return isset($this->_data[$fieldName]) ? $this->_data[$fieldName] : null;
|
||||
}
|
||||
|
||||
protected function _set($fieldName, $value)
|
||||
{
|
||||
$this->_data[$fieldName] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the custom mutator method for a virtual property, if it exists.
|
||||
*
|
||||
* @param string $fieldName The field name.
|
||||
* @return mixed The name of the custom mutator or FALSE, if the field does
|
||||
* not have a custom mutator.
|
||||
*/
|
||||
private function _getCustomMutator($fieldName)
|
||||
{
|
||||
if (Doctrine_Common_VirtualPropertySystem::getMutator($this->_entityName, $fieldName) === null) {
|
||||
if (Doctrine_Common_VirtualPropertySystem::isAutoAccessorOverride()) {
|
||||
$setterMethod = 'set' . Doctrine::classify($fieldName);
|
||||
if ( ! method_exists($this, $setterMethod)) {
|
||||
$setterMethod = false;
|
||||
}
|
||||
Doctrine_Common_VirtualPropertySystem::setMutator(
|
||||
$this->_entityName, $fieldName, $setterMethod);
|
||||
} else {
|
||||
Doctrine_Common_VirtualPropertySystem::setMutator(
|
||||
$this->_entityName, $fieldName, false);
|
||||
}
|
||||
}
|
||||
return Doctrine_Common_VirtualPropertySystem::getMutator($this->_entityName, $fieldName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the custom accessor method of a virtual property, if it exists.
|
||||
*
|
||||
* @param string $fieldName The field name.
|
||||
* @return mixed The name of the custom accessor method, or FALSE if the
|
||||
* field does not have a custom accessor.
|
||||
*/
|
||||
private function _getCustomAccessor($fieldName)
|
||||
{
|
||||
if (Doctrine_Common_VirtualPropertySystem::getAccessor($this->_entityName, $fieldName) === null) {
|
||||
if (Doctrine_Common_VirtualPropertySystem::isAutoAccessorOverride()) {
|
||||
$getterMethod = 'get' . Doctrine::classify($fieldName);
|
||||
if ( ! method_exists($this, $getterMethod)) {
|
||||
$getterMethod = false;
|
||||
}
|
||||
Doctrine_Common_VirtualPropertySystem::setAccessor(
|
||||
$this->_entityName, $fieldName, $getterMethod);
|
||||
} else {
|
||||
Doctrine_Common_VirtualPropertySystem::setAccessor(
|
||||
$this->_entityName, $fieldName, false);
|
||||
}
|
||||
}
|
||||
|
||||
return Doctrine_Common_VirtualPropertySystem::getAccessor($this->_entityName, $fieldName);
|
||||
}
|
||||
|
||||
protected function _contains($fieldName)
|
||||
{
|
||||
return isset($this->_data[$fieldName]);
|
||||
}
|
||||
|
||||
protected function _unset($fieldName)
|
||||
{
|
||||
unset($this->_data[$fieldName]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Intercepts mutating calls for virtual properties.
|
||||
*
|
||||
* @see set, offsetSet
|
||||
* @param $name
|
||||
* @param $value
|
||||
* @since 1.0
|
||||
* @return void
|
||||
*/
|
||||
public function __set($name, $value)
|
||||
{
|
||||
$this->set($name, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Intercepts accessing calls for virtual properties.
|
||||
*
|
||||
* @see get, offsetGet
|
||||
* @param mixed $name
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
return $this->get($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Intercepts isset() calls for virtual properties.
|
||||
*
|
||||
* @param string $name
|
||||
* @return boolean whether or not this object contains $name
|
||||
*/
|
||||
public function __isset($name)
|
||||
{
|
||||
return $this->_contains($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Intercepts unset() calls for virtual properties.
|
||||
*
|
||||
* @param string $name
|
||||
* @return void
|
||||
*/
|
||||
public function __unset($name)
|
||||
{
|
||||
return $this->_unset($name);
|
||||
}
|
||||
|
||||
/* ArrayAccess implementation */
|
||||
|
||||
/**
|
||||
* Check if an offsetExists.
|
||||
*
|
||||
* @param mixed $offset
|
||||
* @return boolean whether or not this object contains $offset
|
||||
*/
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
return $this->_contains($offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* offsetGet an alias of get()
|
||||
*
|
||||
* @see get, __get
|
||||
* @param mixed $offset
|
||||
* @return mixed
|
||||
*/
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
return $this->get($offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* sets $offset to $value
|
||||
* @see set, __set
|
||||
* @param mixed $offset
|
||||
* @param mixed $value
|
||||
* @return void
|
||||
*/
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
return $this->set($offset, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* unset a given offset
|
||||
* @see set, offsetSet, __set
|
||||
* @param mixed $offset
|
||||
*/
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
return $this->_unset($offset);
|
||||
}
|
||||
|
||||
/* END of ArrayAccess implementation */
|
||||
}
|
||||
?>
|
241
lib/Doctrine/Common/VirtualPropertySystem.php
Normal file
241
lib/Doctrine/Common/VirtualPropertySystem.php
Normal file
@ -0,0 +1,241 @@
|
||||
<?php
|
||||
/**
|
||||
* The VirtualPropertySystem class is a class consisting solely of static methods and
|
||||
* serves as a generic virtual property registry system.
|
||||
* Classes register their (virtual) properties with the property system, optionally specifying
|
||||
* property features/options. These can then be evaluated by other code.
|
||||
*
|
||||
* @author robo
|
||||
* @since 2.0
|
||||
*/
|
||||
class Doctrine_Common_VirtualPropertySystem {
|
||||
private static $_properties = array();
|
||||
private static $_callback = 'construct';
|
||||
private static $_checkTypes = false;
|
||||
private static $_useAutoAccessorOverride = true;
|
||||
private static $_simplePHPTypes = array(
|
||||
'int' => true,
|
||||
'string' => true,
|
||||
'bool' => true,
|
||||
'double' => true
|
||||
);
|
||||
|
||||
/** Private constructor. This class cannot be instantiated. */
|
||||
private function __construct() {}
|
||||
|
||||
/**
|
||||
* Gets all properties of a class that are registered with the VirtualPropertySystem.
|
||||
*
|
||||
* @param string $class
|
||||
* @return array
|
||||
*/
|
||||
public static function getProperties($class)
|
||||
{
|
||||
if ( ! self::isInitialized($class)) {
|
||||
self::initialize($class);
|
||||
}
|
||||
return self::$_properties[$class];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether automatic accessor overrides are enabled.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public static function isAutoAccessorOverride()
|
||||
{
|
||||
return self::$_useAutoAccessorOverride;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether automatic accessor overrides are enabled.
|
||||
*
|
||||
* @param boolean $bool
|
||||
*/
|
||||
public static function setAutoAccessorOverride($bool)
|
||||
{
|
||||
self::$_useAutoAccessorOverride = (bool)$bool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepopulates the property system.
|
||||
*
|
||||
* @param array $properties
|
||||
*/
|
||||
public static function populate(array $properties)
|
||||
{
|
||||
self::$_properties = $properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given type is a simple PHP type.
|
||||
* Simple php types are: int, string, bool, double.
|
||||
*
|
||||
* @param string $type The type to check.
|
||||
* @return boolean
|
||||
*/
|
||||
public static function isSimplePHPType($type)
|
||||
{
|
||||
return isset(self::$_simplePHPTypes[$type]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether type checks are enabled.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public static function isTypeCheckEnabled()
|
||||
{
|
||||
return self::$_checkTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether type checks are enabled.
|
||||
*
|
||||
* @param boolean $bool
|
||||
*/
|
||||
public static function setTypeCheckEnabled($bool)
|
||||
{
|
||||
self::$_checkTypes = (bool)$bool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the callback method to use for initializing the virtual
|
||||
* properties of a class. The callback must be static and public.
|
||||
*
|
||||
* @param string $callback
|
||||
*/
|
||||
public static function setCallback($callback)
|
||||
{
|
||||
self::$_callback = $callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a virtual property for a class.
|
||||
*
|
||||
* @param string $class
|
||||
* @param string $propName
|
||||
* @param string $type
|
||||
* @param string $accessor
|
||||
* @param string $mutator
|
||||
*/
|
||||
public static function register($class, $propName, $type, $accessor = null, $mutator = null)
|
||||
{
|
||||
self::$_properties[$class][$propName] = array(
|
||||
'type' => $type, 'accessor' => $accessor, 'mutator' => $mutator
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether a class has already been initialized by the virtual property system.
|
||||
*
|
||||
* @param string $class
|
||||
* @return boolean
|
||||
*/
|
||||
public static function isInitialized($class)
|
||||
{
|
||||
return isset(self::$_properties[$class]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes a class with the virtual property system.
|
||||
*
|
||||
* @param <type> $class
|
||||
*/
|
||||
public static function initialize($class)
|
||||
{
|
||||
if (method_exists($class, self::$_callback)) {
|
||||
call_user_func(array($class, self::$_callback));
|
||||
} else {
|
||||
self::$_properties[$class] = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether a class has a virtual property with a certain name.
|
||||
*
|
||||
* @param string $class
|
||||
* @param string $propName
|
||||
* @return boolean
|
||||
*/
|
||||
public static function hasProperty($class, $propName)
|
||||
{
|
||||
return isset(self::$_properties[$class][$propName]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the accessor for a virtual property.
|
||||
*
|
||||
* @param string $class
|
||||
* @param string $propName
|
||||
* @return string|null
|
||||
*/
|
||||
public static function getAccessor($class, $propName)
|
||||
{
|
||||
return isset(self::$_properties[$class][$propName]['accessor']) ?
|
||||
self::$_properties[$class][$propName]['accessor'] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the accessor method for a virtual property.
|
||||
*
|
||||
* @param <type> $class
|
||||
* @param <type> $propName
|
||||
* @param <type> $accessor
|
||||
*/
|
||||
public static function setAccessor($class, $propName, $accessor)
|
||||
{
|
||||
self::$_properties[$class][$propName]['accessor'] = $accessor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the mutator method for a virtual property.
|
||||
*
|
||||
* @param <type> $class
|
||||
* @param <type> $propName
|
||||
* @return <type>
|
||||
*/
|
||||
public static function getMutator($class, $propName)
|
||||
{
|
||||
return isset(self::$_properties[$class][$propName]['mutator']) ?
|
||||
self::$_properties[$class][$propName]['mutator'] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the mutator method for a virtual property.
|
||||
*
|
||||
* @param <type> $class
|
||||
* @param <type> $propName
|
||||
* @param <type> $mutator
|
||||
*/
|
||||
public static function setMutator($class, $propName, $mutator)
|
||||
{
|
||||
self::$_properties[$class][$propName]['mutator'] = $mutator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type of a virtual property.
|
||||
*
|
||||
* @param <type> $class
|
||||
* @param <type> $propName
|
||||
* @return <type>
|
||||
*/
|
||||
public static function getType($class, $propName)
|
||||
{
|
||||
return isset(self::$_properties[$class][$propName]['type']) ?
|
||||
self::$_properties[$class][$propName]['type'] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the type of a virtual property.
|
||||
*
|
||||
* @param <type> $class
|
||||
* @param <type> $propName
|
||||
* @param <type> $type
|
||||
*/
|
||||
public static function setType($class, $propName, $type)
|
||||
{
|
||||
self::$_properties[$class][$propName]['type'] = $type;
|
||||
}
|
||||
}
|
||||
?>
|
@ -19,14 +19,14 @@
|
||||
* <http://www.phpdoctrine.org>.
|
||||
*/
|
||||
|
||||
#namespace Doctrine::DBAL;
|
||||
#namespace Doctrine\DBAL;
|
||||
|
||||
#use Doctrine::Common::Configuration;
|
||||
#use Doctrine::Common::EventManager;
|
||||
#use Doctrine::DBAL::Exceptions::ConnectionException;
|
||||
#use Doctrine\Common\Configuration;
|
||||
#use Doctrine\Common\EventManager;
|
||||
#use Doctrine\DBAL\Exceptions\ConnectionException;
|
||||
|
||||
/**
|
||||
* A wrapper around a Doctrine::DBAL::Driver::Connection that adds features like
|
||||
* A wrapper around a Doctrine\DBAL\Driver\Connection that adds features like
|
||||
* events, transaction isolation levels, configuration, emulated transaction nesting,
|
||||
* lazy connecting and more.
|
||||
*
|
||||
@ -51,7 +51,7 @@
|
||||
* 'masters' => array(...),
|
||||
* 'masterConnectionResolver' => new MyMasterConnectionResolver()
|
||||
*
|
||||
* Doctrine::DBAL could ship with a simple standard broker that uses a primitive
|
||||
* Doctrine\DBAL could ship with a simple standard broker that uses a primitive
|
||||
* round-robin approach to distribution. User can provide its own brokers.
|
||||
*/
|
||||
class Doctrine_DBAL_Connection
|
||||
@ -76,21 +76,21 @@ class Doctrine_DBAL_Connection
|
||||
/**
|
||||
* The wrapped driver connection.
|
||||
*
|
||||
* @var Doctrine::DBAL::Driver::Connection
|
||||
* @var Doctrine\DBAL\Driver\Connection
|
||||
*/
|
||||
protected $_conn;
|
||||
|
||||
/**
|
||||
* The Configuration.
|
||||
*
|
||||
* @var Doctrine::Common::Configuration
|
||||
* @var Doctrine\Common\Configuration
|
||||
*/
|
||||
protected $_config;
|
||||
|
||||
/**
|
||||
* The EventManager.
|
||||
*
|
||||
* @var Doctrine::Commom::EventManager
|
||||
* @var Doctrine\Common\EventManager
|
||||
*/
|
||||
protected $_eventManager;
|
||||
|
||||
@ -116,7 +116,7 @@ class Doctrine_DBAL_Connection
|
||||
protected $_transactionIsolationLevel;
|
||||
|
||||
/**
|
||||
* The parameters used during creation of the Connection.
|
||||
* The parameters used during creation of the Connection instance.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
@ -133,32 +133,32 @@ class Doctrine_DBAL_Connection
|
||||
* The DatabasePlatform object that provides information about the
|
||||
* database platform used by the connection.
|
||||
*
|
||||
* @var Doctrine::DBAL::Platforms::DatabasePlatform
|
||||
* @var Doctrine\DBAL\Platforms\AbstractPlatform
|
||||
*/
|
||||
protected $_platform;
|
||||
|
||||
/**
|
||||
* The schema manager.
|
||||
*
|
||||
* @var Doctrine::DBAL::Schema::SchemaManager
|
||||
* @var Doctrine\DBAL\Schema\SchemaManager
|
||||
*/
|
||||
protected $_schemaManager;
|
||||
|
||||
/**
|
||||
* The used DBAL driver.
|
||||
*
|
||||
* @var Doctrine::DBAL::Driver
|
||||
* @var Doctrine\DBAL\Driver
|
||||
*/
|
||||
protected $_driver;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* Creates a new Connection.
|
||||
* Initializes a new instance of the Connection class.
|
||||
*
|
||||
* @param array $params The connection parameters.
|
||||
*/
|
||||
public function __construct(array $params, Doctrine_DBAL_Driver $driver,
|
||||
Doctrine_Common_Configuration $config = null, Doctrine_Common_EventManager $eventManager = null)
|
||||
Doctrine_Common_Configuration $config = null,
|
||||
Doctrine_Common_EventManager $eventManager = null)
|
||||
{
|
||||
$this->_driver = $driver;
|
||||
$this->_params = $params;
|
||||
@ -193,7 +193,7 @@ class Doctrine_DBAL_Connection
|
||||
/**
|
||||
* Gets the EventManager used by the Connection.
|
||||
*
|
||||
* @return Doctrine::Common::EventManager
|
||||
* @return Doctrine\Common\EventManager
|
||||
*/
|
||||
public function getEventManager()
|
||||
{
|
||||
@ -203,7 +203,7 @@ class Doctrine_DBAL_Connection
|
||||
/**
|
||||
* Gets the DatabasePlatform for the connection.
|
||||
*
|
||||
* @return Doctrine::DBAL::Platforms::DatabasePlatform
|
||||
* @return Doctrine\DBAL\Platforms\AbstractPlatform
|
||||
*/
|
||||
public function getDatabasePlatform()
|
||||
{
|
||||
@ -842,7 +842,7 @@ class Doctrine_DBAL_Connection
|
||||
/**
|
||||
* Gets the wrapped driver connection.
|
||||
*
|
||||
* @return Doctrine::DBAL::Driver::Connection
|
||||
* @return Doctrine\DBAL\Driver\Connection
|
||||
*/
|
||||
public function getWrappedConnection()
|
||||
{
|
||||
@ -853,7 +853,7 @@ class Doctrine_DBAL_Connection
|
||||
* Gets the SchemaManager that can be used to inspect or change the
|
||||
* database schema through the connection.
|
||||
*
|
||||
* @return Doctrine::DBAL::Schema::SchemaManager
|
||||
* @return Doctrine\DBAL\Schema\SchemaManager
|
||||
*/
|
||||
public function getSchemaManager()
|
||||
{
|
||||
|
@ -90,7 +90,8 @@ final class Doctrine_DBAL_DriverManager
|
||||
* @param Doctrine::Common::EventManager The event manager to use.
|
||||
* @return Doctrine::DBAL::Connection
|
||||
*/
|
||||
public static function getConnection(array $params, Doctrine_Common_Configuration $config = null,
|
||||
public static function getConnection(array $params,
|
||||
Doctrine_Common_Configuration $config = null,
|
||||
Doctrine_Common_EventManager $eventManager = null)
|
||||
{
|
||||
// create default config and event manager, if not set
|
||||
|
@ -1,6 +1,8 @@
|
||||
<?php
|
||||
|
||||
#namespace Doctrine::DBAL::Types;
|
||||
#namespace Doctrine\DBAL\Types;
|
||||
|
||||
#use Doctrine\DBAL\Platforms\AbstractDatabasePlatform;
|
||||
|
||||
abstract class Doctrine_DBAL_Types_Type
|
||||
{
|
||||
@ -14,7 +16,7 @@ abstract class Doctrine_DBAL_Types_Type
|
||||
'double' => 'Doctrine_DataType_DoubleType'
|
||||
);
|
||||
|
||||
public function convertToDatabaseValue($value, Doctrine_DatabasePlatform $platform)
|
||||
public function convertToDatabaseValue($value, Doctrine_DBAL_Platforms_AbstractDatabasePlatform $platform)
|
||||
{
|
||||
return $value;
|
||||
}
|
||||
@ -24,8 +26,8 @@ abstract class Doctrine_DBAL_Types_Type
|
||||
return $value;
|
||||
}
|
||||
|
||||
abstract public function getDefaultLength(Doctrine_DatabasePlatform $platform);
|
||||
abstract public function getSqlDeclaration(array $fieldDeclaration, Doctrine_DatabasePlatform $platform);
|
||||
abstract public function getDefaultLength(Doctrine_DBAL_Platforms_AbstractDatabasePlatform $platform);
|
||||
abstract public function getSqlDeclaration(array $fieldDeclaration, Doctrine_DBAL_Platforms_AbstractDatabasePlatform $platform);
|
||||
abstract public function getName();
|
||||
|
||||
/**
|
||||
|
@ -10,8 +10,45 @@
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
class Doctrine_ORM_ActiveEntity extends Doctrine_ORM_Entity
|
||||
class Doctrine_ORM_ActiveEntity extends Doctrine_Common_VirtualPropertyObject implements Doctrine_ORM_Entity
|
||||
{
|
||||
/**
|
||||
* The class descriptor.
|
||||
*
|
||||
* @var Doctrine::ORM::ClassMetadata
|
||||
*/
|
||||
private $_class;
|
||||
|
||||
/**
|
||||
* The changes that happened to fields of a managed entity.
|
||||
* Keys are field names, values oldValue => newValue tuples.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $_dataChangeSet = array();
|
||||
|
||||
/**
|
||||
* The EntityManager that is responsible for the persistent state of the entity.
|
||||
* Only managed entities have an associated EntityManager.
|
||||
*
|
||||
* @var Doctrine\ORM\EntityManager
|
||||
*/
|
||||
private $_em;
|
||||
|
||||
/**
|
||||
* Initializes a new instance of a class derived from ActiveEntity.
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->_oid = self::$_index++;
|
||||
$this->_em = Doctrine_ORM_EntityManager::getActiveEntityManager();
|
||||
if (is_null($this->_em)) {
|
||||
throw new Doctrine_Exception("No EntityManager found. ActiveEntity instances "
|
||||
. "can only be instantiated within the context of an active EntityManager.");
|
||||
}
|
||||
$this->_class = $this->_em->getClassMetadata($this->_entityName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the current state of the entity into the database.
|
||||
*
|
||||
@ -419,6 +456,270 @@ class Doctrine_ORM_ActiveEntity extends Doctrine_ORM_Entity
|
||||
$this->_data = array_merge($this->_data, $data);
|
||||
$this->_extractIdentifier();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helps freeing the memory occupied by the entity.
|
||||
* Cuts all references the entity has to other entities and removes the entity
|
||||
* from the instance pool.
|
||||
* Note: The entity is no longer useable after free() has been called. Any operations
|
||||
* done with the entity afterwards can lead to unpredictable results.
|
||||
*
|
||||
* @param boolean $deep Whether to cascade the free() call to (loaded) associated entities.
|
||||
*/
|
||||
public function free($deep = false)
|
||||
{
|
||||
if ($this->_state != self::STATE_LOCKED) {
|
||||
if ($this->_state == self::STATE_MANAGED) {
|
||||
$this->_em->detach($this);
|
||||
}
|
||||
if ($deep) {
|
||||
foreach ($this->_data as $name => $value) {
|
||||
if ($value instanceof Doctrine_ORM_Entity || $value instanceof Doctrine_ORM_Collection) {
|
||||
$value->free($deep);
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->_data = array();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of this object.
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return (string)$this->_oid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the entity is new.
|
||||
*
|
||||
* @return boolean TRUE if the entity is new, FALSE otherwise.
|
||||
*/
|
||||
final public function isNew()
|
||||
{
|
||||
return $this->_state == self::STATE_NEW;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the entity has been modified since it was last synchronized
|
||||
* with the database.
|
||||
*
|
||||
* @return boolean TRUE if the object has been modified, FALSE otherwise.
|
||||
*/
|
||||
final public function isModified()
|
||||
{
|
||||
return count($this->_dataChangeSet) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ClassMetadata object that describes the entity class.
|
||||
*
|
||||
* @return Doctrine::ORM::Mapping::ClassMetadata
|
||||
*/
|
||||
final public function getClass()
|
||||
{
|
||||
return $this->_class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the EntityManager that is responsible for the persistence of
|
||||
* this entity.
|
||||
*
|
||||
* @return Doctrine::ORM::EntityManager
|
||||
*/
|
||||
final public function getEntityManager()
|
||||
{
|
||||
return $this->_em;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the EntityRepository of the Entity.
|
||||
*
|
||||
* @return Doctrine::ORM::EntityRepository
|
||||
*/
|
||||
final public function getRepository()
|
||||
{
|
||||
return $this->_em->getRepository($this->_entityName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks whether a field is set (not null).
|
||||
*
|
||||
* @param string $name
|
||||
* @return boolean
|
||||
* @override
|
||||
*/
|
||||
final protected function _contains($fieldName)
|
||||
{
|
||||
if (isset($this->_data[$fieldName])) {
|
||||
if ($this->_data[$fieldName] === Doctrine_ORM_Internal_Null::$INSTANCE) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the value of a field.
|
||||
*
|
||||
* @param string $name
|
||||
* @return void
|
||||
* @override
|
||||
*/
|
||||
final protected function _unset($fieldName)
|
||||
{
|
||||
if (isset($this->_data[$fieldName])) {
|
||||
if ($this->_state == self::STATE_MANAGED && $this->_class->hasAssociation($fieldName)) {
|
||||
$assoc = $this->_class->getAssociationMapping($fieldName);
|
||||
if ($assoc->isOneToOne() && $assoc->shouldDeleteOrphans()) {
|
||||
$this->_em->delete($this->_references[$fieldName]);
|
||||
} else if ($assoc->isOneToMany() && $assoc->shouldDeleteOrphans()) {
|
||||
foreach ($this->_references[$fieldName] as $entity) {
|
||||
$this->_em->delete($entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->_data[$fieldName] = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Registers the entity as dirty with the UnitOfWork.
|
||||
* Note: The Entity is only registered dirty if it is MANAGED and not yet
|
||||
* registered as dirty.
|
||||
*/
|
||||
private function _registerDirty()
|
||||
{
|
||||
if ($this->_state == self::STATE_MANAGED &&
|
||||
! $this->_em->getUnitOfWork()->isRegisteredDirty($this)) {
|
||||
$this->_em->getUnitOfWork()->registerDirty($this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the entity class name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
final public function getClassName()
|
||||
{
|
||||
return $this->_entityName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the data of the Entity.
|
||||
*
|
||||
* @return array The fields and their values.
|
||||
*/
|
||||
final public function getData()
|
||||
{
|
||||
return $this->_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of a field (regular field or reference).
|
||||
*
|
||||
* @param $name Name of the field.
|
||||
* @return mixed Value of the field.
|
||||
* @throws Doctrine::ORM::Exceptions::EntityException If trying to get an unknown field.
|
||||
* @override
|
||||
*/
|
||||
final protected function _get($fieldName)
|
||||
{
|
||||
$nullObj = Doctrine_ORM_Internal_Null::$INSTANCE;
|
||||
if (isset($this->_data[$fieldName])) {
|
||||
return $this->_data[$fieldName] !== $nullObj ?
|
||||
$this->_data[$fieldName] : null;
|
||||
} else {
|
||||
if ($this->_state == self::STATE_MANAGED && $this->_class->hasAssociation($fieldName)) {
|
||||
$rel = $this->_class->getAssociationMapping($fieldName);
|
||||
if ($rel->isLazilyFetched()) {
|
||||
$this->_data[$fieldName] = $rel->lazyLoadFor($this);
|
||||
return $this->_data[$fieldName] !== $nullObj ?
|
||||
$this->_data[$fieldName] : null;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of a field (regular field or reference).
|
||||
*
|
||||
* @param $fieldName The name of the field.
|
||||
* @param $value The value of the field.
|
||||
* @return void
|
||||
* @throws Doctrine::ORM::Exceptions::EntityException
|
||||
* @override
|
||||
*/
|
||||
final protected function _set($fieldName, $value)
|
||||
{
|
||||
$old = isset($this->_data[$fieldName]) ? $this->_data[$fieldName] : null;
|
||||
if ( ! is_object($value)) {
|
||||
// NOTE: Common case: $old != $value. Special case: null == 0 (TRUE), which
|
||||
// is addressed by xor.
|
||||
if ($old != $value || (is_null($old) xor is_null($value))) {
|
||||
$this->_data[$fieldName] = $value;
|
||||
$this->_dataChangeSet[$fieldName] = array($old => $value);
|
||||
$this->_registerDirty();
|
||||
}
|
||||
} else {
|
||||
if ($old !== $value) {
|
||||
$this->_internalSetReference($fieldName, $value);
|
||||
$this->_dataChangeSet[$fieldName] = array($old => $value);
|
||||
$this->_registerDirty();
|
||||
if ($this->_state == self::STATE_MANAGED) {
|
||||
//TODO: Allow arrays in $value. Wrap them in a Collection transparently.
|
||||
if ($old instanceof Doctrine_ORM_Collection) {
|
||||
$this->_em->getUnitOfWork()->scheduleCollectionDeletion($old);
|
||||
}
|
||||
if ($value instanceof Doctrine_ORM_Collection) {
|
||||
$this->_em->getUnitOfWork()->scheduleCollectionRecreation($value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Serializable implementation */
|
||||
|
||||
/**
|
||||
* Serializes the entity.
|
||||
* This method is automatically called when the entity is serialized.
|
||||
*
|
||||
* Part of the implementation of the Serializable interface.
|
||||
*
|
||||
* @return string
|
||||
* @todo Reimplement
|
||||
*/
|
||||
public function serialize()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Reconstructs the entity from it's serialized form.
|
||||
* This method is automatically called everytime the entity is unserialized.
|
||||
*
|
||||
* @param string $serialized Doctrine_Entity as serialized string
|
||||
* @throws Doctrine_Record_Exception if the cleanData operation fails somehow
|
||||
* @return void
|
||||
* @todo Reimplement.
|
||||
*/
|
||||
public function unserialize($serialized)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
/* END of Serializable implementation */
|
||||
}
|
||||
|
||||
?>
|
@ -45,6 +45,7 @@
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @todo Add more typical Collection methods.
|
||||
* @todo Rename to PersistentCollection
|
||||
*/
|
||||
class Doctrine_ORM_Collection implements Countable, IteratorAggregate, Serializable, ArrayAccess
|
||||
{
|
||||
@ -74,7 +75,7 @@ class Doctrine_ORM_Collection implements Countable, IteratorAggregate, Serializa
|
||||
/**
|
||||
* This entity that owns this collection.
|
||||
*
|
||||
* @var Doctrine::ORM::Entity
|
||||
* @var Doctrine\ORM\Entity
|
||||
*/
|
||||
protected $_owner;
|
||||
|
||||
@ -82,7 +83,7 @@ class Doctrine_ORM_Collection implements Countable, IteratorAggregate, Serializa
|
||||
* The association mapping the collection belongs to.
|
||||
* This is currently either a OneToManyMapping or a ManyToManyMapping.
|
||||
*
|
||||
* @var Doctrine::ORM::Mapping::AssociationMapping
|
||||
* @var Doctrine\ORM\Mapping\AssociationMapping
|
||||
*/
|
||||
protected $_association;
|
||||
|
||||
@ -93,17 +94,10 @@ class Doctrine_ORM_Collection implements Countable, IteratorAggregate, Serializa
|
||||
*/
|
||||
protected $_keyField;
|
||||
|
||||
/**
|
||||
* Helper variable. Used for fast null value testing.
|
||||
*
|
||||
* @var Doctrine_Null
|
||||
*/
|
||||
//protected static $null;
|
||||
|
||||
/**
|
||||
* The EntityManager that manages the persistence of the collection.
|
||||
*
|
||||
* @var Doctrine::ORM::EntityManager
|
||||
* @var Doctrine\ORM\EntityManager
|
||||
*/
|
||||
protected $_em;
|
||||
|
||||
@ -124,7 +118,6 @@ class Doctrine_ORM_Collection implements Countable, IteratorAggregate, Serializa
|
||||
protected $_hydrationFlag;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* Creates a new persistent collection.
|
||||
*/
|
||||
public function __construct($entityBaseType, $keyField = null)
|
||||
@ -174,9 +167,9 @@ class Doctrine_ORM_Collection implements Countable, IteratorAggregate, Serializa
|
||||
}
|
||||
|
||||
/**
|
||||
* returns all the records as an array
|
||||
* Unwraps the array contained in the Collection instance.
|
||||
*
|
||||
* @return array
|
||||
* @return array The wrapped array.
|
||||
*/
|
||||
public function unwrap()
|
||||
{
|
||||
@ -229,7 +222,7 @@ class Doctrine_ORM_Collection implements Countable, IteratorAggregate, Serializa
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function _setOwner(Doctrine_ORM_Entity $entity, Doctrine_ORM_Mapping_AssociationMapping $relation)
|
||||
public function _setOwner($entity, Doctrine_ORM_Mapping_AssociationMapping $relation)
|
||||
{
|
||||
$this->_owner = $entity;
|
||||
$this->_association = $relation;
|
||||
@ -248,9 +241,9 @@ class Doctrine_ORM_Collection implements Countable, IteratorAggregate, Serializa
|
||||
|
||||
/**
|
||||
* INTERNAL:
|
||||
* getReference
|
||||
* Gets the collection owner.
|
||||
*
|
||||
* @return mixed
|
||||
* @return Doctrine\ORM\Entity
|
||||
*/
|
||||
public function _getOwner()
|
||||
{
|
||||
@ -474,8 +467,7 @@ class Doctrine_ORM_Collection implements Countable, IteratorAggregate, Serializa
|
||||
*/
|
||||
public function add($value, $key = null)
|
||||
{
|
||||
//TODO: really only allow entities?
|
||||
if ( ! $value instanceof Doctrine_ORM_Entity) {
|
||||
if ( ! $value instanceof $this->_entityBaseType) {
|
||||
throw new Doctrine_Record_Exception('Value variable in collection is not an instance of Doctrine_Entity.');
|
||||
}
|
||||
|
||||
@ -496,7 +488,8 @@ class Doctrine_ORM_Collection implements Countable, IteratorAggregate, Serializa
|
||||
if ($this->_hydrationFlag) {
|
||||
if ($this->_backRefFieldName) {
|
||||
// set back reference to owner
|
||||
$value->_internalSetReference($this->_backRefFieldName, $this->_owner);
|
||||
$this->_em->getClassMetadata($this->_entityBaseType)->getReflectionProperty(
|
||||
$this->_backRefFieldName)->setValue($value, $this->_owner);
|
||||
}
|
||||
} else {
|
||||
//TODO: Register collection as dirty with the UoW if necessary
|
||||
@ -721,7 +714,8 @@ class Doctrine_ORM_Collection implements Countable, IteratorAggregate, Serializa
|
||||
*/
|
||||
public function isEmpty()
|
||||
{
|
||||
return $this->count() == 0;
|
||||
// Note: Little "trick". Empty arrays evaluate to FALSE. No need to count().
|
||||
return ! (bool)$this->_data;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -765,40 +759,6 @@ class Doctrine_ORM_Collection implements Countable, IteratorAggregate, Serializa
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Export a Doctrine_Collection to one of the supported Doctrine_Parser formats
|
||||
*
|
||||
* @param string $type
|
||||
* @param string $deep
|
||||
* @return void
|
||||
* @todo Move elsewhere.
|
||||
*/
|
||||
/*public function exportTo($type, $deep = false)
|
||||
{
|
||||
if ($type == 'array') {
|
||||
return $this->toArray($deep);
|
||||
} else {
|
||||
return Doctrine_Parser::dump($this->toArray($deep, true), $type);
|
||||
}
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Import data to a Doctrine_Collection from one of the supported Doctrine_Parser formats
|
||||
*
|
||||
* @param string $type
|
||||
* @param string $data
|
||||
* @return void
|
||||
* @todo Move elsewhere.
|
||||
*/
|
||||
/*public function importFrom($type, $data)
|
||||
{
|
||||
if ($type == 'array') {
|
||||
return $this->fromArray($data);
|
||||
} else {
|
||||
return $this->fromArray(Doctrine_Parser::load($data, $type));
|
||||
}
|
||||
}*/
|
||||
|
||||
/**
|
||||
* INTERNAL: getDeleteDiff
|
||||
*
|
||||
@ -833,62 +793,9 @@ class Doctrine_ORM_Collection implements Countable, IteratorAggregate, Serializa
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves all records of this collection and processes the
|
||||
* difference of the last snapshot and the current data.
|
||||
*
|
||||
* @param Doctrine_Connection $conn optional connection parameter
|
||||
* @return Doctrine_Collection
|
||||
* @param <type> $deep
|
||||
*/
|
||||
/*public function save()
|
||||
{
|
||||
$conn = $this->_mapper->getConnection();
|
||||
|
||||
try {
|
||||
$conn->beginInternalTransaction();
|
||||
|
||||
$conn->transaction->addCollection($this);
|
||||
$this->processDiff();
|
||||
foreach ($this->getData() as $key => $record) {
|
||||
$record->save($conn);
|
||||
}
|
||||
|
||||
$conn->commit();
|
||||
} catch (Exception $e) {
|
||||
$conn->rollback();
|
||||
throw $e;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Deletes all records from the collection.
|
||||
* Shorthand for calling delete() for all entities in the collection.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
/*public function delete()
|
||||
{
|
||||
$conn = $this->_mapper->getConnection();
|
||||
|
||||
try {
|
||||
$conn->beginInternalTransaction();
|
||||
|
||||
$conn->transaction->addCollection($this);
|
||||
foreach ($this as $key => $record) {
|
||||
$record->delete($conn);
|
||||
}
|
||||
|
||||
$conn->commit();
|
||||
} catch (Exception $e) {
|
||||
$conn->rollback();
|
||||
throw $e;
|
||||
}
|
||||
|
||||
$this->clear();
|
||||
}*/
|
||||
|
||||
|
||||
public function free($deep = false)
|
||||
{
|
||||
foreach ($this->getData() as $key => $record) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?php
|
||||
/*
|
||||
* $Id: Record.php 4342 2008-05-08 14:17:35Z romanb $
|
||||
* $Id$
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
@ -19,974 +19,18 @@
|
||||
* <http://www.phpdoctrine.org>.
|
||||
*/
|
||||
|
||||
#namespace Doctrine::ORM;
|
||||
#namespace Doctrine\ORM;
|
||||
|
||||
#use \Serializable;
|
||||
|
||||
/**
|
||||
* Base class for all Entities (objects with persistent state in a RDBMS that are
|
||||
* managed by Doctrine). Kind of a Layer Supertype.
|
||||
* Entity marker interface.
|
||||
*
|
||||
* NOTE: Methods that are intended for internal use only but must be public
|
||||
* are marked INTERNAL: and begin with an underscore "_" to indicate that they
|
||||
* ideally would not be public and to minimize naming collisions.
|
||||
*
|
||||
* The "final" modifiers on most methods prevent accidental overrides.
|
||||
* It is not desirable that subclasses can override these methods.
|
||||
* The persistence layer should stay in the background as much as possible.
|
||||
*
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.phpdoctrine.org
|
||||
* @link www.doctrine-project.org
|
||||
* @since 2.0
|
||||
* @version $Revision: 4342 $
|
||||
*/
|
||||
abstract class Doctrine_ORM_Entity implements ArrayAccess, Serializable
|
||||
{
|
||||
/**
|
||||
* MANAGED
|
||||
* An Entity is in managed state when it has a primary key/identifier and is
|
||||
* managed by an EntityManager (registered in the identity map).
|
||||
*/
|
||||
const STATE_MANAGED = 1;
|
||||
|
||||
/**
|
||||
* NEW
|
||||
* An Entity is new if it does not yet have an identifier/primary key
|
||||
* and is not (yet) managed by an EntityManager.
|
||||
*/
|
||||
const STATE_NEW = 2;
|
||||
|
||||
/**
|
||||
* LOCKED STATE
|
||||
* An Entity is temporarily locked during deletes and saves.
|
||||
*
|
||||
* This state is used internally to ensure that circular deletes
|
||||
* and saves will not cause infinite loops.
|
||||
* @todo Not sure this is a good idea. It is a problematic solution because
|
||||
* it hides the original state while the locked state is active.
|
||||
*/
|
||||
const STATE_LOCKED = 6;
|
||||
|
||||
/**
|
||||
* A detached Entity is an instance with a persistent identity that is not
|
||||
* (or no longer) associated with an EntityManager (and a UnitOfWork).
|
||||
* This means its no longer in the identity map.
|
||||
*/
|
||||
const STATE_DETACHED = 3;
|
||||
|
||||
/**
|
||||
* A removed Entity instance is an instance with a persistent identity,
|
||||
* associated with an EntityManager, whose persistent state has been
|
||||
* deleted (or is scheduled for deletion).
|
||||
*/
|
||||
const STATE_DELETED = 4;
|
||||
|
||||
/**
|
||||
* Index used for creating object identifiers (oid's).
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
private static $_index = 1;
|
||||
|
||||
/**
|
||||
* Boolean flag that indicates whether automatic accessor overriding is enabled.
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
private static $_useAutoAccessorOverride;
|
||||
|
||||
/**
|
||||
* The accessor cache is used as a memory for the existance of custom accessors.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $_accessorCache = array();
|
||||
|
||||
/**
|
||||
* The mutator cache is used as a memory for the existance of custom mutators.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $_mutatorCache = array();
|
||||
|
||||
/**
|
||||
* The class descriptor.
|
||||
*
|
||||
* @var Doctrine::ORM::ClassMetadata
|
||||
*/
|
||||
private $_class;
|
||||
|
||||
/**
|
||||
* The name of the Entity.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $_entityName;
|
||||
|
||||
/**
|
||||
* The values that make up the ID/primary key of the entity.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $_id = array();
|
||||
|
||||
/**
|
||||
* The entity data.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $_data = array();
|
||||
|
||||
/**
|
||||
* The state of the object.
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
private $_state;
|
||||
|
||||
/**
|
||||
* Name => Value map of join columns.
|
||||
*
|
||||
* @var array
|
||||
* @todo Not yet clear if needed.
|
||||
*/
|
||||
//private $_joinColumns = array();
|
||||
|
||||
/**
|
||||
* The changes that happened to fields of the entity.
|
||||
* Keys are field names, values oldValue => newValue tuples.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $_dataChangeSet = array();
|
||||
|
||||
/**
|
||||
* The changes that happened to references of the entity to other entities.
|
||||
* Keys are field names, values oldReference => newReference tuples.
|
||||
*
|
||||
* With one-one associations, a reference change means the reference has been
|
||||
* swapped out / replaced by another one.
|
||||
*
|
||||
* With one-many, many-many associations, a reference change means the complete
|
||||
* collection has been sweapped out / replaced by another one.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $_referenceChangeSet = array();
|
||||
|
||||
/**
|
||||
* The references for all associations of the entity to other entities.
|
||||
* Keys are field names, values object references.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $_references = array();
|
||||
|
||||
/**
|
||||
* The EntityManager that is responsible for the persistent state of the entity.
|
||||
*
|
||||
* @var Doctrine::ORM::EntityManager
|
||||
*/
|
||||
private $_em;
|
||||
|
||||
/**
|
||||
* The object identifier of the object. Each object has a unique identifier
|
||||
* during script execution.
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
private $_oid;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* Creates a new Entity instance.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->_entityName = get_class($this);
|
||||
$this->_em = Doctrine_ORM_EntityManager::getActiveEntityManager();
|
||||
$this->_class = $this->_em->getClassMetadata($this->_entityName);
|
||||
$this->_oid = self::$_index++;
|
||||
$this->_data = $this->_em->_getTmpEntityData();
|
||||
if ($this->_data) {
|
||||
$this->_extractIdentifier();
|
||||
$this->_state = self::STATE_MANAGED;
|
||||
} else {
|
||||
$this->_state = self::STATE_NEW;
|
||||
}
|
||||
|
||||
// @todo read from attribute the first time and move this initialization elsewhere.
|
||||
self::$_useAutoAccessorOverride = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the object identifier.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
final public function getOid()
|
||||
{
|
||||
return $this->_oid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the identifier names and values from _data into _id.
|
||||
*/
|
||||
private function _extractIdentifier()
|
||||
{
|
||||
if ( ! $this->_class->isIdentifierComposite()) {
|
||||
// Single field identifier
|
||||
$name = $this->_class->getIdentifier();
|
||||
$name = $name[0];
|
||||
if (isset($this->_data[$name]) && $this->_data[$name] !== Doctrine_ORM_Internal_Null::$INSTANCE) {
|
||||
$this->_id[$name] = $this->_data[$name];
|
||||
}
|
||||
} else {
|
||||
// Composite identifier
|
||||
$names = $this->_class->getIdentifier();
|
||||
foreach ($names as $name) {
|
||||
if ($this->_data[$name] === Doctrine_Null::$INSTANCE) {
|
||||
$this->_id[$name] = null;
|
||||
} else {
|
||||
$this->_id[$name] = $this->_data[$name];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes the entity.
|
||||
* This method is automatically called when the entity is serialized.
|
||||
*
|
||||
* Part of the implementation of the Serializable interface.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function serialize()
|
||||
{
|
||||
//$this->_em->getEventManager()->dispatchEvent(Event::preSerialize);
|
||||
//$this->_class->dispatchLifecycleEvent(Event::preSerialize, $this);
|
||||
|
||||
$vars = get_object_vars($this);
|
||||
|
||||
unset($vars['_references']);
|
||||
unset($vars['_em']);
|
||||
|
||||
//$name = (array)$this->_table->getIdentifier();
|
||||
$this->_data = array_merge($this->_data, $this->_id);
|
||||
|
||||
foreach ($this->_data as $k => $v) {
|
||||
if ($v instanceof Doctrine_ORM_Entity && $this->_class->getTypeOfField($k) != 'object') {
|
||||
unset($vars['_data'][$k]);
|
||||
} else if ($v === Doctrine_Null::$INSTANCE) {
|
||||
unset($vars['_data'][$k]);
|
||||
} else {
|
||||
switch ($this->_class->getTypeOfField($k)) {
|
||||
case 'array':
|
||||
case 'object':
|
||||
$vars['_data'][$k] = serialize($vars['_data'][$k]);
|
||||
break;
|
||||
case 'gzip':
|
||||
$vars['_data'][$k] = gzcompress($vars['_data'][$k]);
|
||||
break;
|
||||
case 'enum':
|
||||
$vars['_data'][$k] = $this->_class->enumIndex($k, $vars['_data'][$k]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$str = serialize($vars);
|
||||
|
||||
//$this->postSerialize($event);
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reconstructs the entity from it's serialized form.
|
||||
* This method is automatically called everytime the entity is unserialized.
|
||||
*
|
||||
* @param string $serialized Doctrine_Entity as serialized string
|
||||
* @throws Doctrine_Record_Exception if the cleanData operation fails somehow
|
||||
* @return void
|
||||
*/
|
||||
public function unserialize($serialized)
|
||||
{
|
||||
//$event = new Doctrine_Event($this, Doctrine_Event::RECORD_UNSERIALIZE);
|
||||
//$this->preUnserialize($event);
|
||||
|
||||
$this->_entityName = get_class($this);
|
||||
$manager = Doctrine_EntityManagerFactory::getManager($this->_entityName);
|
||||
$connection = $manager->getConnection();
|
||||
|
||||
$this->_oid = self::$_index;
|
||||
self::$_index++;
|
||||
|
||||
$this->_em = $manager;
|
||||
|
||||
$array = unserialize($serialized);
|
||||
|
||||
foreach($array as $k => $v) {
|
||||
$this->$k = $v;
|
||||
}
|
||||
|
||||
$this->_class = $this->_em->getClassMetadata($this->_entityName);
|
||||
|
||||
foreach ($this->_data as $k => $v) {
|
||||
switch ($this->_class->getTypeOfField($k)) {
|
||||
case 'array':
|
||||
case 'object':
|
||||
$this->_data[$k] = unserialize($this->_data[$k]);
|
||||
break;
|
||||
case 'gzip':
|
||||
$this->_data[$k] = gzuncompress($this->_data[$k]);
|
||||
break;
|
||||
case 'enum':
|
||||
$this->_data[$k] = $this->_class->enumValue($k, $this->_data[$k]);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
$this->_extractIdentifier(!$this->isNew());
|
||||
|
||||
//$this->postUnserialize($event);
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL:
|
||||
* Gets or sets the state of this Entity.
|
||||
*
|
||||
* @param integer|string $state if set, this method tries to set the record state to $state
|
||||
* @see Doctrine_Entity::STATE_* constants
|
||||
*
|
||||
* @throws Doctrine_Record_State_Exception if trying to set an unknown state
|
||||
* @return null|integer
|
||||
*/
|
||||
final public function _state($state = null)
|
||||
{
|
||||
if ($state == null) {
|
||||
return $this->_state;
|
||||
}
|
||||
$this->_state = $state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current field values.
|
||||
*
|
||||
* @return array The fields and their values.
|
||||
*/
|
||||
final public function getData()
|
||||
{
|
||||
return $this->_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of a field (regular field or reference).
|
||||
*
|
||||
* @param $name Name of the field.
|
||||
* @return mixed Value of the field.
|
||||
* @throws Doctrine::ORM::Exceptions::EntityException If trying to get an unknown field.
|
||||
*/
|
||||
final protected function _get($fieldName)
|
||||
{
|
||||
$nullObj = Doctrine_ORM_Internal_Null::$INSTANCE;
|
||||
if (isset($this->_data[$fieldName])) {
|
||||
return $this->_data[$fieldName] !== $nullObj ?
|
||||
$this->_data[$fieldName] : null;
|
||||
} else if (isset($this->_references[$fieldName])) {
|
||||
return $this->_references[$fieldName] !== $nullObj ?
|
||||
$this->_references[$fieldName] : null;
|
||||
} else {
|
||||
if ($this->_class->hasField($fieldName)) {
|
||||
return null;
|
||||
} else if ($this->_class->hasAssociation($fieldName)) {
|
||||
$rel = $this->_class->getAssociationMapping($fieldName);
|
||||
if ($rel->isLazilyFetched()) {
|
||||
$this->_references[$fieldName] = $rel->lazyLoadFor($this);
|
||||
return $this->_references[$fieldName] !== $nullObj ?
|
||||
$this->_references[$fieldName] : null;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
throw Doctrine_Entity_Exception::invalidField($fieldName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of a field (regular field or reference).
|
||||
*
|
||||
* @param $fieldName The name of the field.
|
||||
* @param $value The value of the field.
|
||||
* @return void
|
||||
* @throws Doctrine::ORM::Exceptions::EntityException
|
||||
*/
|
||||
final protected function _set($fieldName, $value)
|
||||
{
|
||||
if ($this->_class->hasField($fieldName)) {
|
||||
$old = isset($this->_data[$fieldName]) ? $this->_data[$fieldName] : null;
|
||||
// NOTE: Common case: $old != $value. Special case: null == 0 (TRUE), which
|
||||
// is addressed by xor.
|
||||
if ($old != $value || (is_null($old) xor is_null($value))) {
|
||||
$this->_data[$fieldName] = $value;
|
||||
$this->_dataChangeSet[$fieldName] = array($old => $value);
|
||||
if ($this->isNew() && $this->_class->isIdentifier($fieldName)) {
|
||||
$this->_id[$fieldName] = $value;
|
||||
}
|
||||
$this->_registerDirty();
|
||||
}
|
||||
} else if ($this->_class->hasAssociation($fieldName)) {
|
||||
$old = isset($this->_references[$fieldName]) ? $this->_references[$fieldName] : null;
|
||||
if ($old !== $value) {
|
||||
$this->_internalSetReference($fieldName, $value);
|
||||
$this->_referenceChangeSet[$fieldName] = array($old => $value);
|
||||
$this->_registerDirty();
|
||||
//TODO: Allow arrays in $value. Wrap them in a collection transparently.
|
||||
if ($old instanceof Doctrine_Collection) {
|
||||
$this->_em->getUnitOfWork()->scheduleCollectionDeletion($old);
|
||||
}
|
||||
if ($value instanceof Doctrine_Collection) {
|
||||
$this->_em->getUnitOfWork()->scheduleCollectionRecreation($value);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw Doctrine_ORM_Exceptions_EntityException::invalidField($fieldName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the entity as dirty with the UnitOfWork.
|
||||
*/
|
||||
private function _registerDirty()
|
||||
{
|
||||
if ($this->_state == self::STATE_MANAGED &&
|
||||
! $this->_em->getUnitOfWork()->isRegisteredDirty($this)) {
|
||||
$this->_em->getUnitOfWork()->registerDirty($this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL:
|
||||
* Gets the value of a field.
|
||||
*
|
||||
* NOTE: Use of this method in userland code is strongly discouraged.
|
||||
* This method does NOT check whether the field exists.
|
||||
* _get() in extending classes should be preferred.
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @return mixed
|
||||
*/
|
||||
final public function _internalGetField($fieldName)
|
||||
{
|
||||
if ($this->_data[$fieldName] === Doctrine_ORM_Internal_Null::$INSTANCE) {
|
||||
return null;
|
||||
}
|
||||
return $this->_data[$fieldName];
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL:
|
||||
* Sets the value of a field.
|
||||
*
|
||||
* NOTE: Use of this method in userland code is strongly discouraged.
|
||||
* This method does NOT check whether the field exists.
|
||||
* _set() in extending classes should be preferred.
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @param mixed $value
|
||||
*/
|
||||
final public function _internalSetField($fieldName, $value)
|
||||
{
|
||||
$this->_data[$fieldName] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL:
|
||||
* Gets a reference to another Entity.
|
||||
*
|
||||
* NOTE: Use of this method in userland code is strongly discouraged.
|
||||
* This method does NOT check whether the reference exists.
|
||||
*
|
||||
* @param string $fieldName
|
||||
*/
|
||||
final public function _internalGetReference($fieldName)
|
||||
{
|
||||
if ($this->_references[$fieldName] === Doctrine_ORM_Internal_Null::$INSTANCE) {
|
||||
return null;
|
||||
}
|
||||
return $this->_references[$fieldName];
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL:
|
||||
* Sets a reference to another entity or a collection of entities.
|
||||
*
|
||||
* NOTE: Use of this method in userland code is strongly discouraged.
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @param mixed $value
|
||||
* @param boolean $completeBidirectional Whether to complete bidirectional associations
|
||||
* (creating the back-reference). Should only
|
||||
* be used by hydration.
|
||||
*/
|
||||
final public function _internalSetReference($name, $value, $completeBidirectional = false)
|
||||
{
|
||||
if (is_null($value) || $value === Doctrine_ORM_Internal_Null::$INSTANCE) {
|
||||
$this->_references[$name] = $value;
|
||||
return; // early exit!
|
||||
}
|
||||
|
||||
$rel = $this->_class->getAssociationMapping($name);
|
||||
|
||||
if ($rel->isOneToOne() && ! $value instanceof Doctrine_ORM_Entity) {
|
||||
throw Doctrine_Entity_Exception::invalidValueForOneToOneReference();
|
||||
} else if (($rel->isOneToMany() || $rel->isManyToMany()) && ! $value instanceof Doctrine_ORM_Collection) {
|
||||
throw Doctrine_Entity_Exception::invalidValueForOneToManyReference();
|
||||
}
|
||||
|
||||
$this->_references[$name] = $value;
|
||||
|
||||
if ($completeBidirectional && $rel->isOneToOne()) {
|
||||
if ($rel->isOwningSide()) {
|
||||
// If there is an inverse mapping on the target class its bidirectional
|
||||
$targetClass = $this->_em->getClassMetadata($rel->getTargetEntityName());
|
||||
if ($targetClass->hasInverseAssociationMapping($name)) {
|
||||
$value->_internalSetReference(
|
||||
$targetClass->getInverseAssociationMapping($name)->getSourceFieldName(),
|
||||
$this
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// for sure bidirectional, as there is no inverse side in unidirectional
|
||||
$value->_internalSetReference($rel->getMappedByFieldName(), $this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic getter for all (persistent) fields of the entity.
|
||||
*
|
||||
* Invoked by Doctrine::ORM::Access#__get().
|
||||
*
|
||||
* @param string $fieldName Name of the field.
|
||||
* @return mixed
|
||||
* @override
|
||||
*/
|
||||
final public function get($fieldName)
|
||||
{
|
||||
if ($getter = $this->_getCustomAccessor($fieldName)) {
|
||||
return $this->$getter();
|
||||
}
|
||||
return $this->_get($fieldName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the custom mutator method for a field, if it exists.
|
||||
*
|
||||
* @param string $fieldName The field name.
|
||||
* @return mixed The name of the custom mutator or FALSE, if the field does
|
||||
* not have a custom mutator.
|
||||
*/
|
||||
private function _getCustomMutator($fieldName)
|
||||
{
|
||||
if ( ! isset(self::$_mutatorCache[$this->_entityName][$fieldName])) {
|
||||
if (self::$_useAutoAccessorOverride) {
|
||||
$setterMethod = 'set' . Doctrine::classify($fieldName);
|
||||
if (method_exists($this, $setterMethod)) {
|
||||
self::$_mutatorCache[$this->_entityName][$fieldName] = $setterMethod;
|
||||
} else {
|
||||
self::$_mutatorCache[$this->_entityName][$fieldName] = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($setter = $this->_class->getCustomMutator($fieldName)) {
|
||||
self::$_mutatorCache[$this->_entityName][$fieldName] = $setter;
|
||||
} else if ( ! isset(self::$_mutatorCache[$this->_entityName][$fieldName])) {
|
||||
self::$_mutatorCache[$this->_entityName][$fieldName] = false;
|
||||
}
|
||||
}
|
||||
|
||||
return self::$_mutatorCache[$this->_entityName][$fieldName];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the custom accessor method of a field, if it exists.
|
||||
*
|
||||
* @param string $fieldName The field name.
|
||||
* @return mixed The name of the custom accessor method, or FALSE if the
|
||||
* field does not have a custom accessor.
|
||||
*/
|
||||
private function _getCustomAccessor($fieldName)
|
||||
{
|
||||
if ( ! isset(self::$_accessorCache[$this->_entityName][$fieldName])) {
|
||||
if (self::$_useAutoAccessorOverride) {
|
||||
$getterMethod = 'get' . Doctrine::classify($fieldName);
|
||||
if (method_exists($this, $getterMethod)) {
|
||||
self::$_accessorCache[$this->_entityName][$fieldName] = $getterMethod;
|
||||
} else {
|
||||
self::$_accessorCache[$this->_entityName][$fieldName] = false;
|
||||
}
|
||||
}
|
||||
if ($getter = $this->_class->getCustomAccessor($fieldName)) {
|
||||
self::$_accessorCache[$this->_entityName][$fieldName] = $getter;
|
||||
} else if ( ! isset(self::$_accessorCache[$this->_entityName][$fieldName])) {
|
||||
self::$_accessorCache[$this->_entityName][$fieldName] = false;
|
||||
}
|
||||
}
|
||||
|
||||
return self::$_accessorCache[$this->_entityName][$fieldName];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the entity class name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
final public function getClassName()
|
||||
{
|
||||
return $this->_entityName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic setter for (persistent) fields of the entity.
|
||||
*
|
||||
* Invoked by Doctrine::ORM::Access#__set().
|
||||
*
|
||||
* @param string $name The name of the field to set.
|
||||
* @param mixed $value The value of the field.
|
||||
* @override
|
||||
*/
|
||||
final public function set($fieldName, $value)
|
||||
{
|
||||
if ($setter = $this->_getCustomMutator($fieldName)) {
|
||||
return $this->$setter($value);
|
||||
}
|
||||
$this->_set($fieldName, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a field is set (not null).
|
||||
*
|
||||
* NOTE: Invoked by Doctrine::ORM::Access#__isset().
|
||||
*
|
||||
* @param string $name
|
||||
* @return boolean
|
||||
*/
|
||||
private function _contains($fieldName)
|
||||
{
|
||||
if (isset($this->_data[$fieldName])) {
|
||||
if ($this->_data[$fieldName] === Doctrine_ORM_Internal_Null::$INSTANCE) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (isset($this->_id[$fieldName])) {
|
||||
return true;
|
||||
}
|
||||
if (isset($this->_references[$fieldName]) &&
|
||||
$this->_references[$fieldName] !== Doctrine_ORM_Internal_Null::$INSTANCE) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the value of a field.
|
||||
*
|
||||
* @param string $name
|
||||
* @return void
|
||||
*/
|
||||
private function _unset($fieldName)
|
||||
{
|
||||
if (isset($this->_data[$fieldName])) {
|
||||
$this->_data[$fieldName] = null;
|
||||
} else if (isset($this->_references[$fieldName])) {
|
||||
$assoc = $this->_class->getAssociationMapping($fieldName);
|
||||
if ($assoc->isOneToOne() && $assoc->shouldDeleteOrphans()) {
|
||||
$this->_em->delete($this->_references[$fieldName]);
|
||||
} else if ($assoc->isOneToMany() && $assoc->shouldDeleteOrphans()) {
|
||||
foreach ($this->_references[$fieldName] as $entity) {
|
||||
$this->_em->delete($entity);
|
||||
}
|
||||
}
|
||||
$this->_references[$fieldName] = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL:
|
||||
* Gets the changeset of the entities data.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
final public function _getDataChangeSet()
|
||||
{
|
||||
return $this->_dataChangeSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL:
|
||||
* Gets the changeset of the entities references to other entities.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
final public function _getReferenceChangeSet()
|
||||
{
|
||||
return $this->_referenceChangeSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the entity already has a persistent state.
|
||||
*
|
||||
* @return boolean TRUE if the object is new, FALSE otherwise.
|
||||
*/
|
||||
final public function isNew()
|
||||
{
|
||||
return $this->_state == self::STATE_NEW;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the entity has been modified since it was last synchronized
|
||||
* with the database.
|
||||
*
|
||||
* @return boolean TRUE if the object has been modified, FALSE otherwise.
|
||||
*/
|
||||
final public function isModified()
|
||||
{
|
||||
return count($this->_fieldChangeSet) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL:
|
||||
* Assigns an identifier to the entity. This is only intended for use by
|
||||
* the EntityPersisters or the UnitOfWork.
|
||||
*
|
||||
* @param mixed $id
|
||||
*/
|
||||
final public function _assignIdentifier($id)
|
||||
{
|
||||
if (is_array($id)) {
|
||||
foreach ($id as $fieldName => $value) {
|
||||
$this->_id[$fieldName] = $value;
|
||||
$this->_data[$fieldName] = $value;
|
||||
}
|
||||
} else {
|
||||
$name = $this->_class->getSingleIdentifierFieldName();
|
||||
$this->_id[$name] = $id;
|
||||
$this->_data[$name] = $id;
|
||||
}
|
||||
$this->_dataChangeSet = array();
|
||||
$this->_referenceChangeSet = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo Not yet clear if needed.
|
||||
*/
|
||||
/*final public function _setJoinColumn($columnName, $value)
|
||||
{
|
||||
$this->_joinColumns[$columnName] = $value;
|
||||
}*/
|
||||
|
||||
/**
|
||||
* @todo Not yet clear if needed.
|
||||
*/
|
||||
/*final public function _getJoinColumn($columnName)
|
||||
{
|
||||
return $this->_joinColumns[$columnName];
|
||||
}*/
|
||||
|
||||
/**
|
||||
* INTERNAL:
|
||||
* Returns the primary keys of the entity (field => value pairs).
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
final public function _identifier()
|
||||
{
|
||||
return $this->_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL:
|
||||
*
|
||||
* getReferences
|
||||
* @return array all references
|
||||
*/
|
||||
final public function _getReferences()
|
||||
{
|
||||
return $this->_references;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ClassMetadata object that describes the entity class.
|
||||
*
|
||||
* @return Doctrine::ORM::Mapping::ClassMetadata
|
||||
*/
|
||||
final public function getClass()
|
||||
{
|
||||
return $this->_class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the EntityManager that is responsible for the persistence of
|
||||
* the entity.
|
||||
*
|
||||
* @return Doctrine::ORM::EntityManager
|
||||
*/
|
||||
final public function getEntityManager()
|
||||
{
|
||||
return $this->_em;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the EntityRepository of the Entity.
|
||||
*
|
||||
* @return Doctrine::ORM::EntityRepository
|
||||
*/
|
||||
final public function getRepository()
|
||||
{
|
||||
return $this->_em->getRepository($this->_entityName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helps freeing the memory occupied by the entity.
|
||||
* Cuts all references the entity has to other entities and removes the entity
|
||||
* from the instance pool.
|
||||
* Note: The entity is no longer useable after free() has been called. Any operations
|
||||
* done with the entity afterwards can lead to unpredictable results.
|
||||
*
|
||||
* @param boolean $deep Whether to cascade the free() call to (loaded) associated entities.
|
||||
*/
|
||||
public function free($deep = false)
|
||||
{
|
||||
if ($this->_state != self::STATE_LOCKED) {
|
||||
$this->_em->detach($this);
|
||||
$this->_data = array();
|
||||
$this->_id = array();
|
||||
|
||||
if ($deep) {
|
||||
foreach ($this->_references as $name => $reference) {
|
||||
if ( ! ($reference instanceof Doctrine_Null)) {
|
||||
$reference->free($deep);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->_references = array();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an offsetExists.
|
||||
*
|
||||
* Part of the ArrayAccess implementation.
|
||||
*
|
||||
* @param mixed $offset
|
||||
* @return boolean whether or not this object contains $offset
|
||||
*/
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
return $this->_contains($offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* offsetGet an alias of get()
|
||||
*
|
||||
* Part of the ArrayAccess implementation.
|
||||
*
|
||||
* @see get, __get
|
||||
* @param mixed $offset
|
||||
* @return mixed
|
||||
*/
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
return $this->get($offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the ArrayAccess implementation.
|
||||
*
|
||||
* sets $offset to $value
|
||||
* @see set, __set
|
||||
* @param mixed $offset
|
||||
* @param mixed $value
|
||||
* @return void
|
||||
*/
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
return $this->set($offset, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the ArrayAccess implementation.
|
||||
*
|
||||
* unset a given offset
|
||||
* @see set, offsetSet, __set
|
||||
* @param mixed $offset
|
||||
*/
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
return $this->_unset($offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* __set
|
||||
*
|
||||
* @see set, offsetSet
|
||||
* @param $name
|
||||
* @param $value
|
||||
* @since 1.0
|
||||
* @return void
|
||||
*/
|
||||
public function __set($name, $value)
|
||||
{
|
||||
$this->set($name, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* __get
|
||||
*
|
||||
* @see get, offsetGet
|
||||
* @param mixed $name
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
return $this->get($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* __isset()
|
||||
*
|
||||
* @param string $name
|
||||
* @since 1.0
|
||||
* @return boolean whether or not this object contains $name
|
||||
*/
|
||||
public function __isset($name)
|
||||
{
|
||||
return $this->_contains($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* __unset()
|
||||
*
|
||||
* @param string $name
|
||||
* @since 1.0
|
||||
* @return void
|
||||
*/
|
||||
public function __unset($name)
|
||||
{
|
||||
return $this->_unset($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a string representation of this object
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return (string)$this->_oid;
|
||||
}
|
||||
}
|
||||
interface Doctrine_ORM_Entity
|
||||
{}
|
||||
|
@ -19,14 +19,14 @@
|
||||
* <http://www.phpdoctrine.org>.
|
||||
*/
|
||||
|
||||
#namespace Doctrine::ORM;
|
||||
#namespace Doctrine\ORM;
|
||||
|
||||
#use Doctrine::Common::Configuration;
|
||||
#use Doctrine::Common::EventManager;
|
||||
#use Doctrine::DBAL::Connection;
|
||||
#use Doctrine::ORM::Exceptions::EntityManagerException;
|
||||
#use Doctrine::ORM::Internal::UnitOfWork;
|
||||
#use Doctrine::ORM::Mapping::ClassMetadata;
|
||||
#use Doctrine\Common\Configuration;
|
||||
#use Doctrine\Common\EventManager;
|
||||
#use Doctrine\DBAL\Connection;
|
||||
#use Doctrine\ORM\Exceptions\EntityManagerException;
|
||||
#use Doctrine\ORM\Internal\UnitOfWork;
|
||||
#use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
|
||||
/**
|
||||
* The EntityManager is the central access point to ORM functionality.
|
||||
@ -139,8 +139,12 @@ class Doctrine_ORM_EntityManager
|
||||
*/
|
||||
private $_tmpEntityData = array();
|
||||
|
||||
private $_idGenerators = array();
|
||||
|
||||
private $_closed = false;
|
||||
|
||||
private $_originalEntityData = array();
|
||||
|
||||
/**
|
||||
* Creates a new EntityManager that operates on the given database connection.
|
||||
*
|
||||
@ -155,7 +159,8 @@ class Doctrine_ORM_EntityManager
|
||||
$this->_config = $config;
|
||||
$this->_eventManager = $eventManager;
|
||||
$this->_metadataFactory = new Doctrine_ORM_Mapping_ClassMetadataFactory(
|
||||
$this, new Doctrine_ORM_Mapping_Driver_CodeDriver());
|
||||
new Doctrine_ORM_Mapping_Driver_CodeDriver(),
|
||||
$this->_conn->getDatabasePlatform());
|
||||
$this->_unitOfWork = new Doctrine_ORM_UnitOfWork($this);
|
||||
$this->_nullObject = Doctrine_ORM_Internal_Null::$INSTANCE;
|
||||
}
|
||||
@ -170,6 +175,14 @@ class Doctrine_ORM_EntityManager
|
||||
return $this->_conn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the metadata factory used to gather the metadata of classes.
|
||||
*/
|
||||
public function getMetadataFactory()
|
||||
{
|
||||
return $this->_metadataFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the EntityManager.
|
||||
*
|
||||
@ -180,16 +193,6 @@ class Doctrine_ORM_EntityManager
|
||||
return $this->_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the metadata for a class. Alias for getClassMetadata().
|
||||
*
|
||||
* @return Doctrine_Metadata
|
||||
*/
|
||||
public function getMetadata($className)
|
||||
{
|
||||
return $this->getClassMetadata($className);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a database transaction.
|
||||
*/
|
||||
@ -224,18 +227,39 @@ class Doctrine_ORM_EntityManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the driver that is used to obtain metadata mapping information
|
||||
* about Entities.
|
||||
*
|
||||
* @param $driver The driver to use.
|
||||
* Gets an IdGenerator that can be used to generate identifiers for the specified
|
||||
* class.
|
||||
*/
|
||||
public function setClassMetadataDriver($driver)
|
||||
public function getIdGenerator($className)
|
||||
{
|
||||
$this->_metadataFactory->setDriver($driver);
|
||||
if (!isset($this->_idGenerators[$className])) {
|
||||
$this->_idGenerators[$className] = $this->_createIdGenerator(
|
||||
$this->getClassMetadata($className)->getIdGeneratorType());
|
||||
}
|
||||
return $this->_idGenerators[$className];
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Doctrine_Query object that operates on this connection.
|
||||
* Used to lazily create the id generator.
|
||||
*
|
||||
* @param string $generatorType
|
||||
* @return void
|
||||
*/
|
||||
protected function _createIdGenerator($generatorType)
|
||||
{
|
||||
if ($generatorType == Doctrine_ORM_Mapping_ClassMetadata::GENERATOR_TYPE_IDENTITY) {
|
||||
return new Doctrine_ORM_Id_IdentityGenerator($this);
|
||||
} else if ($generatorType == Doctrine_ORM_Mapping_ClassMetadata::GENERATOR_TYPE_SEQUENCE) {
|
||||
return new Doctrine_ORM_Id_SequenceGenerator($this);
|
||||
} else if ($generatorType == Doctrine_ORM_Mapping_ClassMetadata::GENERATOR_TYPE_TABLE) {
|
||||
return new Doctrine_ORM_Id_TableGenerator($this);
|
||||
} else {
|
||||
return new Doctrine_ORM_Id_Assigned($this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Query object.
|
||||
*
|
||||
* @param string The DQL string.
|
||||
* @return Doctrine::ORM::Query
|
||||
@ -405,7 +429,7 @@ class Doctrine_ORM_EntityManager
|
||||
/**
|
||||
* Saves the given entity, persisting it's state.
|
||||
*
|
||||
* @param Doctrine::ORM::Entity $entity
|
||||
* @param Doctrine\ORM\Entity $entity
|
||||
* @return void
|
||||
*/
|
||||
public function save(Doctrine_ORM_Entity $entity)
|
||||
@ -487,9 +511,9 @@ class Doctrine_ORM_EntityManager
|
||||
*
|
||||
* @param string $className The name of the entity class.
|
||||
* @param array $data The data for the entity.
|
||||
* @return Doctrine::ORM::Entity
|
||||
* @return Doctrine\ORM\Entity
|
||||
*/
|
||||
public function createEntity($className, array $data)
|
||||
public function createEntity($className, array $data, Doctrine_Query $query = null)
|
||||
{
|
||||
$this->_errorIfNotActiveOrClosed();
|
||||
|
||||
@ -512,9 +536,9 @@ class Doctrine_ORM_EntityManager
|
||||
$entity = new $className;
|
||||
} else {
|
||||
$idHash = $this->_unitOfWork->getIdentifierHash($id);
|
||||
if ($entity = $this->_unitOfWork->tryGetByIdHash($idHash,
|
||||
$classMetadata->getRootClassName())) {
|
||||
$this->_mergeData($entity, $data);
|
||||
$entity = $this->_unitOfWork->tryGetByIdHash($idHash, $classMetadata->getRootClassName());
|
||||
if ($entity) {
|
||||
$this->_mergeData($entity, $data/*, $classMetadata, $query->getHint('doctrine.refresh')*/);
|
||||
return $entity;
|
||||
} else {
|
||||
$entity = new $className;
|
||||
@ -525,6 +549,8 @@ class Doctrine_ORM_EntityManager
|
||||
$entity = new $className;
|
||||
}
|
||||
|
||||
//$this->_originalEntityData[$entity->getOid()] = $data;
|
||||
|
||||
return $entity;
|
||||
}
|
||||
|
||||
@ -532,12 +558,12 @@ class Doctrine_ORM_EntityManager
|
||||
* Merges the given data into the given entity, optionally overriding
|
||||
* local changes.
|
||||
*
|
||||
* @param Doctrine::ORM::Entity $entity
|
||||
* @param Doctrine\ORM\Entity $entity
|
||||
* @param array $data
|
||||
* @param boolean $overrideLocalChanges
|
||||
* @return void
|
||||
*/
|
||||
private function _mergeData(Doctrine_ORM_Entity $entity, array $data, $overrideLocalChanges = false) {
|
||||
private function _mergeData(Doctrine_ORM_Entity $entity, /*$class,*/ array $data, $overrideLocalChanges = false) {
|
||||
if ($overrideLocalChanges) {
|
||||
foreach ($data as $field => $value) {
|
||||
$entity->_internalSetField($field, $value);
|
||||
@ -550,6 +576,21 @@ class Doctrine_ORM_EntityManager
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NEW
|
||||
/*if ($overrideLocalChanges) {
|
||||
foreach ($data as $field => $value) {
|
||||
$class->getReflectionProperty($field)->setValue($entity, $value);
|
||||
}
|
||||
} else {
|
||||
foreach ($data as $field => $value) {
|
||||
$currentValue = $class->getReflectionProperty($field)->getValue($entity);
|
||||
if ( ! isset($this->_originalEntityData[$entity->getOid()]) ||
|
||||
$currentValue == $this->_originalEntityData[$entity->getOid()]) {
|
||||
$class->getReflectionProperty($field)->setValue($entity, $value);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
/**
|
||||
@ -628,6 +669,8 @@ class Doctrine_ORM_EntityManager
|
||||
|
||||
/**
|
||||
* Throws an exception if the EntityManager is closed or currently not active.
|
||||
*
|
||||
* @throws EntityManagerException If the EntityManager is closed or not active.
|
||||
*/
|
||||
private function _errorIfNotActiveOrClosed()
|
||||
{
|
||||
@ -668,15 +711,16 @@ class Doctrine_ORM_EntityManager
|
||||
|
||||
/**
|
||||
* Factory method to create EntityManager instances.
|
||||
*
|
||||
* A newly created EntityManager is immediately activated, making it the
|
||||
* currently active EntityManager.
|
||||
*
|
||||
* @param mixed $conn An array with the connection parameters or an existing
|
||||
* Doctrine::DBAL::Connection instance.
|
||||
* @param string $name
|
||||
* @param Doctrine::Common::Configuration $config The Configuration instance to use.
|
||||
* @param Doctrine::Common::EventManager $eventManager The EventManager instance to use.
|
||||
* @return Doctrine::ORM::EntityManager The created EntityManager.
|
||||
* Connection instance.
|
||||
* @param string $name The name of the EntityManager.
|
||||
* @param Configuration $config The Configuration instance to use.
|
||||
* @param EventManager $eventManager The EventManager instance to use.
|
||||
* @return EntityManager The created EntityManager.
|
||||
*/
|
||||
public static function create($conn, $name, Doctrine_Common_Configuration $config = null,
|
||||
Doctrine_Common_EventManager $eventManager = null)
|
||||
@ -702,8 +746,6 @@ class Doctrine_ORM_EntityManager
|
||||
|
||||
/**
|
||||
* Static lookup to get the currently active EntityManager.
|
||||
* This is used in the Entity constructor as well as unserialize() to connect
|
||||
* the Entity with an EntityManager.
|
||||
*
|
||||
* @return Doctrine::ORM::EntityManager
|
||||
*/
|
||||
|
@ -18,7 +18,7 @@ abstract class Doctrine_ORM_Id_AbstractIdGenerator
|
||||
$this->_em = $em;
|
||||
}
|
||||
|
||||
abstract public function generate(Doctrine_ORM_Entity $entity);
|
||||
abstract public function generate($entity);
|
||||
}
|
||||
|
||||
?>
|
@ -14,11 +14,12 @@ class Doctrine_ORM_Id_Assigned extends Doctrine_ORM_Id_AbstractIdGenerator
|
||||
* @return unknown
|
||||
* @override
|
||||
*/
|
||||
public function generate(Doctrine_ORM_Entity $entity)
|
||||
public function generate($entity)
|
||||
{
|
||||
if ( ! $entity->_identifier()) {
|
||||
throw Doctrine_IdException::missingAssignedId($entity);
|
||||
throw new Doctrine_Exception("Entity '$entity' is missing an assigned Id");
|
||||
}
|
||||
return $entity->_identifier();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@ class Doctrine_ORM_Id_IdentityGenerator extends Doctrine_ORM_Id_AbstractIdGenera
|
||||
* @return unknown
|
||||
* @override
|
||||
*/
|
||||
public function generate(Doctrine_ORM_Entity $entity)
|
||||
public function generate($entity)
|
||||
{
|
||||
return self::POST_INSERT_INDICATOR;
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ class Doctrine_ORM_Id_SequenceGenerator extends Doctrine_ORM_Id_AbstractIdGenera
|
||||
* @param Doctrine_ORM_Entity $entity
|
||||
* @override
|
||||
*/
|
||||
public function generate(Doctrine_ORM_Entity $entity)
|
||||
public function generate($entity)
|
||||
{
|
||||
$conn = $this->_em->getConnection();
|
||||
$sql = $conn->getDatabasePlatform()->getSequenceNextValSql($this->_sequenceName);
|
||||
|
@ -8,7 +8,7 @@
|
||||
class Doctrine_ORM_Id_TableGenerator extends Doctrine_ORM_Id_AbstractIdGenerator
|
||||
{
|
||||
|
||||
public function generate(Doctrine_ORM_Entity $entity)
|
||||
public function generate($entity)
|
||||
{
|
||||
throw new Exception("Not implemented");
|
||||
}
|
||||
|
@ -129,6 +129,38 @@ class Doctrine_ORM_Internal_Hydration_ArrayDriver
|
||||
return key($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the result pointer for an Entity. The result pointers point to the
|
||||
* last seen instance of each Entity type. This is used for graph construction.
|
||||
*
|
||||
* @param array $resultPointers The result pointers.
|
||||
* @param array|Collection $coll The element.
|
||||
* @param boolean|integer $index Index of the element in the collection.
|
||||
* @param string $dqlAlias
|
||||
* @param boolean $oneToOne Whether it is a single-valued association or not.
|
||||
*/
|
||||
public function updateResultPointer(&$resultPointers, &$coll, $index, $dqlAlias, $oneToOne)
|
||||
{
|
||||
if ($coll === null) {
|
||||
unset($resultPointers[$dqlAlias]); // Ticket #1228
|
||||
return;
|
||||
}
|
||||
|
||||
if ($index !== false) {
|
||||
$resultPointers[$dqlAlias] =& $coll[$index];
|
||||
return;
|
||||
}
|
||||
|
||||
if ($coll) {
|
||||
if ($oneToOne) {
|
||||
$resultPointers[$dqlAlias] =& $coll;
|
||||
} else {
|
||||
end($coll);
|
||||
$resultPointers[$dqlAlias] =& $coll[key($coll)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -19,7 +19,7 @@
|
||||
* <http://www.phpdoctrine.org>.
|
||||
*/
|
||||
|
||||
#namespace Doctrine::ORM::Internal::Hydration;
|
||||
#namespace Doctrine\ORM\Internal\Hydration;
|
||||
|
||||
/**
|
||||
* Hydration strategy used for creating graphs of entities.
|
||||
@ -41,6 +41,7 @@ class Doctrine_ORM_Internal_Hydration_ObjectDriver
|
||||
private $_nullObject;
|
||||
/** The EntityManager */
|
||||
private $_em;
|
||||
private $_metadataMap = array();
|
||||
|
||||
public function __construct(Doctrine_ORM_EntityManager $em)
|
||||
{
|
||||
@ -52,32 +53,36 @@ class Doctrine_ORM_Internal_Hydration_ObjectDriver
|
||||
{
|
||||
$coll = new Doctrine_ORM_Collection($component);
|
||||
$this->_collections[] = $coll;
|
||||
|
||||
return $coll;
|
||||
}
|
||||
|
||||
public function getLastKey($coll)
|
||||
{
|
||||
// check needed because of mixed results
|
||||
if (is_array($coll)) {
|
||||
end($coll);
|
||||
return key($coll);
|
||||
} else {
|
||||
// check needed because of mixed results.
|
||||
// is_object instead of is_array because is_array is slow.
|
||||
if (is_object($coll)) {
|
||||
$coll->end();
|
||||
return $coll->key();
|
||||
} else {
|
||||
end($coll);
|
||||
return key($coll);
|
||||
}
|
||||
}
|
||||
|
||||
public function initRelatedCollection(Doctrine_ORM_Entity $entity, $name)
|
||||
public function initRelatedCollection($entity, $name)
|
||||
{
|
||||
if ( ! isset($this->_initializedRelations[$entity->getOid()][$name])) {
|
||||
$relation = $entity->getClass()->getAssociationMapping($name);
|
||||
//$class = get_class($entity);
|
||||
$oid = spl_object_id($entity);
|
||||
$classMetadata = $this->_metadataMap[$oid];
|
||||
//$classMetadata = $this->_em->getClassMetadata(get_class($entity));
|
||||
if ( ! isset($this->_initializedRelations[$oid][$name])) {
|
||||
$relation = $classMetadata->getAssociationMapping($name);
|
||||
$relatedClass = $this->_em->getClassMetadata($relation->getTargetEntityName());
|
||||
$coll = $this->getElementCollection($relatedClass->getClassName());
|
||||
$coll->_setOwner($entity, $relation);
|
||||
$coll->_setHydrationFlag(true);
|
||||
$entity->_internalSetReference($name, $coll, true);
|
||||
$this->_initializedRelations[$entity->getOid()][$name] = true;
|
||||
$classMetadata->getReflectionProperty($name)->setValue($entity, $coll);
|
||||
$this->_initializedRelations[$oid][$name] = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,49 +98,91 @@ class Doctrine_ORM_Internal_Hydration_ObjectDriver
|
||||
|
||||
public function getElement(array $data, $className)
|
||||
{
|
||||
return $this->_em->createEntity($className, $data);
|
||||
$entity = $this->_em->getUnitOfWork()->createEntity($className, $data);
|
||||
|
||||
$this->_metadataMap[spl_object_id($entity)] = $this->_em->getClassMetadata($className);
|
||||
|
||||
return $entity;
|
||||
}
|
||||
|
||||
public function addRelatedIndexedElement(Doctrine_ORM_Entity $entity1, $property,
|
||||
Doctrine_ORM_Entity $entity2, $indexField)
|
||||
public function addRelatedIndexedElement($entity1, $property, $entity2, $indexField)
|
||||
{
|
||||
$entity1->_internalGetReference($property)->add($entity2, $entity2->_internalGetField($indexField));
|
||||
$classMetadata1 = $this->_metadataMap[spl_object_id($entity1)];
|
||||
$classMetadata2 = $this->_metadataMap[spl_object_id($entity2)];
|
||||
//$classMetadata1 = $this->_em->getClassMetadata(get_class($entity1));
|
||||
//$classMetadata2 = $this->_em->getClassMetadata(get_class($entity2));
|
||||
$indexValue = $classMetadata2->getReflectionProperty($indexField)->getValue($entity2);
|
||||
$classMetadata1->getReflectionProperty($property)->getValue($entity1)->add($entity2, $indexValue);
|
||||
}
|
||||
|
||||
public function addRelatedElement(Doctrine_ORM_Entity $entity1, $property,
|
||||
Doctrine_ORM_Entity $entity2)
|
||||
public function addRelatedElement($entity1, $property, $entity2)
|
||||
{
|
||||
$entity1->_internalGetReference($property)->add($entity2);
|
||||
$classMetadata1 = $this->_metadataMap[spl_object_id($entity1)];
|
||||
//$classMetadata1 = $this->_em->getClassMetadata(get_class($entity1));
|
||||
$classMetadata1->getReflectionProperty($property)
|
||||
->getValue($entity1)->add($entity2);
|
||||
}
|
||||
|
||||
public function setRelatedElement(Doctrine_ORM_Entity $entity1, $property, $entity2)
|
||||
public function setRelatedElement($entity1, $property, $entity2)
|
||||
{
|
||||
$entity1->_internalSetReference($property, $entity2, true);
|
||||
$classMetadata1 = $this->_metadataMap[spl_object_id($entity1)];
|
||||
//$classMetadata1 = $this->_em->getClassMetadata(get_class($entity1));
|
||||
$classMetadata1->getReflectionProperty($property)
|
||||
->setValue($entity1, $entity2);
|
||||
$relation = $classMetadata1->getAssociationMapping($property);
|
||||
if ($relation->isOneToOne()) {
|
||||
$targetClass = $this->_em->getClassMetadata($relation->getTargetEntityName());
|
||||
if ($relation->isOwningSide()) {
|
||||
// If there is an inverse mapping on the target class its bidirectional
|
||||
if ($targetClass->hasInverseAssociationMapping($property)) {
|
||||
$refProp = $targetClass->getReflectionProperty(
|
||||
$targetClass->getInverseAssociationMapping($fieldName)
|
||||
->getSourceFieldName());
|
||||
$refProp->setValue($entity2, $entity1);
|
||||
}
|
||||
} else {
|
||||
// for sure bidirectional, as there is no inverse side in unidirectional
|
||||
$targetClass->getReflectionProperty($relation->getMappedByFieldName())
|
||||
->setValue($entity2, $entity1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function isIndexKeyInUse(Doctrine_ORM_Entity $entity, $assocField, $indexField)
|
||||
public function isIndexKeyInUse($entity, $assocField, $indexField)
|
||||
{
|
||||
return $entity->_internalGetReference($assocField)->contains($indexField);
|
||||
return $this->_metadataMap[spl_object_id($entity)]->getReflectionProperty($assocField)
|
||||
->getValue($entity)->containsKey($indexField);
|
||||
/*return $this->_em->getClassMetadata(get_class($entity))->getReflectionProperty($assocField)
|
||||
->getValue($entity)->containsKey($indexField);*/
|
||||
}
|
||||
|
||||
public function isFieldSet(Doctrine_ORM_Entity $entity, $field)
|
||||
public function isFieldSet($entity, $field)
|
||||
{
|
||||
return $entity->contains($field);
|
||||
return $this->_metadataMap[spl_object_id($entity)]->getReflectionProperty($field)
|
||||
->getValue($entity) !== null;
|
||||
/*return $this->_em->getClassMetadata(get_class($entity))->getReflectionProperty($field)
|
||||
->getValue($entity) !== null;*/
|
||||
}
|
||||
|
||||
public function getFieldValue(Doctrine_ORM_Entity $entity, $field)
|
||||
public function getFieldValue($entity, $field)
|
||||
{
|
||||
return $entity->_internalGetField($field);
|
||||
return $this->_metadataMap[spl_object_id($entity)]->getReflectionProperty($field)
|
||||
->getValue($entity);
|
||||
/*return $this->_em->getClassMetadata(get_class($entity))->getReflectionProperty($field)
|
||||
->getValue($entity);*/
|
||||
}
|
||||
|
||||
public function getReferenceValue(Doctrine_ORM_Entity $entity, $field)
|
||||
public function getReferenceValue($entity, $field)
|
||||
{
|
||||
return $entity->_internalGetReference($field);
|
||||
return $this->_metadataMap[spl_object_id($entity)]->getReflectionProperty($field)
|
||||
->getValue($entity);
|
||||
/*return $this->_em->getClassMetadata(get_class($entity))->getReflectionProperty($field)
|
||||
->getValue($entity);*/
|
||||
}
|
||||
|
||||
public function addElementToIndexedCollection($coll, $entity, $keyField)
|
||||
{
|
||||
$coll->add($entity, $entity->_internalGetField($keyField));
|
||||
$coll->add($entity, $this->getFieldValue($entity, $keyField));
|
||||
}
|
||||
|
||||
public function addElementToCollection($coll, $entity)
|
||||
@ -143,6 +190,40 @@ class Doctrine_ORM_Internal_Hydration_ObjectDriver
|
||||
$coll->add($entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the result pointer for an Entity. The result pointers point to the
|
||||
* last seen instance of each Entity type. This is used for graph construction.
|
||||
*
|
||||
* @param array $resultPointers The result pointers.
|
||||
* @param array|Collection $coll The element.
|
||||
* @param boolean|integer $index Index of the element in the collection.
|
||||
* @param string $dqlAlias
|
||||
* @param boolean $oneToOne Whether it is a single-valued association or not.
|
||||
*/
|
||||
public function updateResultPointer(&$resultPointers, &$coll, $index, $dqlAlias, $oneToOne)
|
||||
{
|
||||
if ($coll === $this->_nullObject) {
|
||||
unset($resultPointers[$dqlAlias]); // Ticket #1228
|
||||
return;
|
||||
}
|
||||
|
||||
if ($index !== false) {
|
||||
$resultPointers[$dqlAlias] = $coll[$index];
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! is_object($coll)) {
|
||||
end($coll);
|
||||
$resultPointers[$dqlAlias] =& $coll[key($coll)];
|
||||
} else if ($coll instanceof Doctrine_ORM_Collection) {
|
||||
if (count($coll) > 0) {
|
||||
$resultPointers[$dqlAlias] = $coll->getLast();
|
||||
}
|
||||
} else {
|
||||
$resultPointers[$dqlAlias] = $coll;
|
||||
}
|
||||
}
|
||||
|
||||
public function flush()
|
||||
{
|
||||
// take snapshots from all initialized collections
|
||||
@ -152,6 +233,7 @@ class Doctrine_ORM_Internal_Hydration_ObjectDriver
|
||||
}
|
||||
$this->_collections = array();
|
||||
$this->_initializedRelations = array();
|
||||
$this->_metadataMap = array();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -19,7 +19,7 @@
|
||||
* <http://www.phpdoctrine.org>.
|
||||
*/
|
||||
|
||||
#namespace Doctrine::ORM::Internal::Hydration;
|
||||
#namespace Doctrine\ORM\Internal\Hydration;
|
||||
|
||||
/**
|
||||
* The hydrator has the tedious to process result sets returned by the database
|
||||
@ -104,7 +104,6 @@ class Doctrine_ORM_Internal_Hydration_StandardHydrator extends Doctrine_ORM_Inte
|
||||
|
||||
$s = microtime(true);
|
||||
|
||||
// Used variables during hydration
|
||||
reset($this->_queryComponents);
|
||||
$rootAlias = key($this->_queryComponents);
|
||||
$rootEntityName = $this->_queryComponents[$rootAlias]['metadata']->getClassName();
|
||||
@ -136,8 +135,7 @@ class Doctrine_ORM_Internal_Hydration_StandardHydrator extends Doctrine_ORM_Inte
|
||||
// Initialize
|
||||
foreach ($this->_queryComponents as $dqlAlias => $component) {
|
||||
// disable lazy-loading of related elements during hydration
|
||||
$component['metadata']->setAttribute('loadReferences', false);
|
||||
$entityName = $component['metadata']->getClassName();
|
||||
//$component['metadata']->setAttribute('loadReferences', false);
|
||||
$identifierMap[$dqlAlias] = array();
|
||||
$resultPointers[$dqlAlias] = array();
|
||||
$idTemplate[$dqlAlias] = '';
|
||||
@ -147,6 +145,7 @@ class Doctrine_ORM_Internal_Hydration_StandardHydrator extends Doctrine_ORM_Inte
|
||||
// Evaluate HYDRATE_SINGLE_SCALAR
|
||||
if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_SINGLE_SCALAR) {
|
||||
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
//TODO: Let this exception be raised by Query as QueryException
|
||||
if (count($result) > 1 || count($result[0]) > 1) {
|
||||
throw Doctrine_ORM_Exceptions_HydrationException::nonUniqueResult();
|
||||
}
|
||||
@ -193,7 +192,7 @@ class Doctrine_ORM_Internal_Hydration_StandardHydrator extends Doctrine_ORM_Inte
|
||||
} else {
|
||||
$index = $identifierMap[$rootAlias][$id[$rootAlias]];
|
||||
}
|
||||
$this->_updateResultPointer($resultPointers, $result, $index, $rootAlias, false);
|
||||
$driver->updateResultPointer($resultPointers, $result, $index, $rootAlias, false);
|
||||
unset($rowData[$rootAlias]);
|
||||
// end hydrate data of the root component for the current row
|
||||
|
||||
@ -211,10 +210,11 @@ class Doctrine_ORM_Internal_Hydration_StandardHydrator extends Doctrine_ORM_Inte
|
||||
$entityName = $map['metadata']->getClassName();
|
||||
$parent = $map['parent'];
|
||||
$relation = $map['relation'];
|
||||
$relationAlias = $relation->getSourceFieldName();//$relation->getAlias();
|
||||
$relationAlias = $relation->getSourceFieldName();
|
||||
$path = $parent . '.' . $dqlAlias;
|
||||
|
||||
// pick the right element that will get the associated element attached
|
||||
// Get a reference to the right element in the result tree.
|
||||
// This element will get the associated element attached.
|
||||
if ($parserResult->isMixedQuery() && $parent == $rootAlias) {
|
||||
$key = key(reset($resultPointers));
|
||||
// TODO: Exception if $key === null ?
|
||||
@ -228,13 +228,13 @@ class Doctrine_ORM_Internal_Hydration_StandardHydrator extends Doctrine_ORM_Inte
|
||||
|
||||
// check the type of the relation (many or single-valued)
|
||||
if ( ! $relation->isOneToOne()) {
|
||||
// x-many relation
|
||||
// x-to-many relation
|
||||
$oneToOne = false;
|
||||
if (isset($nonemptyComponents[$dqlAlias])) {
|
||||
$driver->initRelatedCollection($baseElement, $relationAlias);
|
||||
$indexExists = isset($identifierMap[$path][$id[$parent]][$id[$dqlAlias]]);
|
||||
$index = $indexExists ? $identifierMap[$path][$id[$parent]][$id[$dqlAlias]] : false;
|
||||
$indexIsValid = $index !== false ? isset($baseElement[$relationAlias][$index]) : false;
|
||||
$indexIsValid = $index !== false ? $driver->isIndexKeyInUse($baseElement, $relationAlias, $index) : false;
|
||||
if ( ! $indexExists || ! $indexIsValid) {
|
||||
$element = $driver->getElement($data, $entityName);
|
||||
if ($field = $this->_getCustomIndexField($dqlAlias)) {
|
||||
@ -245,7 +245,7 @@ class Doctrine_ORM_Internal_Hydration_StandardHydrator extends Doctrine_ORM_Inte
|
||||
$identifierMap[$path][$id[$parent]][$id[$dqlAlias]] = $driver->getLastKey(
|
||||
$driver->getReferenceValue($baseElement, $relationAlias));
|
||||
}
|
||||
} else if ( ! isset($baseElement[$relationAlias])) {
|
||||
} else if ( ! $driver->isFieldSet($baseElement, $relationAlias)) {
|
||||
if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_ARRAY) {
|
||||
$baseElement[$relationAlias] = array();
|
||||
} else {
|
||||
@ -254,7 +254,7 @@ class Doctrine_ORM_Internal_Hydration_StandardHydrator extends Doctrine_ORM_Inte
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// x-1 relation
|
||||
// x-to-one relation
|
||||
$oneToOne = true;
|
||||
if ( ! isset($nonemptyComponents[$dqlAlias]) &&
|
||||
! $driver->isFieldSet($baseElement, $relationAlias)) {
|
||||
@ -269,15 +269,17 @@ class Doctrine_ORM_Internal_Hydration_StandardHydrator extends Doctrine_ORM_Inte
|
||||
if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_ARRAY) {
|
||||
$coll =& $baseElement[$relationAlias];
|
||||
} else {
|
||||
$coll = $baseElement->_internalGetReference($relationAlias);
|
||||
$coll = $driver->getReferenceValue($baseElement, $relationAlias);
|
||||
//$baseElement->_internalGetReference($relationAlias);
|
||||
}
|
||||
|
||||
if ($coll !== null) {
|
||||
$this->_updateResultPointer($resultPointers, $coll, $index, $dqlAlias, $oneToOne);
|
||||
$driver->updateResultPointer($resultPointers, $coll, $index, $dqlAlias, $oneToOne);
|
||||
}
|
||||
}
|
||||
|
||||
// append scalar values to mixed result sets
|
||||
// Append scalar values to mixed result sets
|
||||
//TODO: we dont need to count every time here, instead count with the loop
|
||||
if (isset($scalars)) {
|
||||
$rowNumber = count($result) - 1;
|
||||
foreach ($scalars as $name => $value) {
|
||||
@ -289,53 +291,17 @@ class Doctrine_ORM_Internal_Hydration_StandardHydrator extends Doctrine_ORM_Inte
|
||||
$stmt->closeCursor();
|
||||
$driver->flush();
|
||||
|
||||
// re-enable lazy loading
|
||||
/*// re-enable lazy loading
|
||||
foreach ($this->_queryComponents as $dqlAlias => $data) {
|
||||
$data['metadata']->setAttribute('loadReferences', true);
|
||||
}
|
||||
}*/
|
||||
|
||||
$e = microtime(true);
|
||||
echo 'Hydration took: ' . ($e - $s) . ' for '.count($result).' records' . PHP_EOL;
|
||||
echo 'Hydration took: ' . ($e - $s) . PHP_EOL;
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the result pointer for an Entity. The result pointers point to the
|
||||
* last seen instance of each Entity type. This is used for graph construction.
|
||||
*
|
||||
* @param array $resultPointers The result pointers.
|
||||
* @param array|Collection $coll The element.
|
||||
* @param boolean|integer $index Index of the element in the collection.
|
||||
* @param string $dqlAlias
|
||||
* @param boolean $oneToOne Whether it is a single-valued association or not.
|
||||
*/
|
||||
protected function _updateResultPointer(&$resultPointers, &$coll, $index, $dqlAlias, $oneToOne)
|
||||
{
|
||||
if ($coll === $this->_nullObject || $coll === null) {
|
||||
unset($resultPointers[$dqlAlias]); // Ticket #1228
|
||||
return;
|
||||
}
|
||||
|
||||
if ($index !== false) {
|
||||
$resultPointers[$dqlAlias] =& $coll[$index];
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_array($coll) && $coll) {
|
||||
if ($oneToOne) {
|
||||
$resultPointers[$dqlAlias] =& $coll;
|
||||
} else {
|
||||
end($coll);
|
||||
$resultPointers[$dqlAlias] =& $coll[key($coll)];
|
||||
}
|
||||
} else if ($coll instanceof Doctrine_ORM_Entity) {
|
||||
$resultPointers[$dqlAlias] = $coll;
|
||||
} else if (count($coll) > 0) {
|
||||
$resultPointers[$dqlAlias] = $coll->getLast();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a row of the result set.
|
||||
* Used for identity hydration (HYDRATE_IDENTITY_OBJECT and HYDRATE_IDENTITY_ARRAY).
|
||||
@ -370,7 +336,7 @@ class Doctrine_ORM_Internal_Hydration_StandardHydrator extends Doctrine_ORM_Inte
|
||||
$fieldName = $this->_queryComponents[$cache[$key]['dqlAlias']]['agg'][$columnName];
|
||||
$cache[$key]['isScalar'] = true;
|
||||
} else {
|
||||
$fieldName = $classMetadata->lookupFieldName($columnName);
|
||||
$fieldName = $this->_lookupFieldName($classMetadata, $columnName);
|
||||
$cache[$key]['isScalar'] = false;
|
||||
}
|
||||
|
||||
@ -455,7 +421,7 @@ class Doctrine_ORM_Internal_Hydration_StandardHydrator extends Doctrine_ORM_Inte
|
||||
$fieldName = $this->_queryComponents[$cache[$key]['dqlAlias']]['agg'][$columnName];
|
||||
$cache[$key]['isScalar'] = true;
|
||||
} else {
|
||||
$fieldName = $classMetadata->lookupFieldName($columnName);
|
||||
$fieldName = $this->_lookupFieldName($classMetadata, $columnName);
|
||||
$cache[$key]['isScalar'] = false;
|
||||
}
|
||||
|
||||
@ -511,6 +477,42 @@ class Doctrine_ORM_Internal_Hydration_StandardHydrator extends Doctrine_ORM_Inte
|
||||
return $name == 'doctrine_rownum';
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up the field name for a (lowercased) column name.
|
||||
*
|
||||
* This is mostly used during hydration, because we want to make the
|
||||
* conversion to field names while iterating over the result set for best
|
||||
* performance. By doing this at that point, we can avoid re-iterating over
|
||||
* the data just to convert the column names to field names.
|
||||
*
|
||||
* However, when this is happening, we don't know the real
|
||||
* class name to instantiate yet (the row data may target a sub-type), hence
|
||||
* this method looks up the field name in the subclass mappings if it's not
|
||||
* found on this class mapping.
|
||||
* This lookup on subclasses is costly but happens only *once* for a column
|
||||
* during hydration because the hydrator caches effectively.
|
||||
*
|
||||
* @return string The field name.
|
||||
* @throws Doctrine::ORM::Exceptions::ClassMetadataException If the field name could
|
||||
* not be found.
|
||||
*/
|
||||
private function _lookupFieldName($class, $lcColumnName)
|
||||
{
|
||||
if ($class->hasLowerColumn($lcColumnName)) {
|
||||
return $class->getFieldNameForLowerColumnName($lcColumnName);
|
||||
}
|
||||
|
||||
foreach ($class->getSubclasses() as $subClass) {
|
||||
$subClassMetadata = Doctrine_ORM_Mapping_ClassMetadataFactory::getInstance()
|
||||
->getMetadataFor($subClass);
|
||||
if ($subClassMetadata->hasLowerColumn($lcColumnName)) {
|
||||
return $subClassMetadata->getFieldNameForLowerColumnName($lcColumnName);
|
||||
}
|
||||
}
|
||||
|
||||
throw new Doctrine_Exception("No field name found for column name '$lcColumnName' during hydration.");
|
||||
}
|
||||
|
||||
/**
|
||||
* prepareValue
|
||||
* this method performs special data preparation depending on
|
||||
|
@ -19,7 +19,7 @@
|
||||
* <http://www.phpdoctrine.org>.
|
||||
*/
|
||||
|
||||
#namespace Doctrine::ORM::Mapping;
|
||||
#namespace Doctrine\ORM\Mapping;
|
||||
|
||||
/**
|
||||
* Base class for association mappings.
|
||||
|
@ -19,9 +19,10 @@
|
||||
* <http://www.phpdoctrine.org>.
|
||||
*/
|
||||
|
||||
#namespace Doctrine::ORM::Mapping;
|
||||
#namespace Doctrine\ORM\Mapping;
|
||||
|
||||
#use Doctrine::ORM::EntityManager;
|
||||
#use \Serializable;
|
||||
#use Doctrine\Common\ClassMetadata;
|
||||
|
||||
/**
|
||||
* A <tt>ClassMetadata</tt> instance holds all the information (metadata) of an entity and
|
||||
@ -32,7 +33,8 @@
|
||||
* @since 2.0
|
||||
* @todo Rename to ClassDescriptor.
|
||||
*/
|
||||
class Doctrine_ORM_Mapping_ClassMetadata implements Doctrine_Common_Configurable, Serializable
|
||||
class Doctrine_ORM_Mapping_ClassMetadata extends Doctrine_Common_ClassMetadata
|
||||
implements Doctrine_Common_Configurable, Serializable
|
||||
{
|
||||
/* The inheritance mapping types */
|
||||
/**
|
||||
@ -101,13 +103,6 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Doctrine_Common_Configurable
|
||||
*/
|
||||
const ENTITY_TYPE_MAPPED_SUPERCLASS = 'mappedSuperclass';
|
||||
|
||||
/**
|
||||
* The name of the entity class.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_entityName;
|
||||
|
||||
/**
|
||||
* The name of the entity class that is at the root of the entity inheritance
|
||||
* hierarchy. If the entity is not part of an inheritance hierarchy this is the same
|
||||
@ -118,20 +113,13 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Doctrine_Common_Configurable
|
||||
protected $_rootEntityName;
|
||||
|
||||
/**
|
||||
* The name of the custom mapper class used for the entity class.
|
||||
* The name of the custom repository class used for the entity class.
|
||||
* (Optional).
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_customRepositoryClassName;
|
||||
|
||||
/**
|
||||
* The EntityManager.
|
||||
*
|
||||
* @var Doctrine::ORM::EntityManager
|
||||
*/
|
||||
protected $_em;
|
||||
|
||||
/**
|
||||
* The names of the parent classes (ancestors).
|
||||
*
|
||||
@ -168,13 +156,6 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Doctrine_Common_Configurable
|
||||
*/
|
||||
protected $_generatorType = self::GENERATOR_TYPE_NONE;
|
||||
|
||||
/**
|
||||
* The Id generator.
|
||||
*
|
||||
* @var Doctrine::ORM::Id::IdGenerator
|
||||
*/
|
||||
protected $_idGenerator;
|
||||
|
||||
/**
|
||||
* The field mappings of the class.
|
||||
* Keys are field names and values are mapping definitions.
|
||||
@ -233,21 +214,6 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Doctrine_Common_Configurable
|
||||
*/
|
||||
protected $_fieldMappings = array();
|
||||
|
||||
/**
|
||||
* The mapped embedded values (value objects).
|
||||
*
|
||||
* @var array
|
||||
* @TODO Implementation (Value Object support)
|
||||
*/
|
||||
//protected $_embeddedValueMappings = array();
|
||||
|
||||
/**
|
||||
* Enter description here...
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_attributes = array('loadReferences' => true);
|
||||
|
||||
/**
|
||||
* An array of field names. used to look up field names from column names.
|
||||
* Keys are column names and values are field names.
|
||||
@ -347,30 +313,40 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Doctrine_Common_Configurable
|
||||
*/
|
||||
protected $_isIdentifierComposite = false;
|
||||
|
||||
protected $_customAssociationAccessors = array();
|
||||
protected $_customAssociationMutators = array();
|
||||
protected $_reflectionClass;
|
||||
protected $_reflectionProperties;
|
||||
|
||||
/**
|
||||
* Constructs a new ClassMetadata instance.
|
||||
*
|
||||
* @param string $entityName Name of the entity class the metadata info is used for.
|
||||
* @param Doctrine::ORM::Entitymanager $em
|
||||
*/
|
||||
public function __construct($entityName, Doctrine_ORM_EntityManager $em)
|
||||
public function __construct($entityName)
|
||||
{
|
||||
$this->_entityName = $entityName;
|
||||
parent::__construct($entityName);
|
||||
$this->_rootEntityName = $entityName;
|
||||
$this->_em = $em;
|
||||
$this->_reflectionClass = new ReflectionClass($entityName);
|
||||
$reflectionProps = $this->_reflectionClass->getProperties();
|
||||
foreach ($reflectionProps as $prop) {
|
||||
$prop->setAccessible(true);
|
||||
$this->_reflectionProperties[$prop->getName()] = $prop;
|
||||
}
|
||||
//$this->_isVirtualPropertyObject = is_subclass_of($entityName, 'Doctrine\Common\VirtualPropertyObject');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the EntityManager that holds this ClassMetadata.
|
||||
*
|
||||
* @return Doctrine::ORM::EntityManager
|
||||
*/
|
||||
public function getEntityManager()
|
||||
public function getReflectionClass()
|
||||
{
|
||||
return $this->_em;
|
||||
return $this->_reflectionClass;
|
||||
}
|
||||
|
||||
public function getReflectionProperties()
|
||||
{
|
||||
return $this->_reflectionProperties;
|
||||
}
|
||||
|
||||
public function getReflectionProperty($name)
|
||||
{
|
||||
return $this->_reflectionProperties[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
@ -447,7 +423,6 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Doctrine_Common_Configurable
|
||||
public function isNotNull($fieldName)
|
||||
{
|
||||
$mapping = $this->getFieldMapping($fieldName);
|
||||
|
||||
if ($mapping !== false) {
|
||||
return isset($mapping['notnull']) && $mapping['notnull'] == true;
|
||||
}
|
||||
@ -455,34 +430,6 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Doctrine_Common_Configurable
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* adds an index to this table
|
||||
*
|
||||
* @return void
|
||||
* @deprecated
|
||||
* @todo Should be done through setTableOption().
|
||||
*/
|
||||
public function addIndex($index, array $definition)
|
||||
{
|
||||
$this->_tableOptions['indexes'][$index] = $definition;
|
||||
}
|
||||
|
||||
/**
|
||||
* getIndex
|
||||
*
|
||||
* @return array|boolean array on success, FALSE on failure
|
||||
* @todo Should be done through getTableOption().
|
||||
* @deprecated
|
||||
*/
|
||||
public function getIndex($index)
|
||||
{
|
||||
if (isset($this->_tableOptions['indexes'][$index])) {
|
||||
return $this->_tableOptions['indexes'][$index];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a table option.
|
||||
*/
|
||||
@ -547,11 +494,6 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Doctrine_Common_Configurable
|
||||
return $this->_fieldMappings[$fieldName];
|
||||
}
|
||||
|
||||
public function addFieldMapping($fieldName, array $mapping)
|
||||
{
|
||||
$this->_fieldMappings[$fieldName] = $mapping;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the mapping of an association.
|
||||
*
|
||||
@ -562,7 +504,7 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Doctrine_Common_Configurable
|
||||
public function getAssociationMapping($fieldName)
|
||||
{
|
||||
if ( ! isset($this->_associationMappings[$fieldName])) {
|
||||
throw Doctrine_MappingException::mappingNotFound($fieldName);
|
||||
throw new Doctrine_Exception("Mapping not found: $fieldName");
|
||||
}
|
||||
|
||||
return $this->_associationMappings[$fieldName];
|
||||
@ -579,7 +521,6 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Doctrine_Common_Configurable
|
||||
if ( ! isset($this->_associationMappings[$fieldName])) {
|
||||
throw Doctrine_MappingException::mappingNotFound($fieldName);
|
||||
}
|
||||
|
||||
return $this->_inverseMappings[$mappedByFieldName];
|
||||
}
|
||||
|
||||
@ -594,11 +535,6 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Doctrine_Common_Configurable
|
||||
return isset($this->_inverseMappings[$mappedByFieldName]);
|
||||
}
|
||||
|
||||
public function addAssociationMapping($fieldName, Doctrine_Association $assoc)
|
||||
{
|
||||
$this->_associationMappings[$fieldName] = $assoc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all association mappings of the class.
|
||||
*
|
||||
@ -647,51 +583,16 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Doctrine_Common_Configurable
|
||||
$this->_lcColumnToFieldNames[$lcColumnName] : $lcColumnName;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param <type> $lcColumnName
|
||||
* @return <type>
|
||||
*/
|
||||
public function hasLowerColumn($lcColumnName)
|
||||
{
|
||||
return isset($this->_lcColumnToFieldNames[$lcColumnName]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up the field name for a (lowercased) column name.
|
||||
*
|
||||
* This is mostly used during hydration, because we want to make the
|
||||
* conversion to field names while iterating over the result set for best
|
||||
* performance. By doing this at that point, we can avoid re-iterating over
|
||||
* the data just to convert the column names to field names.
|
||||
*
|
||||
* However, when this is happening, we don't know the real
|
||||
* class name to instantiate yet (the row data may target a sub-type), hence
|
||||
* this method looks up the field name in the subclass mappings if it's not
|
||||
* found on this class mapping.
|
||||
* This lookup on subclasses is costly but happens only *once* for a column
|
||||
* during hydration because the hydrator caches effectively.
|
||||
*
|
||||
* @return string The field name.
|
||||
* @throws Doctrine::ORM::Exceptions::ClassMetadataException If the field name could
|
||||
* not be found.
|
||||
*/
|
||||
public function lookupFieldName($lcColumnName)
|
||||
{
|
||||
if (isset($this->_lcColumnToFieldNames[$lcColumnName])) {
|
||||
return $this->_lcColumnToFieldNames[$lcColumnName];
|
||||
}/* else if (isset($this->_subclassFieldNames[$lcColumnName])) {
|
||||
return $this->_subclassFieldNames[$lcColumnName];
|
||||
}*/
|
||||
|
||||
foreach ($this->getSubclasses() as $subClass) {
|
||||
$subClassMetadata = $this->_em->getClassMetadata($subClass);
|
||||
if ($subClassMetadata->hasLowerColumn($lcColumnName)) {
|
||||
/*$this->_subclassFieldNames[$lcColumnName] = $subClassMetadata->
|
||||
getFieldNameForLowerColumnName($lcColumnName);
|
||||
return $this->_subclassFieldNames[$lcColumnName];*/
|
||||
return $subClassMetadata->getFieldNameForLowerColumnName($lcColumnName);
|
||||
}
|
||||
}
|
||||
|
||||
throw new Doctrine_ClassMetadata_Exception("No field name found for column name '$lcColumnName' during lookup.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a field mapping.
|
||||
*
|
||||
@ -732,11 +633,6 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Doctrine_Common_Configurable
|
||||
$this->_fieldNames[$mapping['columnName']] = $mapping['fieldName'];
|
||||
$this->_lcColumnToFieldNames[$lcColumnName] = $mapping['fieldName'];
|
||||
|
||||
// Complete length mapping
|
||||
if ( ! isset($mapping['length'])) {
|
||||
$mapping['length'] = $this->_getDefaultLength($mapping['type']);
|
||||
}
|
||||
|
||||
// Complete id mapping
|
||||
if (isset($mapping['id']) && $mapping['id'] === true) {
|
||||
if ( ! in_array($mapping['fieldName'], $this->_identifier)) {
|
||||
@ -783,58 +679,6 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Doctrine_Common_Configurable
|
||||
//...
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to lazily create the id generator.
|
||||
*
|
||||
* @param string $generatorType
|
||||
* @return void
|
||||
*/
|
||||
protected function _createIdGenerator()
|
||||
{
|
||||
if ($this->_generatorType == self::GENERATOR_TYPE_IDENTITY) {
|
||||
$this->_idGenerator = new Doctrine_ORM_Id_IdentityGenerator($this->_em);
|
||||
} else if ($this->_generatorType == self::GENERATOR_TYPE_SEQUENCE) {
|
||||
$this->_idGenerator = new Doctrine_ORM_Id_SequenceGenerator($this->_em);
|
||||
} else if ($this->_generatorType == self::GENERATOR_TYPE_TABLE) {
|
||||
$this->_idGenerator = new Doctrine_ORM_Id_TableGenerator($this->_em);
|
||||
} else {
|
||||
$this->_idGenerator = new Doctrine_ORM_Id_Assigned($this->_em);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default length for a column type.
|
||||
*
|
||||
* @param string $type
|
||||
* @return mixed
|
||||
*/
|
||||
private function _getDefaultLength($type)
|
||||
{
|
||||
switch ($type) {
|
||||
case 'string':
|
||||
case 'clob':
|
||||
case 'float':
|
||||
case 'integer':
|
||||
case 'array':
|
||||
case 'object':
|
||||
case 'blob':
|
||||
case 'gzip':
|
||||
// use php int max
|
||||
return 2147483647;
|
||||
case 'boolean':
|
||||
return 1;
|
||||
case 'date':
|
||||
// YYYY-MM-DD ISO 8601
|
||||
return 10;
|
||||
case 'time':
|
||||
// HH:NN:SS+00:00 ISO 8601
|
||||
return 14;
|
||||
case 'timestamp':
|
||||
// YYYY-MM-DDTHH:MM:SS+00:00 ISO 8601
|
||||
return 25;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps an embedded value object.
|
||||
*
|
||||
@ -845,6 +689,59 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Doctrine_Common_Configurable
|
||||
//...
|
||||
}
|
||||
|
||||
private $_entityIdentifiers = array();
|
||||
/**
|
||||
* Gets the identifier of an entity.
|
||||
*
|
||||
* @param object $entity
|
||||
* @return array Map of identifier field names to values.
|
||||
*/
|
||||
public function getEntityIdentifier($entity)
|
||||
{
|
||||
$oid = spl_object_id($entity);
|
||||
if ( ! isset($this->_entityIdentifiers[$oid])) {
|
||||
if ( ! $this->isIdentifierComposite()) {
|
||||
$idField = $this->_identifier[0];
|
||||
$idValue = $this->_reflectionProperties[$idField]->getValue($entity);
|
||||
if (isset($idValue)) {
|
||||
//return array($idField => $idValue);
|
||||
$this->_entityIdentifiers[$oid] = array($idField => $idValue);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
//$this->_entityIdentifiers[$oid] = false;
|
||||
} else {
|
||||
$id = array();
|
||||
foreach ($this->getIdentifierFieldNames() as $idFieldName) {
|
||||
$idValue = $this->_reflectionProperties[$idFieldName]->getValue($entity);
|
||||
if (isset($idValue)) {
|
||||
$id[$idFieldName] = $idValue;
|
||||
}
|
||||
}
|
||||
//return $id;
|
||||
$this->_entityIdentifiers[$oid] = $id;
|
||||
}
|
||||
}
|
||||
return $this->_entityIdentifiers[$oid];
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param <type> $entity
|
||||
* @param <type> $identifier
|
||||
*/
|
||||
public function setEntityIdentifier($entity, $identifier)
|
||||
{
|
||||
if (is_array($identifier)) {
|
||||
foreach ($identifier as $fieldName => $value) {
|
||||
$this->_reflectionProperties[$fieldName]->setValue($entity, $value);
|
||||
}
|
||||
} else {
|
||||
$this->_reflectionProperties[$this->_identifier[0]]->setValue($entity, $identifier);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the identifier (primary key) field names of the class.
|
||||
*
|
||||
@ -896,38 +793,6 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Doctrine_Common_Configurable
|
||||
return isset($this->_columnNames[$fieldName]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the custom accessor of a field.
|
||||
*
|
||||
* @return string The name of the accessor (getter) method or NULL if the field does
|
||||
* not have a custom accessor.
|
||||
*/
|
||||
public function getCustomAccessor($fieldName)
|
||||
{
|
||||
if (isset($this->_fieldMappings[$fieldName]['accessor'])) {
|
||||
return $this->_fieldMappings[$fieldName]['accessor'];
|
||||
} else if (isset($this->_customAssociationAccessors[$fieldName])) {
|
||||
return $this->_customAssociationAccessors[$fieldName];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the custom mutator of a field.
|
||||
*
|
||||
* @return string The name of the mutator (setter) method or NULL if the field does
|
||||
* not have a custom mutator.
|
||||
*/
|
||||
public function getCustomMutator($fieldName)
|
||||
{
|
||||
if (isset($this->_fieldMappings[$fieldName]['mutator'])) {
|
||||
return $this->_fieldMappings[$fieldName]['mutator'];
|
||||
} else if (isset($this->_customAssociationMutators[$fieldName])) {
|
||||
return $this->_customAssociationMutators[$fieldName];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all field mappings.
|
||||
*
|
||||
@ -986,6 +851,14 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Doctrine_Common_Configurable
|
||||
return $this->_generatorType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the type of Id generator to use for this class.
|
||||
*/
|
||||
public function setIdGeneratorType($generatorType)
|
||||
{
|
||||
$this->_generatorType = $generatorType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the class uses an Id generator.
|
||||
*
|
||||
@ -996,16 +869,43 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Doctrine_Common_Configurable
|
||||
return $this->_generatorType != self::GENERATOR_TYPE_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return <type>
|
||||
*/
|
||||
public function isInheritanceTypeNone()
|
||||
{
|
||||
return $this->_inheritanceType == self::INHERITANCE_TYPE_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the mapped class uses the JOINED inheritance mapping strategy.
|
||||
*
|
||||
* @return boolean TRUE if the class participates in a JOINED inheritance mapping,
|
||||
* FALSE otherwise.
|
||||
*/
|
||||
public function isInheritanceTypeJoined()
|
||||
{
|
||||
return $this->_inheritanceType == self::INHERITANCE_TYPE_JOINED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the mapped class uses the SINGLE_TABLE inheritance mapping strategy.
|
||||
*
|
||||
* @return boolean TRUE if the class participates in a SINGLE_TABLE inheritance mapping,
|
||||
* FALSE otherwise.
|
||||
*/
|
||||
public function isInheritanceTypeSingleTable()
|
||||
{
|
||||
return $this->_inheritanceType == self::INHERITANCE_TYPE_SINGLE_TABLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the mapped class uses the TABLE_PER_CLASS inheritance mapping strategy.
|
||||
*
|
||||
* @return boolean TRUE if the class participates in a TABLE_PER_CLASS inheritance mapping,
|
||||
* FALSE otherwise.
|
||||
*/
|
||||
public function isInheritanceTypeTablePerClass()
|
||||
{
|
||||
return $this->_inheritanceType == self::INHERITANCE_TYPE_TABLE_PER_CLASS;
|
||||
@ -1110,9 +1010,9 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Doctrine_Common_Configurable
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the inheritance type used by the class.
|
||||
* Gets the inheritance mapping type used by the class.
|
||||
*
|
||||
* @return integer
|
||||
* @return string
|
||||
*/
|
||||
public function getInheritanceType()
|
||||
{
|
||||
@ -1141,29 +1041,6 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Doctrine_Common_Configurable
|
||||
return $this->_subClasses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the class in the entity hierarchy that owns the field with
|
||||
* the given name. The owning class is the one that defines the field.
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @return string
|
||||
* @todo Consider using 'inherited' => 'ClassName' to make the lookup simpler.
|
||||
*/
|
||||
public function getOwningClass($fieldName)
|
||||
{
|
||||
if ($this->_inheritanceType == self::INHERITANCE_TYPE_NONE) {
|
||||
return $this;
|
||||
} else {
|
||||
foreach ($this->_parentClasses as $parentClass) {
|
||||
if ( ! $this->_em->getClassMetadata($parentClass)->isInheritedField($fieldName)) {
|
||||
return $parentClass;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new Doctrine_ClassMetadata_Exception("Unable to find defining class of field '$fieldName'.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the class has any persistent subclasses.
|
||||
*
|
||||
@ -1259,9 +1136,9 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Doctrine_Common_Configurable
|
||||
*/
|
||||
public function getInheritanceOption($name)
|
||||
{
|
||||
if ( ! array_key_exists($name, $this->_inheritanceOptions)) {
|
||||
/*if ( ! array_key_exists($name, $this->_inheritanceOptions)) {
|
||||
throw new Doctrine_ClassMetadata_Exception("Unknown inheritance option: '$name'.");
|
||||
}
|
||||
}*/
|
||||
|
||||
return $this->_inheritanceOptions[$name];
|
||||
}
|
||||
@ -1317,7 +1194,6 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Doctrine_Common_Configurable
|
||||
*/
|
||||
public function export()
|
||||
{
|
||||
//$this->_em->export->exportTable($this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1329,7 +1205,7 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Doctrine_Common_Configurable
|
||||
*/
|
||||
public function getExportableFormat($parseForeignKeys = true)
|
||||
{
|
||||
$columns = array();
|
||||
/*$columns = array();
|
||||
$primary = array();
|
||||
$allColumns = $this->getColumns();
|
||||
|
||||
@ -1338,13 +1214,13 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Doctrine_Common_Configurable
|
||||
if ($this->_inheritanceType == self::INHERITANCE_TYPE_SINGLE_TABLE) {
|
||||
$parents = $this->getParentClasses();
|
||||
if ($parents) {
|
||||
$rootClass = $this->_em->getClassMetadata(array_pop($parents));
|
||||
$rootClass = $this->_classFactory->getClassMetadata(array_pop($parents));
|
||||
} else {
|
||||
$rootClass = $this;
|
||||
}
|
||||
$subClasses = $rootClass->getSubclasses();
|
||||
foreach ($subClasses as $subClass) {
|
||||
$subClassMetadata = $this->_em->getClassMetadata($subClass);
|
||||
$subClassMetadata = $this->_classFactory->getClassMetadata($subClass);
|
||||
$allColumns = array_merge($allColumns, $subClassMetadata->getColumns());
|
||||
}
|
||||
} else if ($this->_inheritanceType == self::INHERITANCE_TYPE_JOINED) {
|
||||
@ -1440,6 +1316,8 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Doctrine_Common_Configurable
|
||||
return array('tableName' => $this->getTableOption('tableName'),
|
||||
'columns' => $columns,
|
||||
'options' => array_merge($options, $this->getTableOptions()));
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1545,23 +1423,6 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Doctrine_Common_Configurable
|
||||
return $mapping;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers any custom accessors/mutators in the given association mapping in
|
||||
* an internal cache for fast lookup.
|
||||
*
|
||||
* @param Doctrine_Association $assoc
|
||||
* @param unknown_type $fieldName
|
||||
*/
|
||||
private function _registerCustomAssociationAccessors(Doctrine_ORM_Mapping_AssociationMapping $assoc, $fieldName)
|
||||
{
|
||||
if ($acc = $assoc->getCustomAccessor()) {
|
||||
$this->_customAssociationAccessors[$fieldName] = $acc;
|
||||
}
|
||||
if ($mut = $assoc->getCustomMutator()) {
|
||||
$this->_customAssociationMutators[$fieldName] = $mut;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a one-to-one mapping.
|
||||
*
|
||||
@ -1572,17 +1433,15 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Doctrine_Common_Configurable
|
||||
$mapping = $this->_completeAssociationMapping($mapping);
|
||||
$oneToOneMapping = new Doctrine_ORM_Mapping_OneToOneMapping($mapping);
|
||||
$this->_storeAssociationMapping($oneToOneMapping);
|
||||
|
||||
/*if ($oneToOneMapping->isInverseSide()) {
|
||||
//FIXME: infinite recursion possible?
|
||||
// Alternative: Store inverse side mappings indexed by mappedBy fieldname
|
||||
// ($this->_inverseMappings). Then look it up.
|
||||
$owningClass = $this->_em->getClassMetadata($oneToOneMapping->getTargetEntityName());
|
||||
$owningClass->getAssociationMapping($oneToOneMapping->getMappedByFieldName())
|
||||
->setBidirectional($oneToOneMapping->getSourceFieldName());
|
||||
}*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the mapping as an inverse mapping, if it is a mapping on the
|
||||
* inverse side of an association mapping.
|
||||
*
|
||||
* @param AssociationMapping The mapping to register as inverse if it is a mapping
|
||||
* for the inverse side of an association.
|
||||
*/
|
||||
private function _registerMappingIfInverse(Doctrine_ORM_Mapping_AssociationMapping $assoc)
|
||||
{
|
||||
if ($assoc->isInverseSide()) {
|
||||
@ -1637,7 +1496,6 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Doctrine_Common_Configurable
|
||||
throw Doctrine_MappingException::duplicateFieldMapping();
|
||||
}
|
||||
$this->_associationMappings[$sourceFieldName] = $assocMapping;
|
||||
$this->_registerCustomAssociationAccessors($assocMapping, $sourceFieldName);
|
||||
$this->_registerMappingIfInverse($assocMapping);
|
||||
}
|
||||
|
||||
@ -1666,19 +1524,6 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Doctrine_Common_Configurable
|
||||
return $this->_customRepositoryClassName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Id generator used by the class.
|
||||
*
|
||||
* @return Doctrine::ORM::Id::AbstractIdGenerator
|
||||
*/
|
||||
public function getIdGenerator()
|
||||
{
|
||||
if (is_null($this->_idGenerator)) {
|
||||
$this->_createIdGenerator();
|
||||
}
|
||||
return $this->_idGenerator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo Thoughts & Implementation.
|
||||
*/
|
||||
@ -1746,7 +1591,7 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Doctrine_Common_Configurable
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a lifecycle listener for Entities this class.
|
||||
* Adds a lifecycle listener for Entities of this class.
|
||||
*
|
||||
* Note: If the same listener class is registered more than once, the old
|
||||
* one will be overridden.
|
||||
@ -1781,33 +1626,6 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Doctrine_Common_Configurable
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL: Completes the identifier mapping of the class.
|
||||
* NOTE: Should only be called by the ClassMetadataFactory!
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function completeIdentifierMapping()
|
||||
{
|
||||
if ($this->_generatorType == self::GENERATOR_TYPE_AUTO) {
|
||||
$platform = $this->_em->getConnection()->getDatabasePlatform();
|
||||
if ($platform === null) {
|
||||
try {
|
||||
throw new Exception();
|
||||
} catch (Exception $e) {
|
||||
echo $e->getTraceAsString();
|
||||
}
|
||||
}
|
||||
if ($platform->prefersSequences()) {
|
||||
$this->_generatorType = self::GENERATOR_TYPE_SEQUENCE;
|
||||
} else if ($platform->prefersIdentityColumns()) {
|
||||
$this->_generatorType = self::GENERATOR_TYPE_IDENTITY;
|
||||
} else {
|
||||
$this->_generatorType = self::GENERATOR_TYPE_TABLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo Implementation. Immutable entities can not be updated or deleted once
|
||||
* they are created. This means the entity can only be modified as long as it's
|
||||
|
@ -19,11 +19,14 @@
|
||||
* <http://www.phpdoctrine.org>.
|
||||
*/
|
||||
|
||||
#namespace Doctrine::ORM::Internal;
|
||||
#namespace Doctrine\ORM\Mapping;
|
||||
|
||||
#use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||
|
||||
/**
|
||||
* The metadata factory is used to create ClassMetadata objects that contain all the
|
||||
* metadata mapping informations of a class.
|
||||
* metadata mapping informations of a class which describes how a class should be mapped
|
||||
* to a relational database.
|
||||
*
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
@ -33,44 +36,21 @@
|
||||
* @since 2.0
|
||||
* @todo Rename to ClassDescriptorFactory.
|
||||
*/
|
||||
class Doctrine_ORM_Mapping_ClassMetadataFactory
|
||||
class Doctrine_ORM_Mapping_ClassMetadataFactory extends Doctrine_Common_ClassMetadataFactory
|
||||
{
|
||||
protected $_em;
|
||||
protected $_driver;
|
||||
|
||||
/**
|
||||
* The already loaded metadata objects.
|
||||
*/
|
||||
protected $_loadedMetadata = array();
|
||||
/** The targeted database platform. */
|
||||
private $_targetPlatform;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* Creates a new factory instance that uses the given EntityManager and metadata driver
|
||||
* implementations.
|
||||
* Creates a new factory instance that uses the given metadata driver implementation.
|
||||
*
|
||||
* @param $conn The connection to use.
|
||||
* @param $driver The metadata driver to use.
|
||||
*/
|
||||
public function __construct(Doctrine_ORM_EntityManager $em, $driver)
|
||||
public function __construct($driver, Doctrine_DBAL_Platforms_AbstractPlatform $targetPlatform)
|
||||
{
|
||||
$this->_em = $em;
|
||||
$this->_driver = $driver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the metadata object for a class.
|
||||
*
|
||||
* @param string $className The name of the class.
|
||||
* @return Doctrine_Metadata
|
||||
*/
|
||||
public function getMetadataFor($className)
|
||||
{
|
||||
if (isset($this->_loadedMetadata[$className])) {
|
||||
return $this->_loadedMetadata[$className];
|
||||
}
|
||||
$this->_loadClasses($className, $this->_loadedMetadata);
|
||||
|
||||
return $this->_loadedMetadata[$className];
|
||||
parent::__construct($driver);
|
||||
$this->_targetPlatform = $targetPlatform;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -79,17 +59,16 @@ class Doctrine_ORM_Mapping_ClassMetadataFactory
|
||||
*
|
||||
* @param string $name The name of the class for which the metadata should get loaded.
|
||||
* @param array $tables The metadata collection to which the loaded metadata is added.
|
||||
* @override
|
||||
*/
|
||||
protected function _loadClasses($name, array &$classes)
|
||||
protected function _loadMetadata($name)
|
||||
{
|
||||
|
||||
$parentClass = $name;
|
||||
$parentClasses = array();
|
||||
$loadedParentClass = false;
|
||||
while ($parentClass = get_parent_class($parentClass)) {
|
||||
if ($parentClass == 'Doctrine_ORM_Entity') {
|
||||
break;
|
||||
}
|
||||
if (isset($classes[$parentClass])) {
|
||||
if (isset($this->_loadedMetadata[$parentClass])) {
|
||||
$loadedParentClass = $parentClass;
|
||||
break;
|
||||
}
|
||||
@ -99,12 +78,12 @@ class Doctrine_ORM_Mapping_ClassMetadataFactory
|
||||
$parentClasses[] = $name;
|
||||
|
||||
if ($loadedParentClass) {
|
||||
$class = $classes[$loadedParentClass];
|
||||
$class = $this->_loadedMetadata[$loadedParentClass];
|
||||
} else {
|
||||
$rootClassOfHierarchy = count($parentClasses) > 0 ? array_shift($parentClasses) : $name;
|
||||
$class = new Doctrine_ORM_Mapping_ClassMetadata($rootClassOfHierarchy, $this->_em);
|
||||
$this->_loadMetadata($class, $rootClassOfHierarchy);
|
||||
$classes[$rootClassOfHierarchy] = $class;
|
||||
$class = new Doctrine_ORM_Mapping_ClassMetadata($rootClassOfHierarchy);
|
||||
$this->_loadClassMetadata($class, $rootClassOfHierarchy);
|
||||
$this->_loadedMetadata[$rootClassOfHierarchy] = $class;
|
||||
}
|
||||
|
||||
if (count($parentClasses) == 0) {
|
||||
@ -117,15 +96,15 @@ class Doctrine_ORM_Mapping_ClassMetadataFactory
|
||||
// Move down the hierarchy of parent classes, starting from the topmost class
|
||||
$parent = $class;
|
||||
foreach ($parentClasses as $subclassName) {
|
||||
$subClass = new Doctrine_ORM_Mapping_ClassMetadata($subclassName, $this->_em);
|
||||
$subClass = new Doctrine_ORM_Mapping_ClassMetadata($subclassName);
|
||||
$subClass->setInheritanceType($parent->getInheritanceType(), $parent->getInheritanceOptions());
|
||||
$this->_addInheritedFields($subClass, $parent);
|
||||
$this->_addInheritedRelations($subClass, $parent);
|
||||
$this->_loadMetadata($subClass, $subclassName);
|
||||
$this->_loadClassMetadata($subClass, $subclassName);
|
||||
if ($parent->isInheritanceTypeSingleTable()) {
|
||||
$subClass->setTableName($parent->getTableName());
|
||||
}
|
||||
$classes[$subclassName] = $subClass;
|
||||
$this->_loadedMetadata[$subclassName] = $subClass;
|
||||
$parent = $subClass;
|
||||
}
|
||||
}
|
||||
@ -137,7 +116,7 @@ class Doctrine_ORM_Mapping_ClassMetadataFactory
|
||||
* @param Doctrine::ORM::Mapping::ClassMetadata $parentClass
|
||||
* @return void
|
||||
*/
|
||||
protected function _addInheritedFields($subClass, $parentClass)
|
||||
private function _addInheritedFields($subClass, $parentClass)
|
||||
{
|
||||
foreach ($parentClass->getFieldMappings() as $fieldName => $mapping) {
|
||||
if ( ! isset($mapping['inherited'])) {
|
||||
@ -153,7 +132,7 @@ class Doctrine_ORM_Mapping_ClassMetadataFactory
|
||||
* @param unknown_type $subClass
|
||||
* @param unknown_type $parentClass
|
||||
*/
|
||||
protected function _addInheritedRelations($subClass, $parentClass)
|
||||
private function _addInheritedRelations($subClass, $parentClass)
|
||||
{
|
||||
foreach ($parentClass->getAssociationMappings() as $fieldName => $mapping) {
|
||||
$subClass->addAssociationMapping($name, $mapping);
|
||||
@ -166,7 +145,7 @@ class Doctrine_ORM_Mapping_ClassMetadataFactory
|
||||
* @param Doctrine_ClassMetadata $class The container for the metadata.
|
||||
* @param string $name The name of the class for which the metadata will be loaded.
|
||||
*/
|
||||
protected function _loadMetadata(Doctrine_ORM_Mapping_ClassMetadata $class, $name)
|
||||
private function _loadClassMetadata(Doctrine_ORM_Mapping_ClassMetadata $class, $name)
|
||||
{
|
||||
if ( ! class_exists($name) || empty($name)) {
|
||||
throw new Doctrine_Exception("Couldn't find class " . $name . ".");
|
||||
@ -177,17 +156,15 @@ class Doctrine_ORM_Mapping_ClassMetadataFactory
|
||||
// get parent classes
|
||||
//TODO: Skip Entity types MappedSuperclass/Transient
|
||||
do {
|
||||
if ($className === 'Doctrine_ORM_Entity') {
|
||||
break;
|
||||
} else if ($className == $name) {
|
||||
if ($className == $name) {
|
||||
continue;
|
||||
}
|
||||
$names[] = $className;
|
||||
} while ($className = get_parent_class($className));
|
||||
|
||||
if ($className === false) {
|
||||
throw new Doctrine_ClassMetadata_Factory_Exception("Unknown component '$className'.");
|
||||
}
|
||||
/*if ($className === false) {
|
||||
throw new Doctrine_Exception("Unknown component '$className'.");
|
||||
}*/
|
||||
|
||||
// save parents
|
||||
$class->setParentClasses($names);
|
||||
@ -201,11 +178,20 @@ class Doctrine_ORM_Mapping_ClassMetadataFactory
|
||||
$class->setTableName(Doctrine::tableize($class->getClassName()));
|
||||
}
|
||||
|
||||
$class->completeIdentifierMapping();
|
||||
// Complete Id generator mapping. If AUTO is specified we choose the generator
|
||||
// most appropriate for the target platform.
|
||||
if ($class->getIdGeneratorType() == Doctrine_ORM_Mapping_ClassMetadata::GENERATOR_TYPE_AUTO) {
|
||||
if ($this->_targetPlatform->prefersSequences()) {
|
||||
$class->setIdGeneratorType(Doctrine_ORM_Mapping_ClassMetadata::GENERATOR_TYPE_SEQUENCE);
|
||||
} else if ($this->_targetPlatform->prefersIdentityColumns()) {
|
||||
$class->setIdGeneratorType(Doctrine_ORM_Mapping_ClassMetadata::GENERATOR_TYPE_IDENTITY);
|
||||
} else {
|
||||
$class->setIdGeneratorType(Doctrine_ORM_Mapping_ClassMetadata::GENERATOR_TYPE_TABLE);
|
||||
}
|
||||
}
|
||||
|
||||
return $class;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
* <http://www.phpdoctrine.org>.
|
||||
*/
|
||||
|
||||
#namespace Doctrine::ORM::Internal;
|
||||
#namespace Doctrine\ORM\Mapping\Driver;
|
||||
|
||||
/**
|
||||
* The code metadata driver loads the metadata of the classes through invoking
|
||||
@ -39,17 +39,27 @@ class Doctrine_ORM_Mapping_Driver_CodeDriver
|
||||
*
|
||||
* @todo We could make the name of the callback methods customizable for users.
|
||||
*/
|
||||
const CALLBACK_METHOD = 'initMetadata';
|
||||
private $_callback = 'initMetadata';
|
||||
|
||||
public function setCallback($callback)
|
||||
{
|
||||
$this->_callback = $callback;
|
||||
}
|
||||
|
||||
public function getCallback()
|
||||
{
|
||||
return $this->_callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the metadata for the specified class into the provided container.
|
||||
*/
|
||||
public function loadMetadataForClass($className, Doctrine_ORM_Mapping_ClassMetadata $metadata)
|
||||
{
|
||||
if ( ! method_exists($className, self::CALLBACK_METHOD)) {
|
||||
throw new Doctrine_ClassMetadata_Exception("Unable to load metadata for class"
|
||||
if ( ! method_exists($className, $this->_callback)) {
|
||||
throw new Doctrine_Exception("Unable to load metadata for class"
|
||||
. " '$className'. Callback method 'initMetadata' not found.");
|
||||
}
|
||||
call_user_func_array(array($className, 'initMetadata'), array($metadata));
|
||||
call_user_func_array(array($className, $this->_callback), array($metadata));
|
||||
}
|
||||
}
|
@ -19,7 +19,7 @@
|
||||
* <http://www.phpdoctrine.org>.
|
||||
*/
|
||||
|
||||
#namespace Doctrine::ORM::Persisters;
|
||||
#namespace Doctrine\ORM\Persisters;
|
||||
|
||||
/**
|
||||
* Base class for all EntityPersisters.
|
||||
@ -89,60 +89,13 @@ abstract class Doctrine_ORM_Persisters_AbstractEntityPersister
|
||||
* @param Doctrine::ORM::Entity $entity The entity to insert.
|
||||
* @return void
|
||||
*/
|
||||
public function insert(Doctrine_ORM_Entity $entity)
|
||||
public function insert($entity)
|
||||
{
|
||||
$insertData = array();
|
||||
$class = $entity->getClass();
|
||||
|
||||
$referenceChangeSet = $entity->_getReferenceChangeSet();
|
||||
foreach ($referenceChangeSet as $field => $change) {
|
||||
list($old, $new) = each($change);
|
||||
$assocMapping = $class->getAssociationMapping($field);
|
||||
if ( ! $assocMapping->isOneToOne() || $assocMapping->isInverseSide()) {
|
||||
//echo "NOT TO-ONE OR INVERSE!";
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($assocMapping->getSourceToTargetKeyColumns() as $sourceColumn => $targetColumn) {
|
||||
//TODO: What if both join columns (local/foreign) are just db-only
|
||||
// columns (no fields in models) ? Currently we assume the foreign column
|
||||
// is mapped to a field in the foreign entity.
|
||||
//TODO: throw exc if field not set
|
||||
$insertData[$sourceColumn] = $new->_internalGetField(
|
||||
$new->getClass()->getFieldName($targetColumn)
|
||||
);
|
||||
}
|
||||
//...
|
||||
}
|
||||
|
||||
$this->_prepareData($entity, $insertData, true);
|
||||
|
||||
//TODO: perform insert
|
||||
$this->_conn->insert($class->getTableName(), $insertData);
|
||||
$this->_conn->insert($this->_classMetadata->getTableName(), $insertData);
|
||||
}
|
||||
|
||||
/*protected function _fillJoinColumns($entity, array &$data)
|
||||
{
|
||||
$referenceChangeSet = $entity->_getReferenceChangeSet();
|
||||
foreach ($referenceChangeSet as $field => $change) {
|
||||
list($old, $new) = each($change);
|
||||
$assocMapping = $entity->getClass()->getAssociationMapping($field);
|
||||
if ( ! $assocMapping->isOneToOne() || $assocMapping->isInverseSide()) {
|
||||
//echo "NOT TO-ONE OR INVERSE!";
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($assocMapping->getSourceToTargetKeyColumns() as $sourceColumn => $targetColumn) {
|
||||
//TODO: What if both join columns (local/foreign) are just db-only
|
||||
// columns (no fields in models) ? Currently we assume the foreign column
|
||||
// is mapped to a field in the foreign entity.
|
||||
$insertData[$sourceColumn] = $new->_internalGetField(
|
||||
$new->getClass()->getFieldName($targetColumn)
|
||||
);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Updates an entity.
|
||||
*
|
||||
@ -231,11 +184,27 @@ abstract class Doctrine_ORM_Persisters_AbstractEntityPersister
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo Move to ClassMetadata?
|
||||
* Gets the name of the class in the entity hierarchy that owns the field with
|
||||
* the given name. The owning class is the one that defines the field.
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @return string
|
||||
* @todo Consider using 'inherited' => 'ClassName' to make the lookup simpler.
|
||||
*/
|
||||
public function getOwningClass($fieldName)
|
||||
{
|
||||
if ($this->_classMetadata->isInheritanceTypeNone()) {
|
||||
return $this->_classMetadata;
|
||||
} else {
|
||||
foreach ($this->_classMetadata->getParentClasses() as $parentClass) {
|
||||
$parentClassMetadata = Doctrine_ORM_Mapping_ClassMetadataFactory::getInstance()
|
||||
->getMetadataFor($parentClass);
|
||||
if ( ! $parentClassMetadata->isInheritedField($fieldName)) {
|
||||
return $parentClassMetadata;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new Doctrine_Exception("Unable to find defining class of field '$fieldName'.");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -278,20 +247,33 @@ abstract class Doctrine_ORM_Persisters_AbstractEntityPersister
|
||||
*
|
||||
* @param array $array
|
||||
* @return void
|
||||
* @todo Move to EntityPersister. There call _getChangeSet() and apply this logic.
|
||||
*/
|
||||
protected function _prepareData($entity, array &$result, $isInsert = false)
|
||||
{
|
||||
foreach ($entity->_getDataChangeSet() as $field => $change) {
|
||||
foreach ($this->_em->getUnitOfWork()->getDataChangeSet($entity) as $field => $change) {
|
||||
list ($oldVal, $newVal) = each($change);
|
||||
$type = $entity->getClass()->getTypeOfField($field);
|
||||
$columnName = $entity->getClass()->getColumnName($field);
|
||||
$type = $this->_classMetadata->getTypeOfField($field);
|
||||
$columnName = $this->_classMetadata->getColumnName($field);
|
||||
|
||||
if ($newVal === Doctrine_ORM_Internal_Null::$INSTANCE) {
|
||||
$result[$columnName] = null;
|
||||
} else if (is_object($newVal)) {
|
||||
$assocMapping = $this->_classMetadata->getAssociationMapping($field);
|
||||
if ( ! $assocMapping->isOneToOne() || $assocMapping->isInverseSide()) {
|
||||
//echo "NOT TO-ONE OR INVERSE!";
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($assocMapping->getSourceToTargetKeyColumns() as $sourceColumn => $targetColumn) {
|
||||
//TODO: What if both join columns (local/foreign) are just db-only
|
||||
// columns (no fields in models) ? Currently we assume the foreign column
|
||||
// is mapped to a field in the foreign entity.
|
||||
//TODO: throw exc if field not set
|
||||
$otherClass = $this->_em->getClassMetadata($assocMapping->getTargetEntityName());
|
||||
$result[$sourceColumn] = $otherClass->getReflectionProperty(
|
||||
$otherClass->getFieldName($targetColumn))->getValue($newVal);
|
||||
}
|
||||
} else {
|
||||
switch ($type) {
|
||||
case 'array':
|
||||
case 'object':
|
||||
@ -306,16 +288,16 @@ abstract class Doctrine_ORM_Persisters_AbstractEntityPersister
|
||||
default:
|
||||
$result[$columnName] = $newVal;
|
||||
}
|
||||
}
|
||||
/*$result[$columnName] = $type->convertToDatabaseValue(
|
||||
$newVal, $this->_em->getConnection()->getDatabasePlatform());*/
|
||||
}
|
||||
|
||||
// @todo Cleanup
|
||||
// populates the discriminator column on insert in Single & Class Table Inheritance
|
||||
if ($isInsert && ($entity->getClass()->isInheritanceTypeJoined() ||
|
||||
$entity->getClass()->isInheritanceTypeSingleTable())) {
|
||||
$discColumn = $entity->getClass()->getInheritanceOption('discriminatorColumn');
|
||||
$discMap = $entity->getClass()->getInheritanceOption('discriminatorMap');
|
||||
if ($isInsert && ($this->_classMetadata->isInheritanceTypeJoined() ||
|
||||
$this->_classMetadata->isInheritanceTypeSingleTable())) {
|
||||
$discColumn = $this->_classMetadata->getInheritanceOption('discriminatorColumn');
|
||||
$discMap = $this->_classMetadata->getInheritanceOption('discriminatorMap');
|
||||
$result[$discColumn] = array_search($this->_entityName, $discMap);
|
||||
}
|
||||
}
|
||||
@ -597,14 +579,14 @@ abstract class Doctrine_ORM_Persisters_AbstractEntityPersister
|
||||
*/
|
||||
protected function _insert(Doctrine_ORM_Entity $record)
|
||||
{
|
||||
$record->preInsert();
|
||||
$this->notifyEntityListeners($record, 'preInsert', Doctrine_Event::RECORD_INSERT);
|
||||
//$record->preInsert();
|
||||
//$this->notifyEntityListeners($record, 'preInsert', Doctrine_Event::RECORD_INSERT);
|
||||
|
||||
$this->_doInsert($record);
|
||||
$this->addRecord($record);
|
||||
|
||||
$record->postInsert();
|
||||
$this->notifyEntityListeners($record, 'postInsert', Doctrine_Event::RECORD_INSERT);
|
||||
//$record->postInsert();
|
||||
//$this->notifyEntityListeners($record, 'postInsert', Doctrine_Event::RECORD_INSERT);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -219,7 +219,7 @@ class Doctrine_ORM_Persisters_JoinedSubclassPersister extends Doctrine_ORM_Persi
|
||||
*
|
||||
* @todo Looks like this better belongs into the ClassMetadata class.
|
||||
*/
|
||||
public function getOwningClass($fieldName)
|
||||
/*public function getOwningClass($fieldName)
|
||||
{
|
||||
$conn = $this->_conn;
|
||||
$classMetadata = $this->_classMetadata;
|
||||
@ -242,7 +242,7 @@ class Doctrine_ORM_Persisters_JoinedSubclassPersister extends Doctrine_ORM_Persi
|
||||
}
|
||||
|
||||
throw new Doctrine_Mapper_Exception("Unable to find defining class of field '$fieldName'.");
|
||||
}
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Analyzes the fields of the entity and creates a map in which the field names
|
||||
|
@ -19,6 +19,10 @@
|
||||
* <http://www.phpdoctrine.org>.
|
||||
*/
|
||||
|
||||
#namespace Doctrine\ORM\Persisters;
|
||||
|
||||
#use Doctrine\ORM\Entity;
|
||||
|
||||
/**
|
||||
* The default persister strategy maps a single entity instance to a single database table,
|
||||
* as is the case in Single Table Inheritance & Concrete Table Inheritance.
|
||||
|
@ -33,6 +33,7 @@
|
||||
* @version $Revision: 3938 $
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
*/
|
||||
class Doctrine_ORM_Query extends Doctrine_ORM_Query_Abstract
|
||||
{
|
||||
@ -74,9 +75,11 @@ class Doctrine_ORM_Query extends Doctrine_ORM_Query_Abstract
|
||||
protected $_parserResult;
|
||||
|
||||
/**
|
||||
* @var string $_sql Cached SQL query.
|
||||
* A set of query hints.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_sql;
|
||||
protected $_hints = array();
|
||||
|
||||
|
||||
// Caching Stuff
|
||||
@ -114,7 +117,11 @@ class Doctrine_ORM_Query extends Doctrine_ORM_Query_Abstract
|
||||
|
||||
// End of Caching Stuff
|
||||
|
||||
|
||||
/**
|
||||
* Initializes a new instance of the Query class.
|
||||
*
|
||||
* @param EntityManager $entityManager
|
||||
*/
|
||||
public function __construct(Doctrine_ORM_EntityManager $entityManager)
|
||||
{
|
||||
$this->_entityManager = $entityManager;
|
||||
@ -123,21 +130,8 @@ class Doctrine_ORM_Query extends Doctrine_ORM_Query_Abstract
|
||||
$this->free();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a new Doctrine_ORM_Query object
|
||||
*
|
||||
* @param Doctrine_Connection $conn optional connection parameter
|
||||
* @return Doctrine_ORM_Query
|
||||
*/
|
||||
public static function create($conn = null)
|
||||
{
|
||||
return new self($conn);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the assocated Doctrine_EntityManager to this Doctrine_ORM_Query
|
||||
* Retrieves the assocated EntityManager to this Doctrine_ORM_Query
|
||||
*
|
||||
* @return Doctrine_EntityManager
|
||||
*/
|
||||
@ -146,7 +140,6 @@ class Doctrine_ORM_Query extends Doctrine_ORM_Query_Abstract
|
||||
return $this->_entityManager;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the hydrator associated with this query object
|
||||
*
|
||||
@ -157,7 +150,6 @@ class Doctrine_ORM_Query extends Doctrine_ORM_Query_Abstract
|
||||
return $this->_hydrator;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convenience method to execute using array fetching as hydration mode.
|
||||
*
|
||||
@ -168,7 +160,6 @@ class Doctrine_ORM_Query extends Doctrine_ORM_Query_Abstract
|
||||
return $this->execute($params, self::HYDRATE_ARRAY);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convenience method to execute the query and return the first item
|
||||
* of the collection.
|
||||
@ -194,7 +185,6 @@ class Doctrine_ORM_Query extends Doctrine_ORM_Query_Abstract
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Query the database with DQL (Doctrine Query Language).
|
||||
*
|
||||
@ -210,7 +200,6 @@ class Doctrine_ORM_Query extends Doctrine_ORM_Query_Abstract
|
||||
return $this->execute($params, $hydrationMode);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Builds the sql query from the given parameters and applies things such as
|
||||
* column aggregation inheritance and limit subqueries if needed
|
||||
@ -222,7 +211,6 @@ class Doctrine_ORM_Query extends Doctrine_ORM_Query_Abstract
|
||||
return $this->parse()->getSqlExecutor()->getSqlStatements();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parses the DQL query, if necessary, and stores the parser result.
|
||||
*
|
||||
@ -239,7 +227,6 @@ class Doctrine_ORM_Query extends Doctrine_ORM_Query_Abstract
|
||||
return $this->_parserResult;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Executes the query and populates the data set.
|
||||
*
|
||||
@ -278,7 +265,6 @@ class Doctrine_ORM_Query extends Doctrine_ORM_Query_Abstract
|
||||
return $this->_execute($params, $hydrationMode);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* _execute
|
||||
*
|
||||
@ -304,7 +290,6 @@ class Doctrine_ORM_Query extends Doctrine_ORM_Query_Abstract
|
||||
return $this->_hydrator->hydrateResultSet($stmt, $hydrationMode);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* _execute2
|
||||
*
|
||||
@ -356,7 +341,6 @@ class Doctrine_ORM_Query extends Doctrine_ORM_Query_Abstract
|
||||
return $executor->execute($this->_conn, $params);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @nodoc
|
||||
*/
|
||||
@ -369,7 +353,6 @@ class Doctrine_ORM_Query extends Doctrine_ORM_Query_Abstract
|
||||
return $this->convertEnums($params);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Defines a cache driver to be used for caching result sets.
|
||||
*
|
||||
@ -389,7 +372,6 @@ class Doctrine_ORM_Query extends Doctrine_ORM_Query_Abstract
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the cache driver used for caching result sets.
|
||||
*
|
||||
@ -404,7 +386,6 @@ class Doctrine_ORM_Query extends Doctrine_ORM_Query_Abstract
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Defines how long the result cache will be active before expire.
|
||||
*
|
||||
@ -422,7 +403,6 @@ class Doctrine_ORM_Query extends Doctrine_ORM_Query_Abstract
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the lifetime of resultset cache.
|
||||
*
|
||||
@ -433,7 +413,6 @@ class Doctrine_ORM_Query extends Doctrine_ORM_Query_Abstract
|
||||
return $this->_resultCacheTTL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Defines if the resultset cache is active or not.
|
||||
*
|
||||
@ -447,7 +426,6 @@ class Doctrine_ORM_Query extends Doctrine_ORM_Query_Abstract
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves if the resultset cache is active or not.
|
||||
*
|
||||
@ -458,7 +436,6 @@ class Doctrine_ORM_Query extends Doctrine_ORM_Query_Abstract
|
||||
return $this->_expireResultCache;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Defines a cache driver to be used for caching queries.
|
||||
*
|
||||
@ -478,7 +455,6 @@ class Doctrine_ORM_Query extends Doctrine_ORM_Query_Abstract
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the cache driver used for caching queries.
|
||||
*
|
||||
@ -493,7 +469,6 @@ class Doctrine_ORM_Query extends Doctrine_ORM_Query_Abstract
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Defines how long the query cache will be active before expire.
|
||||
*
|
||||
@ -511,7 +486,6 @@ class Doctrine_ORM_Query extends Doctrine_ORM_Query_Abstract
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the lifetime of resultset cache.
|
||||
*
|
||||
@ -522,7 +496,6 @@ class Doctrine_ORM_Query extends Doctrine_ORM_Query_Abstract
|
||||
return $this->_queryCacheTTL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Defines if the query cache is active or not.
|
||||
*
|
||||
@ -536,7 +509,6 @@ class Doctrine_ORM_Query extends Doctrine_ORM_Query_Abstract
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves if the query cache is active or not.
|
||||
*
|
||||
@ -547,7 +519,6 @@ class Doctrine_ORM_Query extends Doctrine_ORM_Query_Abstract
|
||||
return $this->_expireQueryCache;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Defines the processing mode to be used during hydration process.
|
||||
*
|
||||
@ -620,6 +591,29 @@ class Doctrine_ORM_Query extends Doctrine_ORM_Query_Abstract
|
||||
return is_array($result) ? array_shift($result) : $result->getFirst();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an implementation-specific hint. If the hint name is not recognized,
|
||||
* it is silently ignored.
|
||||
*
|
||||
* @param string $name The name of the hint.
|
||||
* @param mixed $value The value of the hint.
|
||||
*/
|
||||
public function setHint($name, $value)
|
||||
{
|
||||
$this->_hints[$name] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an implementation-specific hint. If the hint name is not recognized,
|
||||
* FALSE is returned.
|
||||
*
|
||||
* @param string $name The name of the hint.
|
||||
*/
|
||||
public function getHint($name)
|
||||
{
|
||||
return isset($this->_hints[$name]) ? $this->_hints[$name] : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is automatically called when this Doctrine_Hydrate is serialized.
|
||||
*
|
||||
|
@ -51,7 +51,7 @@ class Doctrine_ORM_Query_Parser_AbstractSchemaName extends Doctrine_ORM_Query_Pa
|
||||
// Check if we are dealing with a real Doctrine_Entity or not
|
||||
if ( ! $this->_isDoctrineEntity($componentName)) {
|
||||
$this->_parser->semanticalError(
|
||||
"Defined entity '" . $companyName . "' is not a valid Doctrine_Entity."
|
||||
"Defined entity '" . $componentName . "' is not a valid entity."
|
||||
);
|
||||
}
|
||||
|
||||
@ -62,6 +62,6 @@ class Doctrine_ORM_Query_Parser_AbstractSchemaName extends Doctrine_ORM_Query_Pa
|
||||
|
||||
protected function _isDoctrineEntity($componentName)
|
||||
{
|
||||
return class_exists($componentName) && is_subclass_of($componentName, 'Doctrine_ORM_Entity');
|
||||
return class_exists($componentName)/* && is_subclass_of($componentName, 'Doctrine_ORM_Entity')*/;
|
||||
}
|
||||
}
|
||||
|
@ -19,11 +19,10 @@
|
||||
* <http://www.phpdoctrine.org>.
|
||||
*/
|
||||
|
||||
#namespace Doctrine::ORM;
|
||||
#namespace Doctrine\ORM;
|
||||
|
||||
#use Doctrine::ORM::Entity;
|
||||
#use Doctrine::ORM::EntityManager;
|
||||
#use Doctrine::ORM::Exceptions::UnitOfWorkException;
|
||||
#use Doctrine\ORM\EntityManager;
|
||||
#use Doctrine\ORM\Exceptions\UnitOfWorkException;
|
||||
|
||||
/**
|
||||
* The UnitOfWork is responsible for tracking changes to objects during an
|
||||
@ -41,6 +40,45 @@
|
||||
*/
|
||||
class Doctrine_ORM_UnitOfWork
|
||||
{
|
||||
/**
|
||||
* An Entity is in managed state when it has a primary key/identifier (and
|
||||
* therefore persistent state) and is managed by an EntityManager
|
||||
* (registered in the identity map).
|
||||
* In MANAGED state the entity is associated with an EntityManager that manages
|
||||
* the persistent state of the Entity.
|
||||
*/
|
||||
const STATE_MANAGED = 1;
|
||||
|
||||
/**
|
||||
* An Entity is new if it does not yet have an identifier/primary key
|
||||
* and is not (yet) managed by an EntityManager.
|
||||
*/
|
||||
const STATE_NEW = 2;
|
||||
|
||||
/**
|
||||
* An Entity is temporarily locked during deletes and saves.
|
||||
*
|
||||
* This state is used internally to ensure that circular deletes
|
||||
* and saves will not cause infinite loops.
|
||||
* @todo Not sure this is a good idea. It is a problematic solution because
|
||||
* it hides the original state while the locked state is active.
|
||||
*/
|
||||
const STATE_LOCKED = 6;
|
||||
|
||||
/**
|
||||
* A detached Entity is an instance with a persistent identity that is not
|
||||
* (or no longer) associated with an EntityManager (and a UnitOfWork).
|
||||
* This means its no longer in the identity map.
|
||||
*/
|
||||
const STATE_DETACHED = 3;
|
||||
|
||||
/**
|
||||
* A removed Entity instance is an instance with a persistent identity,
|
||||
* associated with an EntityManager, whose persistent state has been
|
||||
* deleted (or is scheduled for deletion).
|
||||
*/
|
||||
const STATE_DELETED = 4;
|
||||
|
||||
/**
|
||||
* The identity map that holds references to all managed entities that have
|
||||
* an identity. The entities are grouped by their class name.
|
||||
@ -51,6 +89,31 @@ class Doctrine_ORM_UnitOfWork
|
||||
*/
|
||||
protected $_identityMap = array();
|
||||
|
||||
/**
|
||||
* Map of the original entity data of entities fetched from the database.
|
||||
* Keys are object ids. This is used for calculating changesets at commit time.
|
||||
* Note that PHPs "copy-on-write" behavior helps a lot with the potentially
|
||||
* high memory usage.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_originalEntityData = array();
|
||||
|
||||
/**
|
||||
* Map of data changes. Keys are object ids.
|
||||
* Filled at the beginning of a commit() of the UnitOfWork and cleaned at the end.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_dataChangeSets = array();
|
||||
|
||||
/**
|
||||
* The states of entities in this UnitOfWork.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_entityStates = array();
|
||||
|
||||
/**
|
||||
* A list of all new entities that need to be INSERTed.
|
||||
*
|
||||
@ -61,7 +124,7 @@ class Doctrine_ORM_UnitOfWork
|
||||
protected $_newEntities = array();
|
||||
|
||||
/**
|
||||
* A list of all dirty entities.
|
||||
* A list of all dirty entities that need to be UPDATEd.
|
||||
*
|
||||
* @var array
|
||||
* @todo Rename to _updates?
|
||||
@ -102,7 +165,7 @@ class Doctrine_ORM_UnitOfWork
|
||||
/**
|
||||
* The EntityManager the UnitOfWork belongs to.
|
||||
*
|
||||
* @var Doctrine::ORM::EntityManager
|
||||
* @var Doctrine\ORM\EntityManager
|
||||
*/
|
||||
protected $_em;
|
||||
|
||||
@ -110,7 +173,7 @@ class Doctrine_ORM_UnitOfWork
|
||||
* The calculator used to calculate the order in which changes to
|
||||
* entities need to be written to the database.
|
||||
*
|
||||
* @var Doctrine::ORM::Internal::CommitOrderCalculator
|
||||
* @var Doctrine\ORM\Internal\CommitOrderCalculator
|
||||
*/
|
||||
protected $_commitOrderCalculator;
|
||||
|
||||
@ -118,7 +181,7 @@ class Doctrine_ORM_UnitOfWork
|
||||
* Constructor.
|
||||
* Creates a new UnitOfWork.
|
||||
*
|
||||
* @param Doctrine_EntityManager $em
|
||||
* @param Doctrine\ORM\EntityManager $em
|
||||
*/
|
||||
public function __construct(Doctrine_ORM_EntityManager $em)
|
||||
{
|
||||
@ -131,21 +194,12 @@ class Doctrine_ORM_UnitOfWork
|
||||
* Commits the unit of work, executing all operations that have been postponed
|
||||
* up to this point.
|
||||
*
|
||||
* @todo Impl
|
||||
* @return void
|
||||
*/
|
||||
public function commit()
|
||||
{
|
||||
// Detect changes in managed entities (mark dirty)
|
||||
//TODO: Consider using registerDirty() in Entity#_set() instead if its
|
||||
// more performant (SEE THERE).
|
||||
/*foreach ($this->_identityMap as $entities) {
|
||||
foreach ($entities as $entity) {
|
||||
if ($entity->_state() == Doctrine_Entity::STATE_MANAGED
|
||||
&& $entity->isModified()) {
|
||||
$this->registerDirty($entity);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
// Compute changes in managed entities
|
||||
$this->_computeDataChangeSet();
|
||||
|
||||
if (empty($this->_newEntities) &&
|
||||
empty($this->_deletedEntities) &&
|
||||
@ -176,10 +230,88 @@ class Doctrine_ORM_UnitOfWork
|
||||
|
||||
//TODO: commit transaction here?
|
||||
|
||||
// clear lists
|
||||
// clear up
|
||||
$this->_newEntities = array();
|
||||
$this->_dirtyEntities = array();
|
||||
$this->_deletedEntities = array();
|
||||
$this->_dataChangeSets = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the data changeset for an entity.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getDataChangeSet($entity)
|
||||
{
|
||||
$oid = spl_object_id($entity);
|
||||
if (isset($this->_dataChangeSets[$oid])) {
|
||||
return $this->_dataChangeSets[$oid];
|
||||
}
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes all the changes that have been done to entities in the identity map
|
||||
* and stores these changes in _dataChangeSet temporarily for access by the
|
||||
* peristers, until the UoW commit is finished.
|
||||
*
|
||||
* @param array $entities The entities for which to compute the changesets. If this
|
||||
* parameter is not specified, the changesets of all entities in the identity
|
||||
* map are computed.
|
||||
* @return void
|
||||
*/
|
||||
private function _computeDataChangeSet(array $entities = null)
|
||||
{
|
||||
$entitySet = array();
|
||||
if ( ! is_null($entities)) {
|
||||
foreach ($entities as $entity) {
|
||||
$className = get_class($entity);
|
||||
if ( ! isset($entitySet[$className])) {
|
||||
$entitySet[$className] = array();
|
||||
}
|
||||
$entitySet[$className][] = $entity;
|
||||
}
|
||||
} else {
|
||||
$entitySet = $this->_identityMap;
|
||||
}
|
||||
|
||||
foreach ($entitySet as $className => $entities) {
|
||||
$class = $this->_em->getClassMetadata($className);
|
||||
foreach ($entities as $entity) {
|
||||
$oid = spl_object_id($entity);
|
||||
if ($this->getEntityState($entity) == self::STATE_MANAGED) {
|
||||
if ( ! $class->isInheritanceTypeNone()) {
|
||||
$class = $this->_em->getClassMetadata(get_class($entity));
|
||||
}
|
||||
|
||||
$actualData = array();
|
||||
foreach ($class->getReflectionProperties() as $name => $refProp) {
|
||||
$actualData[$name] = $refProp->getValue($entity);
|
||||
}
|
||||
|
||||
if ( ! isset($this->_originalEntityData[$oid])) {
|
||||
$this->_dataChangeSets[$oid] = $actualData;
|
||||
} else {
|
||||
$originalData = $this->_originalEntityData[$oid];
|
||||
$changeSet = array();
|
||||
foreach ($actualData as $propName => $actualValue) {
|
||||
$orgValue = isset($originalData[$propName]) ? $originalData[$propName] : null;
|
||||
if (is_object($orgValue) && $orgValue !== $actualValue) {
|
||||
$changeSet[$propName] = array($orgValue => $actualValue);
|
||||
} else if ($orgValue != $actualValue || (is_null($orgValue) xor is_null($actualValue))) {
|
||||
$changeSet[$propName] = array($orgValue => $actualValue);
|
||||
}
|
||||
}
|
||||
$this->_dirtyEntities[$oid] = $entity;
|
||||
$this->_dataChangeSets[$oid] = $changeSet;
|
||||
}
|
||||
}
|
||||
if (isset($this->_dirtyEntities[$oid])) {
|
||||
$this->_originalEntityData[$oid] = $actualData;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -196,10 +328,12 @@ class Doctrine_ORM_UnitOfWork
|
||||
$className = $class->getClassName();
|
||||
$persister = $this->_em->getEntityPersister($className);
|
||||
foreach ($this->_newEntities as $entity) {
|
||||
if ($entity->getClass()->getClassName() == $className) {
|
||||
if (get_class($entity) == $className) {
|
||||
$persister->insert($entity);
|
||||
if ($class->isIdGeneratorIdentity()) {
|
||||
$entity->_assignIdentifier($class->getIdGenerator()->getPostInsertId());
|
||||
$id = $this->_em->getIdGenerator($class->getIdGeneratorType());
|
||||
$class->setEntityIdentifier($entity, $id);
|
||||
$this->_entityStates[spl_object_id($oid)] = self::STATE_MANAGED;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -265,18 +399,20 @@ class Doctrine_ORM_UnitOfWork
|
||||
// commit order graph yet (dont have a node).
|
||||
$newNodes = array();
|
||||
foreach ($entityChangeSet as $entity) {
|
||||
if ( ! $this->_commitOrderCalculator->hasNodeWithKey($entity->getClass()->getClassName())) {
|
||||
$className = get_class($entity);
|
||||
if ( ! $this->_commitOrderCalculator->hasNodeWithKey($className)) {
|
||||
$this->_commitOrderCalculator->addNodeWithItem(
|
||||
$entity->getClass()->getClassName(), // index/key
|
||||
$entity->getClass() // item
|
||||
$className, // index/key
|
||||
$this->_em->getClassMetadata($className) // item
|
||||
);
|
||||
$newNodes[] = $this->_commitOrderCalculator->getNodeForKey($entity->getClass()->getClassName());
|
||||
$newNodes[] = $this->_commitOrderCalculator->getNodeForKey($className);
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate dependencies for new nodes
|
||||
foreach ($newNodes as $node) {
|
||||
foreach ($node->getClass()->getAssociationMappings() as $assocMapping) {
|
||||
$class = $node->getClass();
|
||||
foreach ($class->getAssociationMappings() as $assocMapping) {
|
||||
//TODO: should skip target classes that are not in the changeset.
|
||||
if ($assocMapping->isOwningSide()) {
|
||||
$targetClass = $this->_em->getClassMetadata($assocMapping->getTargetEntityName());
|
||||
@ -303,9 +439,9 @@ class Doctrine_ORM_UnitOfWork
|
||||
*
|
||||
* @todo Rename to scheduleForInsert().
|
||||
*/
|
||||
public function registerNew(Doctrine_ORM_Entity $entity)
|
||||
public function registerNew($entity)
|
||||
{
|
||||
$oid = $entity->getOid();
|
||||
$oid = spl_object_id($entity);
|
||||
|
||||
/*if ( ! $entity->_identifier()) {
|
||||
throw new Doctrine_Connection_Exception("Entity without identity cant be registered as new.");
|
||||
@ -321,7 +457,7 @@ class Doctrine_ORM_UnitOfWork
|
||||
}
|
||||
|
||||
$this->_newEntities[$oid] = $entity;
|
||||
if ($entity->_identifier()) {
|
||||
if ($this->_em->getClassMetadata(get_class($entity))->getEntityIdentifier($entity)) {
|
||||
$this->addToIdentityMap($entity);
|
||||
}
|
||||
}
|
||||
@ -333,18 +469,18 @@ class Doctrine_ORM_UnitOfWork
|
||||
* @return boolean
|
||||
* @todo Rename to isScheduledForInsert().
|
||||
*/
|
||||
public function isRegisteredNew(Doctrine_ORM_Entity $entity)
|
||||
public function isRegisteredNew($entity)
|
||||
{
|
||||
return isset($this->_newEntities[$entity->getOid()]);
|
||||
return isset($this->_newEntities[spl_object_id($entity)]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a clean entity.
|
||||
* The entity is simply put into the identity map.
|
||||
*
|
||||
* @param Doctrine::ORM::Entity $entity
|
||||
* @param object $entity
|
||||
*/
|
||||
public function registerClean(Doctrine_ORM_Entity $entity)
|
||||
public function registerClean($entity)
|
||||
{
|
||||
$this->addToIdentityMap($entity);
|
||||
}
|
||||
@ -355,15 +491,15 @@ class Doctrine_ORM_UnitOfWork
|
||||
* @param Doctrine::ORM::Entity $entity
|
||||
* @todo Rename to scheduleForUpdate().
|
||||
*/
|
||||
public function registerDirty(Doctrine_ORM_Entity $entity)
|
||||
public function registerDirty($entity)
|
||||
{
|
||||
$oid = $entity->getOid();
|
||||
$oid = spl_object_id($entity);
|
||||
if ( ! $entity->_identifier()) {
|
||||
throw new Doctrine_Connection_Exception("Entity without identity "
|
||||
throw new Doctrine_Exception("Entity without identity "
|
||||
. "can't be registered as dirty.");
|
||||
}
|
||||
if (isset($this->_deletedEntities[$oid])) {
|
||||
throw new Doctrine_Connection_Exception("Removed object can't be registered as dirty.");
|
||||
throw new Doctrine_Exception("Removed object can't be registered as dirty.");
|
||||
}
|
||||
|
||||
if ( ! isset($this->_dirtyEntities[$oid]) && ! isset($this->_newEntities[$oid])) {
|
||||
@ -380,9 +516,9 @@ class Doctrine_ORM_UnitOfWork
|
||||
* @return boolean
|
||||
* @todo Rename to isScheduledForUpdate().
|
||||
*/
|
||||
public function isRegisteredDirty(Doctrine_ORM_Entity $entity)
|
||||
public function isRegisteredDirty($entity)
|
||||
{
|
||||
return isset($this->_dirtyEntities[$entity->getOid()]);
|
||||
return isset($this->_dirtyEntities[spl_object_id($entity)]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -390,9 +526,9 @@ class Doctrine_ORM_UnitOfWork
|
||||
*
|
||||
* @todo Rename to scheduleForDelete().
|
||||
*/
|
||||
public function registerDeleted(Doctrine_ORM_Entity $entity)
|
||||
public function registerDeleted($entity)
|
||||
{
|
||||
$oid = $entity->getOid();
|
||||
$oid = spl_object_id($entity);
|
||||
if ( ! $this->isInIdentityMap($entity)) {
|
||||
return;
|
||||
}
|
||||
@ -420,9 +556,9 @@ class Doctrine_ORM_UnitOfWork
|
||||
* @return boolean
|
||||
* @todo Rename to isScheduledForDelete().
|
||||
*/
|
||||
public function isRegisteredRemoved(Doctrine_ORM_Entity $entity)
|
||||
public function isRegisteredRemoved($entity)
|
||||
{
|
||||
return isset($this->_deletedEntities[$entity->getOid()]);
|
||||
return isset($this->_deletedEntities[spl_object_id($entity)]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -432,7 +568,7 @@ class Doctrine_ORM_UnitOfWork
|
||||
* @param integer $oid object identifier
|
||||
* @return boolean whether ot not the operation was successful
|
||||
*/
|
||||
public function detach(Doctrine_ORM_Entity $entity)
|
||||
public function detach($entity)
|
||||
{
|
||||
if ($this->isInIdentityMap($entity)) {
|
||||
$this->removeFromIdentityMap($entity);
|
||||
@ -446,9 +582,9 @@ class Doctrine_ORM_UnitOfWork
|
||||
* @return unknown
|
||||
* @todo Rename to isScheduled()
|
||||
*/
|
||||
public function isEntityRegistered(Doctrine_ORM_Entity $entity)
|
||||
public function isEntityRegistered($entity)
|
||||
{
|
||||
$oid = $entity->getOid();
|
||||
$oid = spl_object_id($entity);
|
||||
return isset($this->_newEntities[$oid]) ||
|
||||
isset($this->_dirtyEntities[$oid]) ||
|
||||
isset($this->_deletedEntities[$oid]) ||
|
||||
@ -484,40 +620,54 @@ class Doctrine_ORM_UnitOfWork
|
||||
* Note that entities in a hierarchy are registered with the class name of
|
||||
* the root entity.
|
||||
*
|
||||
* @param Doctrine::ORM::Entity $entity The entity to register.
|
||||
* @param Doctrine\ORM\Entity $entity The entity to register.
|
||||
* @return boolean TRUE if the registration was successful, FALSE if the identity of
|
||||
* the entity in question is already managed.
|
||||
*/
|
||||
public function addToIdentityMap(Doctrine_ORM_Entity $entity)
|
||||
public function addToIdentityMap($entity)
|
||||
{
|
||||
$idHash = $this->getIdentifierHash($entity->_identifier());
|
||||
$classMetadata = $this->_em->getClassMetadata(get_class($entity));
|
||||
$idHash = $this->getIdentifierHash($classMetadata->getEntityIdentifier($entity));
|
||||
if ($idHash === '') {
|
||||
throw new Doctrine_Connection_Exception("Entity with oid '" . $entity->getOid()
|
||||
throw new Doctrine_Exception("Entity with oid '" . spl_object_id($entity)
|
||||
. "' has no identity and therefore can't be added to the identity map.");
|
||||
}
|
||||
$className = $entity->getClass()->getRootClassName();
|
||||
$className = $classMetadata->getRootClassName();
|
||||
if (isset($this->_identityMap[$className][$idHash])) {
|
||||
return false;
|
||||
}
|
||||
$this->_identityMap[$className][$idHash] = $entity;
|
||||
$entity->_state(Doctrine_ORM_Entity::STATE_MANAGED);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the state of an entity within the current unit of work.
|
||||
*
|
||||
* @param Doctrine\ORM\Entity $entity
|
||||
* @return int
|
||||
*/
|
||||
public function getEntityState($entity)
|
||||
{
|
||||
$oid = spl_object_id($entity);
|
||||
return isset($this->_entityStates[$oid]) ? $this->_entityStates[$oid] :
|
||||
self::STATE_NEW;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an entity from the identity map.
|
||||
*
|
||||
* @param Doctrine_ORM_Entity $entity
|
||||
* @return unknown
|
||||
*/
|
||||
public function removeFromIdentityMap(Doctrine_ORM_Entity $entity)
|
||||
public function removeFromIdentityMap($entity)
|
||||
{
|
||||
$idHash = $this->getIdentifierHash($entity->_identifier());
|
||||
$classMetadata = $this->_em->getClassMetadata(get_class($entity));
|
||||
$idHash = $this->getIdentifierHash($classMetadata->getEntityIdentifier($entity));
|
||||
if ($idHash === '') {
|
||||
throw new Doctrine_Connection_Exception("Entity with oid '" . $entity->getOid()
|
||||
throw new Doctrine_Exception("Entity with oid '" . spl_object_id($entity)
|
||||
. "' has no identity and therefore can't be removed from the identity map.");
|
||||
}
|
||||
$className = $entity->getClass()->getRootClassName();
|
||||
$className = $classMetadata->getRootClassName();
|
||||
if (isset($this->_identityMap[$className][$idHash])) {
|
||||
unset($this->_identityMap[$className][$idHash]);
|
||||
return true;
|
||||
@ -537,6 +687,15 @@ class Doctrine_ORM_UnitOfWork
|
||||
{
|
||||
return $this->_identityMap[$rootClassName][$idHash];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to get an entity by its identifier hash. If no entity is found for
|
||||
* the given hash, FALSE is returned.
|
||||
*
|
||||
* @param <type> $idHash
|
||||
* @param <type> $rootClassName
|
||||
* @return mixed The found entity or FALSE.
|
||||
*/
|
||||
public function tryGetByIdHash($idHash, $rootClassName)
|
||||
{
|
||||
if ($this->containsIdHash($idHash, $rootClassName)) {
|
||||
@ -565,18 +724,19 @@ class Doctrine_ORM_UnitOfWork
|
||||
* Checks whether an entity is registered in the identity map of the
|
||||
* UnitOfWork.
|
||||
*
|
||||
* @param Doctrine_ORM_Entity $entity
|
||||
* @param object $entity
|
||||
* @return boolean
|
||||
*/
|
||||
public function isInIdentityMap(Doctrine_ORM_Entity $entity)
|
||||
public function isInIdentityMap($entity)
|
||||
{
|
||||
$idHash = $this->getIdentifierHash($entity->_identifier());
|
||||
$classMetadata = $this->_em->getClassMetadata(get_class($entity));
|
||||
$idHash = $this->getIdentifierHash($classMetadata->getEntityIdentifier($entity));
|
||||
if ($idHash === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return isset($this->_identityMap
|
||||
[$entity->getClass()->getRootClassName()]
|
||||
[$classMetadata->getRootClassName()]
|
||||
[$idHash]
|
||||
);
|
||||
}
|
||||
@ -598,7 +758,7 @@ class Doctrine_ORM_UnitOfWork
|
||||
*
|
||||
* @param Doctrine_ORM_Entity $entity The entity to save.
|
||||
*/
|
||||
public function save(Doctrine_ORM_Entity $entity)
|
||||
public function save($entity)
|
||||
{
|
||||
$insertNow = array();
|
||||
$visited = array();
|
||||
@ -606,12 +766,14 @@ class Doctrine_ORM_UnitOfWork
|
||||
if ( ! empty($insertNow)) {
|
||||
// We have no choice. This means that there are new entities
|
||||
// with an IDENTITY column key generation.
|
||||
$this->_computeDataChangeSet($insertNow);
|
||||
$commitOrder = $this->_getCommitOrder($insertNow);
|
||||
foreach ($commitOrder as $class) {
|
||||
$this->_executeInserts($class);
|
||||
}
|
||||
// remove them from _newEntities
|
||||
$this->_newEntities = array_diff_key($this->_newEntities, $insertNow);
|
||||
$this->_dataChangeSets = array();
|
||||
}
|
||||
}
|
||||
|
||||
@ -623,37 +785,39 @@ class Doctrine_ORM_UnitOfWork
|
||||
* @param Doctrine_ORM_Entity $entity The entity to save.
|
||||
* @param array $visited The already visited entities.
|
||||
*/
|
||||
private function _doSave(Doctrine_ORM_Entity $entity, array &$visited, array &$insertNow)
|
||||
private function _doSave($entity, array &$visited, array &$insertNow)
|
||||
{
|
||||
if (isset($visited[$entity->getOid()])) {
|
||||
$oid = spl_object_id($entity);
|
||||
if (isset($visited[$oid])) {
|
||||
return; // Prevent infinite recursion
|
||||
}
|
||||
|
||||
$visited[$entity->getOid()] = $entity; // mark visited
|
||||
$visited[$oid] = $entity; // mark visited
|
||||
|
||||
$class = $entity->getClass();
|
||||
switch ($entity->_state()) {
|
||||
case Doctrine_ORM_Entity::STATE_MANAGED:
|
||||
// nothing to do for $entity
|
||||
$class = $this->_em->getClassMetadata(get_class($entity));
|
||||
switch ($this->getEntityState($entity)) {
|
||||
case self::STATE_MANAGED:
|
||||
// nothing to do
|
||||
break;
|
||||
case Doctrine_ORM_Entity::STATE_NEW:
|
||||
$result = $class->getIdGenerator()->generate($entity);
|
||||
case self::STATE_NEW:
|
||||
$result = $this->_em->getIdGenerator($class->getClassName())->generate($entity);
|
||||
if ($result == Doctrine_ORM_Id_AbstractIdGenerator::POST_INSERT_INDICATOR) {
|
||||
$insertNow[$entity->getOid()] = $entity;
|
||||
$insertNow[$oid] = $entity;
|
||||
} else {
|
||||
$entity->_assignIdentifier($result);
|
||||
$class->setEntityIdentifier($entity, $result);
|
||||
$this->_entityStates[$oid] = self::STATE_MANAGED;
|
||||
}
|
||||
$this->registerNew($entity);
|
||||
break;
|
||||
case Doctrine_ORM_Entity::STATE_DETACHED:
|
||||
case self::STATE_DETACHED:
|
||||
//exception?
|
||||
throw new Doctrine_Exception("Behavior of save() for a detached entity "
|
||||
. "is not yet defined.");
|
||||
case Doctrine_ORM_Entity::STATE_DELETED:
|
||||
case self::STATE_DELETED:
|
||||
// $entity becomes managed again
|
||||
if ($this->isRegisteredRemoved($entity)) {
|
||||
//TODO: better a method for this?
|
||||
unset($this->_deletedEntities[$entity->getOid()]);
|
||||
unset($this->_deletedEntities[$oid]);
|
||||
} else {
|
||||
//FIXME: There's more to think of here...
|
||||
$this->registerNew($entity);
|
||||
@ -672,7 +836,7 @@ class Doctrine_ORM_UnitOfWork
|
||||
*
|
||||
* @param Doctrine_ORM_Entity $entity
|
||||
*/
|
||||
public function delete(Doctrine_ORM_Entity $entity)
|
||||
public function delete($entity)
|
||||
{
|
||||
$this->_doDelete($entity, array());
|
||||
}
|
||||
@ -683,24 +847,25 @@ class Doctrine_ORM_UnitOfWork
|
||||
* @param Doctrine_ORM_Entity $entity
|
||||
* @param array $visited
|
||||
*/
|
||||
private function _doDelete(Doctrine_ORM_Entity $entity, array &$visited)
|
||||
private function _doDelete($entity, array &$visited)
|
||||
{
|
||||
if (isset($visited[$entity->getOid()])) {
|
||||
$oid = spl_object_id($entity);
|
||||
if (isset($visited[$oid])) {
|
||||
return; // Prevent infinite recursion
|
||||
}
|
||||
|
||||
$visited[$entity->getOid()] = $entity; // mark visited
|
||||
$visited[$oid] = $entity; // mark visited
|
||||
|
||||
$class = $entity->getClass();
|
||||
switch ($entity->_state()) {
|
||||
case Doctrine_ORM_Entity::STATE_NEW:
|
||||
case Doctrine_ORM_Entity::STATE_DELETED:
|
||||
//$class = $entity->getClass();
|
||||
switch ($this->getEntityState($entity)) {
|
||||
case self::STATE_NEW:
|
||||
case self::STATE_DELETED:
|
||||
// nothing to do for $entity
|
||||
break;
|
||||
case Doctrine_ORM_Entity::STATE_MANAGED:
|
||||
case self::STATE_MANAGED:
|
||||
$this->registerDeleted($entity);
|
||||
break;
|
||||
case Doctrine_ORM_Entity::STATE_DETACHED:
|
||||
case self::STATE_DETACHED:
|
||||
//exception?
|
||||
throw new Doctrine_Exception("A detached entity can't be deleted.");
|
||||
default:
|
||||
@ -714,28 +879,30 @@ class Doctrine_ORM_UnitOfWork
|
||||
/**
|
||||
* Cascades the save operation to associated entities.
|
||||
*
|
||||
* @param Doctrine_ORM_Entity $entity
|
||||
* @param Doctrine\ORM\Entity $entity
|
||||
* @param array $visited
|
||||
*/
|
||||
private function _cascadeSave(Doctrine_ORM_Entity $entity, array &$visited, array &$insertNow)
|
||||
private function _cascadeSave($entity, array &$visited, array &$insertNow)
|
||||
{
|
||||
foreach ($entity->getClass()->getAssociationMappings() as $assocMapping) {
|
||||
$class = $this->_em->getClassMetadata(get_class($entity));
|
||||
foreach ($class->getAssociationMappings() as $assocMapping) {
|
||||
if ( ! $assocMapping->isCascadeSave()) {
|
||||
continue;
|
||||
}
|
||||
$relatedEntities = $entity->get($assocMapping->getSourceFieldName());
|
||||
if ($relatedEntities instanceof Doctrine_ORM_Entity) {
|
||||
$this->_doSave($relatedEntities, $visited, $insertNow);
|
||||
} else if ($relatedEntities instanceof Doctrine_Collection &&
|
||||
$relatedEntities = $class->getReflectionProperty($assocMapping->getSourceFieldName())
|
||||
->getValue($entity);
|
||||
if ($relatedEntities instanceof Doctrine_ORM_Collection &&
|
||||
count($relatedEntities) > 0) {
|
||||
foreach ($relatedEntities as $relatedEntity) {
|
||||
$this->_doSave($relatedEntity, $visited, $insertNow);
|
||||
}
|
||||
} else if (is_object($relatedEntities)) {
|
||||
$this->_doSave($relatedEntities, $visited, $insertNow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function _cascadeDelete(Doctrine_ORM_Entity $entity)
|
||||
private function _cascadeDelete($entity)
|
||||
{
|
||||
|
||||
}
|
||||
@ -783,192 +950,110 @@ class Doctrine_ORM_UnitOfWork
|
||||
//...
|
||||
}
|
||||
|
||||
|
||||
// Stuff from 0.11/1.0 that we will need later (need to modify it though)
|
||||
|
||||
/**
|
||||
* Collects all records that need to be deleted by applying defined
|
||||
* application-level delete cascades.
|
||||
* Creates an entity. Used for reconstitution as well as initial creation.
|
||||
*
|
||||
* @param array $deletions Map of the records to delete. Keys=Oids Values=Records.
|
||||
* @param string $className The name of the entity class.
|
||||
* @param array $data The data for the entity.
|
||||
* @return Doctrine\ORM\Entity
|
||||
*/
|
||||
/*private function _collectDeletions(Doctrine_Record $record, array &$deletions)
|
||||
public function createEntity($className, array $data, Doctrine_Query $query = null)
|
||||
{
|
||||
if ( ! $record->exists()) {
|
||||
return;
|
||||
$className = $this->_inferCorrectClassName($data, $className);
|
||||
$classMetadata = $this->_em->getClassMetadata($className);
|
||||
if ( ! empty($data)) {
|
||||
$identifierFieldNames = $classMetadata->getIdentifier();
|
||||
$isNew = false;
|
||||
foreach ($identifierFieldNames as $fieldName) {
|
||||
if ( ! isset($data[$fieldName])) {
|
||||
// id field not found return new entity
|
||||
$isNew = true;
|
||||
break;
|
||||
}
|
||||
$id[] = $data[$fieldName];
|
||||
}
|
||||
|
||||
$deletions[$record->getOid()] = $record;
|
||||
$this->_cascadeDelete($record, $deletions);
|
||||
}*/
|
||||
if ($isNew) {
|
||||
$entity = new $className;
|
||||
} else {
|
||||
$idHash = $this->getIdentifierHash($id);
|
||||
$entity = $this->tryGetByIdHash($idHash, $classMetadata->getRootClassName());
|
||||
if ($entity) {
|
||||
$this->_mergeData($entity, $data, $classMetadata/*, $query->getHint('doctrine.refresh')*/);
|
||||
return $entity;
|
||||
} else {
|
||||
$entity = new $className;
|
||||
$this->_mergeData($entity, $data, $classMetadata, true);
|
||||
$this->addToIdentityMap($entity);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$entity = new $className;
|
||||
}
|
||||
|
||||
$this->_originalEntityData[spl_object_id($entity)] = $data;
|
||||
|
||||
return $entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cascades an ongoing delete operation to related objects. Applies only on relations
|
||||
* that have 'delete' in their cascade options.
|
||||
* This is an application-level cascade. Related objects that participate in the
|
||||
* cascade and are not yet loaded are fetched from the database.
|
||||
* Exception: many-valued relations are always (re-)fetched from the database to
|
||||
* make sure we have all of them.
|
||||
* Merges the given data into the given entity, optionally overriding
|
||||
* local changes.
|
||||
*
|
||||
* @param Doctrine_Record The record for which the delete operation will be cascaded.
|
||||
* @throws PDOException If something went wrong at database level
|
||||
* @param Doctrine\ORM\Entity $entity
|
||||
* @param array $data
|
||||
* @param boolean $overrideLocalChanges
|
||||
* @return void
|
||||
*/
|
||||
/*protected function _cascadeDelete(Doctrine_Record $record, array &$deletions)
|
||||
{
|
||||
foreach ($record->getTable()->getRelations() as $relation) {
|
||||
if ($relation->isCascadeDelete()) {
|
||||
$fieldName = $relation->getAlias();
|
||||
// if it's a xToOne relation and the related object is already loaded
|
||||
// we don't need to refresh.
|
||||
if ( ! ($relation->getType() == Doctrine_Relation::ONE && isset($record->$fieldName))) {
|
||||
$record->refreshRelated($relation->getAlias());
|
||||
private function _mergeData($entity, array $data, $class, $overrideLocalChanges = false) {
|
||||
if ($overrideLocalChanges) {
|
||||
foreach ($data as $field => $value) {
|
||||
$class->getReflectionProperty($field)->setValue($entity, $value);
|
||||
}
|
||||
$relatedObjects = $record->get($relation->getAlias());
|
||||
if ($relatedObjects instanceof Doctrine_Record && $relatedObjects->exists()
|
||||
&& ! isset($deletions[$relatedObjects->getOid()])) {
|
||||
$this->_collectDeletions($relatedObjects, $deletions);
|
||||
} else if ($relatedObjects instanceof Doctrine_Collection && count($relatedObjects) > 0) {
|
||||
// cascade the delete to the other objects
|
||||
foreach ($relatedObjects as $object) {
|
||||
if ( ! isset($deletions[$object->getOid()])) {
|
||||
$this->_collectDeletions($object, $deletions);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Executes the deletions for all collected records during a delete operation
|
||||
* (usually triggered through $record->delete()).
|
||||
*
|
||||
* @param array $deletions Map of the records to delete. Keys=Oids Values=Records.
|
||||
*/
|
||||
/*private function _executeDeletions(array $deletions)
|
||||
{
|
||||
// collect class names
|
||||
$classNames = array();
|
||||
foreach ($deletions as $record) {
|
||||
$classNames[] = $record->getTable()->getComponentName();
|
||||
}
|
||||
$classNames = array_unique($classNames);
|
||||
|
||||
// order deletes
|
||||
$executionOrder = $this->buildFlushTree($classNames);
|
||||
|
||||
// execute
|
||||
try {
|
||||
$this->conn->beginInternalTransaction();
|
||||
|
||||
for ($i = count($executionOrder) - 1; $i >= 0; $i--) {
|
||||
$className = $executionOrder[$i];
|
||||
$table = $this->conn->getTable($className);
|
||||
|
||||
// collect identifiers
|
||||
$identifierMaps = array();
|
||||
$deletedRecords = array();
|
||||
foreach ($deletions as $oid => $record) {
|
||||
if ($record->getTable()->getComponentName() == $className) {
|
||||
$veto = $this->_preDelete($record);
|
||||
if ( ! $veto) {
|
||||
$identifierMaps[] = $record->identifier();
|
||||
$deletedRecords[] = $record;
|
||||
unset($deletions[$oid]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count($deletedRecords) < 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// extract query parameters (only the identifier values are of interest)
|
||||
$params = array();
|
||||
$columnNames = array();
|
||||
foreach ($identifierMaps as $idMap) {
|
||||
while (list($fieldName, $value) = each($idMap)) {
|
||||
$params[] = $value;
|
||||
$columnNames[] = $table->getColumnName($fieldName);
|
||||
}
|
||||
}
|
||||
$columnNames = array_unique($columnNames);
|
||||
|
||||
// delete
|
||||
$tableName = $table->getTableName();
|
||||
$sql = "DELETE FROM " . $this->conn->quoteIdentifier($tableName) . " WHERE ";
|
||||
|
||||
if ($table->isIdentifierComposite()) {
|
||||
$sql .= $this->_buildSqlCompositeKeyCondition($columnNames, count($identifierMaps));
|
||||
$this->conn->exec($sql, $params);
|
||||
} else {
|
||||
$sql .= $this->_buildSqlSingleKeyCondition($columnNames, count($params));
|
||||
$this->conn->exec($sql, $params);
|
||||
}
|
||||
|
||||
// adjust state, remove from identity map and inform postDelete listeners
|
||||
foreach ($deletedRecords as $record) {
|
||||
// currently just for bc!
|
||||
$this->_deleteCTIParents($table, $record);
|
||||
//--
|
||||
$record->state(Doctrine_Record::STATE_TCLEAN);
|
||||
$record->getTable()->removeRecord($record);
|
||||
$this->_postDelete($record);
|
||||
$oid = spl_object_id($entity);
|
||||
foreach ($data as $field => $value) {
|
||||
$currentValue = $class->getReflectionProperty($field)->getValue($entity);
|
||||
if ( ! isset($this->_originalEntityData[$oid]) ||
|
||||
$currentValue == $this->_originalEntityData[$oid]) {
|
||||
$class->getReflectionProperty($field)->setValue($entity, $value);
|
||||
}
|
||||
}
|
||||
|
||||
$this->conn->commit();
|
||||
// trigger postDelete for records skipped during the deletion (veto!)
|
||||
foreach ($deletions as $skippedRecord) {
|
||||
$this->_postDelete($skippedRecord);
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (Exception $e) {
|
||||
$this->conn->rollback();
|
||||
throw $e;
|
||||
}
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Builds the SQL condition to target multiple records who have a single-column
|
||||
* primary key.
|
||||
* Check the dataset for a discriminator column to determine the correct
|
||||
* class to instantiate. If no discriminator column is found, the given
|
||||
* classname will be returned.
|
||||
*
|
||||
* @param Doctrine_Table $table The table from which the records are going to be deleted.
|
||||
* @param integer $numRecords The number of records that are going to be deleted.
|
||||
* @return string The SQL condition "pk = ? OR pk = ? OR pk = ? ..."
|
||||
* @param array $data
|
||||
* @param string $className
|
||||
* @return string The name of the class to instantiate.
|
||||
*/
|
||||
/*private function _buildSqlSingleKeyCondition($columnNames, $numRecords)
|
||||
private function _inferCorrectClassName(array $data, $className)
|
||||
{
|
||||
$idColumn = $this->conn->quoteIdentifier($columnNames[0]);
|
||||
return implode(' OR ', array_fill(0, $numRecords, "$idColumn = ?"));
|
||||
}*/
|
||||
$class = $this->_em->getClassMetadata($className);
|
||||
|
||||
/**
|
||||
* Builds the SQL condition to target multiple records who have a composite primary key.
|
||||
*
|
||||
* @param Doctrine_Table $table The table from which the records are going to be deleted.
|
||||
* @param integer $numRecords The number of records that are going to be deleted.
|
||||
* @return string The SQL condition "(pk1 = ? AND pk2 = ?) OR (pk1 = ? AND pk2 = ?) ..."
|
||||
*/
|
||||
/*private function _buildSqlCompositeKeyCondition($columnNames, $numRecords)
|
||||
{
|
||||
$singleCondition = "";
|
||||
foreach ($columnNames as $columnName) {
|
||||
$columnName = $this->conn->quoteIdentifier($columnName);
|
||||
if ($singleCondition === "") {
|
||||
$singleCondition .= "($columnName = ?";
|
||||
$discCol = $class->getInheritanceOption('discriminatorColumn');
|
||||
if ( ! $discCol) {
|
||||
return $className;
|
||||
}
|
||||
|
||||
$discMap = $class->getInheritanceOption('discriminatorMap');
|
||||
|
||||
if (isset($data[$discCol], $discMap[$data[$discCol]])) {
|
||||
return $discMap[$data[$discCol]];
|
||||
} else {
|
||||
$singleCondition .= " AND $columnName = ?";
|
||||
return $className;
|
||||
}
|
||||
}
|
||||
$singleCondition .= ")";
|
||||
$fullCondition = implode(' OR ', array_fill(0, $numRecords, $singleCondition));
|
||||
|
||||
return $fullCondition;
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Gets the identity map of the UnitOfWork.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getIdentityMap()
|
||||
{
|
||||
return $this->_identityMap;
|
||||
|
@ -18,8 +18,14 @@ class Orm_Entity_AccessorTest extends Doctrine_OrmTestCase
|
||||
|
||||
/* Local test classes */
|
||||
|
||||
class CustomAccessorMutatorTestEntity extends Doctrine_ORM_Entity
|
||||
class CustomAccessorMutatorTestEntity extends Doctrine_Common_VirtualPropertyObject
|
||||
{
|
||||
static function construct() {
|
||||
Doctrine_Common_VirtualPropertySystem::register(__CLASS__, 'id', 'int');
|
||||
Doctrine_Common_VirtualPropertySystem::register(__CLASS__,
|
||||
'username', 'string', 'getUsernameCustom', 'setUsernameCustom');
|
||||
}
|
||||
|
||||
public static function initMetadata($mapping)
|
||||
{
|
||||
$mapping->mapField(array(
|
||||
@ -31,9 +37,7 @@ class CustomAccessorMutatorTestEntity extends Doctrine_ORM_Entity
|
||||
$mapping->mapField(array(
|
||||
'fieldName' => 'username',
|
||||
'type' => 'string',
|
||||
'length' => 50,
|
||||
'accessor' => 'getUsernameCustom',
|
||||
'mutator' => 'setUsernameCustom'
|
||||
'length' => 50
|
||||
));
|
||||
}
|
||||
|
||||
@ -48,8 +52,13 @@ class CustomAccessorMutatorTestEntity extends Doctrine_ORM_Entity
|
||||
}
|
||||
}
|
||||
|
||||
class MagicAccessorMutatorTestEntity extends Doctrine_ORM_Entity
|
||||
class MagicAccessorMutatorTestEntity extends Doctrine_Common_VirtualPropertyObject
|
||||
{
|
||||
static function construct() {
|
||||
Doctrine_Common_VirtualPropertySystem::register(__CLASS__, 'id', 'int');
|
||||
Doctrine_Common_VirtualPropertySystem::register(__CLASS__, 'username', 'string');
|
||||
}
|
||||
|
||||
public static function initMetadata($mapping)
|
||||
{
|
||||
$mapping->mapField(array(
|
||||
|
@ -20,7 +20,7 @@ class Orm_Entity_AllTests
|
||||
{
|
||||
$suite = new Doctrine_TestSuite('Doctrine Orm Entity Tests');
|
||||
|
||||
$suite->addTestSuite('Orm_Entity_AccessorTest');
|
||||
//$suite->addTestSuite('Orm_Entity_AccessorTest');
|
||||
$suite->addTestSuite('Orm_Entity_ConstructorTest');
|
||||
|
||||
return $suite;
|
||||
|
@ -6,17 +6,18 @@ class Orm_Entity_ConstructorTest extends Doctrine_OrmTestCase
|
||||
public function testFieldInitializationInConstructor()
|
||||
{
|
||||
$entity = new ConstructorTestEntity1("romanb");
|
||||
$this->assertTrue($entity->isNew());
|
||||
$this->assertEquals("romanb", $entity->username);
|
||||
}
|
||||
}
|
||||
|
||||
class ConstructorTestEntity1 extends Doctrine_ORM_Entity
|
||||
class ConstructorTestEntity1
|
||||
{
|
||||
public $id;
|
||||
public $username;
|
||||
|
||||
public function __construct($username = null)
|
||||
{
|
||||
parent::__construct();
|
||||
if ($this->isNew()) {
|
||||
if ($username !== null) {
|
||||
$this->username = $username;
|
||||
}
|
||||
}
|
||||
@ -24,10 +25,16 @@ class ConstructorTestEntity1 extends Doctrine_ORM_Entity
|
||||
/* The mapping definition */
|
||||
public static function initMetadata($mapping)
|
||||
{
|
||||
/*
|
||||
$mapping->addFieldMetadata('id', array(
|
||||
'doctrine.id' => true,
|
||||
'doctrine.validator.constraints' => array('notnull', 'unique')
|
||||
));
|
||||
*/
|
||||
|
||||
$mapping->mapField(array(
|
||||
'fieldName' => 'id',
|
||||
'type' => 'integer',
|
||||
'length' => 4,
|
||||
'id' => true
|
||||
));
|
||||
$mapping->mapField(array(
|
||||
|
@ -3,50 +3,57 @@ require_once 'lib/DoctrineTestInit.php';
|
||||
require_once 'lib/mocks/Doctrine_EntityManagerMock.php';
|
||||
require_once 'lib/mocks/Doctrine_ConnectionMock.php';
|
||||
require_once 'lib/mocks/Doctrine_ClassMetadataMock.php';
|
||||
require_once 'lib/mocks/Doctrine_UnitOfWorkMock.php';
|
||||
|
||||
/**
|
||||
* EntityPersister tests.
|
||||
*/
|
||||
class Orm_EntityPersisterTest extends Doctrine_OrmTestCase
|
||||
{
|
||||
private $_persister; // SUT
|
||||
private $_connMock;
|
||||
private $_emMock;
|
||||
private $_idGenMock;
|
||||
private $classMetadataMock;
|
||||
private $_uowMock;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->_connMock = new Doctrine_ConnectionMock(array());
|
||||
$this->_emMock = Doctrine_EntityManagerMock::create($this->_connMock, 'persisterMockEM');
|
||||
$this->_uowMock = new Doctrine_UnitOfWorkMock($this->_emMock);
|
||||
$this->_emMock->setUnitOfWork($this->_uowMock);
|
||||
$this->_idGenMock = new Doctrine_SequenceMock($this->_emMock);
|
||||
$this->_classMetadataMock = new Doctrine_ClassMetadataMock("ForumUser", $this->_emMock);
|
||||
$this->_classMetadataMock->setIdGenerator($this->_idGenMock);
|
||||
$this->_connMock->setDatabasePlatform(new Doctrine_DatabasePlatformMock());
|
||||
$this->_persister = new Doctrine_ORM_Persisters_StandardEntityPersister(
|
||||
$this->_emMock, $this->_emMock->getClassMetadata("ForumUser"));
|
||||
$this->_emMock->setIdGenerator('ForumUser', $this->_idGenMock);
|
||||
|
||||
$this->_emMock->activate();
|
||||
}
|
||||
|
||||
public function testInsert() {
|
||||
public function testSimpleInsert() {
|
||||
$userPersister = new Doctrine_ORM_Persisters_StandardEntityPersister(
|
||||
$this->_emMock, $this->_emMock->getClassMetadata("ForumUser"));
|
||||
$avatarPersister = new Doctrine_ORM_Persisters_StandardEntityPersister(
|
||||
$this->_emMock, $this->_emMock->getClassMetadata("ForumAvatar"));
|
||||
|
||||
$user = new ForumUser();
|
||||
$user->username = "romanb";
|
||||
$user->avatar = new ForumAvatar();
|
||||
|
||||
$this->_uowMock->setDataChangeSet($user, array(
|
||||
'username' => array('' => 'romanb'),
|
||||
'avatar' => array('' => $user->avatar)));
|
||||
|
||||
|
||||
//insert
|
||||
$this->_persister->insert($user->avatar);
|
||||
$avatarPersister->insert($user->avatar);
|
||||
$inserts = $this->_connMock->getInserts();
|
||||
//check
|
||||
$this->assertEquals(1, count($inserts));
|
||||
$this->assertEquals(null, $user->avatar->id);
|
||||
$user->avatar->id = 0; // fake we got id
|
||||
$this->assertTrue(isset($inserts['forum_avatar']));
|
||||
$this->assertEquals(1, count($inserts['forum_avatar']));
|
||||
$this->assertTrue(empty($inserts['forum_avatar'][0]));
|
||||
$this->assertEquals(null, $user->avatar->id);
|
||||
$user->avatar->id = 0; // Fake that we got an id
|
||||
|
||||
//insert
|
||||
$this->_persister->insert($user);
|
||||
$userPersister->insert($user);
|
||||
$inserts = $this->_connMock->getInserts();
|
||||
//check
|
||||
$this->assertEquals(2, count($inserts));
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
#namespace Doctrine::Tests::ORM::Hydration;
|
||||
#namespace Doctrine\Tests\ORM\Hydration;
|
||||
|
||||
require_once 'lib/DoctrineTestInit.php';
|
||||
require_once 'lib/mocks/Doctrine_HydratorMockStatement.php';
|
||||
@ -78,18 +78,22 @@ class Orm_Hydration_BasicHydrationTest extends Doctrine_OrmTestCase
|
||||
|
||||
if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_ARRAY || $hydrationMode == Doctrine_ORM_Query::HYDRATE_OBJECT) {
|
||||
$this->assertEquals(2, count($result));
|
||||
$this->assertEquals(1, $result[0]['id']);
|
||||
$this->assertEquals('romanb', $result[0]['name']);
|
||||
$this->assertEquals(2, $result[1]['id']);
|
||||
$this->assertEquals('jwage', $result[1]['name']);
|
||||
}
|
||||
|
||||
if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_OBJECT) {
|
||||
$this->assertTrue($result instanceof Doctrine_ORM_Collection);
|
||||
$this->assertTrue($result[0] instanceof Doctrine_ORM_Entity);
|
||||
$this->assertTrue($result[1] instanceof Doctrine_ORM_Entity);
|
||||
$this->assertTrue($result[0] instanceof CmsUser);
|
||||
$this->assertTrue($result[1] instanceof CmsUser);
|
||||
$this->assertEquals(1, $result[0]->id);
|
||||
$this->assertEquals('romanb', $result[0]->name);
|
||||
$this->assertEquals(2, $result[1]->id);
|
||||
$this->assertEquals('jwage', $result[1]->name);
|
||||
} else if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_ARRAY) {
|
||||
$this->assertTrue(is_array($result));
|
||||
$this->assertEquals(1, $result[0]['id']);
|
||||
$this->assertEquals('romanb', $result[0]['name']);
|
||||
$this->assertEquals(2, $result[1]['id']);
|
||||
$this->assertEquals('jwage', $result[1]['name']);
|
||||
} else if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_SCALAR) {
|
||||
$this->assertTrue(is_array($result));
|
||||
$this->assertEquals(2, count($result));
|
||||
@ -172,7 +176,27 @@ class Orm_Hydration_BasicHydrationTest extends Doctrine_OrmTestCase
|
||||
$this->assertTrue(is_array($result));
|
||||
$this->assertTrue(is_array($result[0]));
|
||||
$this->assertTrue(is_array($result[1]));
|
||||
}
|
||||
|
||||
if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_OBJECT) {
|
||||
$this->assertTrue($result[0][0] instanceof CmsUser);
|
||||
$this->assertTrue($result[0][0]->phonenumbers instanceof Doctrine_ORM_Collection);
|
||||
$this->assertTrue($result[0][0]->phonenumbers[0] instanceof CmsPhonenumber);
|
||||
$this->assertTrue($result[0][0]->phonenumbers[1] instanceof CmsPhonenumber);
|
||||
$this->assertTrue($result[1][0] instanceof CmsUser);
|
||||
$this->assertTrue($result[1][0]->phonenumbers instanceof Doctrine_ORM_Collection);
|
||||
|
||||
// first user => 2 phonenumbers
|
||||
$this->assertEquals(2, count($result[0][0]->phonenumbers));
|
||||
$this->assertEquals('ROMANB', $result[0]['nameUpper']);
|
||||
// second user => 1 phonenumber
|
||||
$this->assertEquals(1, count($result[1][0]->phonenumbers));
|
||||
$this->assertEquals('JWAGE', $result[1]['nameUpper']);
|
||||
|
||||
$this->assertEquals(42, $result[0][0]->phonenumbers[0]->phonenumber);
|
||||
$this->assertEquals(43, $result[0][0]->phonenumbers[1]->phonenumber);
|
||||
$this->assertEquals(91, $result[1][0]->phonenumbers[0]->phonenumber);
|
||||
} else if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_ARRAY) {
|
||||
// first user => 2 phonenumbers
|
||||
$this->assertEquals(2, count($result[0][0]['phonenumbers']));
|
||||
$this->assertEquals('ROMANB', $result[0]['nameUpper']);
|
||||
@ -183,15 +207,6 @@ class Orm_Hydration_BasicHydrationTest extends Doctrine_OrmTestCase
|
||||
$this->assertEquals(42, $result[0][0]['phonenumbers'][0]['phonenumber']);
|
||||
$this->assertEquals(43, $result[0][0]['phonenumbers'][1]['phonenumber']);
|
||||
$this->assertEquals(91, $result[1][0]['phonenumbers'][0]['phonenumber']);
|
||||
}
|
||||
|
||||
if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_OBJECT) {
|
||||
$this->assertTrue($result[0][0] instanceof Doctrine_ORM_Entity);
|
||||
$this->assertTrue($result[0][0]['phonenumbers'] instanceof Doctrine_ORM_Collection);
|
||||
$this->assertTrue($result[0][0]['phonenumbers'][0] instanceof Doctrine_ORM_Entity);
|
||||
$this->assertTrue($result[0][0]['phonenumbers'][1] instanceof Doctrine_ORM_Entity);
|
||||
$this->assertTrue($result[1][0] instanceof Doctrine_ORM_Entity);
|
||||
$this->assertTrue($result[1][0]['phonenumbers'] instanceof Doctrine_ORM_Collection);
|
||||
} else if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_SCALAR) {
|
||||
$this->assertTrue(is_array($result));
|
||||
$this->assertEquals(3, count($result));
|
||||
@ -265,7 +280,6 @@ class Orm_Hydration_BasicHydrationTest extends Doctrine_OrmTestCase
|
||||
$this->assertTrue(is_array($result));
|
||||
$this->assertTrue(is_array($result[0]));
|
||||
$this->assertTrue(is_array($result[1]));
|
||||
|
||||
// first user => 2 phonenumbers
|
||||
$this->assertEquals(2, $result[0]['numPhones']);
|
||||
// second user => 1 phonenumber
|
||||
@ -273,8 +287,8 @@ class Orm_Hydration_BasicHydrationTest extends Doctrine_OrmTestCase
|
||||
}
|
||||
|
||||
if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_OBJECT) {
|
||||
$this->assertTrue($result[0][0] instanceof Doctrine_ORM_Entity);
|
||||
$this->assertTrue($result[1][0] instanceof Doctrine_ORM_Entity);
|
||||
$this->assertTrue($result[0][0] instanceof CmsUser);
|
||||
$this->assertTrue($result[1][0] instanceof CmsUser);
|
||||
} else if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_SCALAR) {
|
||||
$this->assertEquals(2, count($result));
|
||||
|
||||
@ -351,7 +365,7 @@ class Orm_Hydration_BasicHydrationTest extends Doctrine_OrmTestCase
|
||||
|
||||
$result = $hydrator->hydrateResultSet($this->_createParserResult(
|
||||
$stmt, $queryComponents, $tableAliasMap, $hydrationMode, true));
|
||||
if ($hydrationMode == Doctrine::HYDRATE_ARRAY) {
|
||||
if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_ARRAY) {
|
||||
//var_dump($result);
|
||||
}
|
||||
|
||||
@ -361,26 +375,32 @@ class Orm_Hydration_BasicHydrationTest extends Doctrine_OrmTestCase
|
||||
$this->assertTrue(is_array($result[0]));
|
||||
$this->assertTrue(is_array($result[1]));
|
||||
|
||||
// first user => 2 phonenumbers. notice the custom indexing by user id
|
||||
$this->assertEquals(2, count($result[0]['1']['phonenumbers']));
|
||||
// second user => 1 phonenumber. notice the custom indexing by user id
|
||||
$this->assertEquals(1, count($result[1]['2']['phonenumbers']));
|
||||
|
||||
// test the custom indexing of the phonenumbers
|
||||
$this->assertTrue(isset($result[0]['1']['phonenumbers']['42']));
|
||||
$this->assertTrue(isset($result[0]['1']['phonenumbers']['43']));
|
||||
$this->assertTrue(isset($result[1]['2']['phonenumbers']['91']));
|
||||
|
||||
// test the scalar values
|
||||
$this->assertEquals('ROMANB', $result[0]['nameUpper']);
|
||||
$this->assertEquals('JWAGE', $result[1]['nameUpper']);
|
||||
}
|
||||
|
||||
if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_OBJECT) {
|
||||
$this->assertTrue($result[0]['1'] instanceof Doctrine_ORM_Entity);
|
||||
$this->assertTrue($result[1]['2'] instanceof Doctrine_ORM_Entity);
|
||||
$this->assertTrue($result[0]['1']['phonenumbers'] instanceof Doctrine_ORM_Collection);
|
||||
$this->assertTrue($result[0]['1'] instanceof CmsUser);
|
||||
$this->assertTrue($result[1]['2'] instanceof CmsUser);
|
||||
$this->assertTrue($result[0]['1']->phonenumbers instanceof Doctrine_ORM_Collection);
|
||||
// first user => 2 phonenumbers. notice the custom indexing by user id
|
||||
$this->assertEquals(2, count($result[0]['1']->phonenumbers));
|
||||
// second user => 1 phonenumber. notice the custom indexing by user id
|
||||
$this->assertEquals(1, count($result[1]['2']->phonenumbers));
|
||||
// test the custom indexing of the phonenumbers
|
||||
$this->assertTrue(isset($result[0]['1']->phonenumbers['42']));
|
||||
$this->assertTrue(isset($result[0]['1']->phonenumbers['43']));
|
||||
$this->assertTrue(isset($result[1]['2']->phonenumbers['91']));
|
||||
} else if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_ARRAY) {
|
||||
// first user => 2 phonenumbers. notice the custom indexing by user id
|
||||
$this->assertEquals(2, count($result[0]['1']['phonenumbers']));
|
||||
// second user => 1 phonenumber. notice the custom indexing by user id
|
||||
$this->assertEquals(1, count($result[1]['2']['phonenumbers']));
|
||||
// test the custom indexing of the phonenumbers
|
||||
$this->assertTrue(isset($result[0]['1']['phonenumbers']['42']));
|
||||
$this->assertTrue(isset($result[0]['1']['phonenumbers']['43']));
|
||||
$this->assertTrue(isset($result[1]['2']['phonenumbers']['91']));
|
||||
} else if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_SCALAR) {
|
||||
// NOTE: Indexing has no effect with HYDRATE_SCALAR
|
||||
//... asserts to come
|
||||
@ -500,7 +520,22 @@ class Orm_Hydration_BasicHydrationTest extends Doctrine_OrmTestCase
|
||||
$this->assertTrue(is_array($result));
|
||||
$this->assertTrue(is_array($result[0]));
|
||||
$this->assertTrue(is_array($result[1]));
|
||||
}
|
||||
|
||||
if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_OBJECT) {
|
||||
$this->assertTrue($result[0][0] instanceof CmsUser);
|
||||
$this->assertTrue($result[0][0]->phonenumbers instanceof Doctrine_ORM_Collection);
|
||||
$this->assertTrue($result[0][0]->phonenumbers[0] instanceof CmsPhonenumber);
|
||||
$this->assertTrue($result[0][0]->phonenumbers[1] instanceof CmsPhonenumber);
|
||||
$this->assertTrue($result[0][0]->articles instanceof Doctrine_ORM_Collection);
|
||||
$this->assertTrue($result[0][0]->articles[0] instanceof CmsArticle);
|
||||
$this->assertTrue($result[0][0]->articles[1] instanceof CmsArticle);
|
||||
$this->assertTrue($result[1][0] instanceof CmsUser);
|
||||
$this->assertTrue($result[1][0]->phonenumbers instanceof Doctrine_ORM_Collection);
|
||||
$this->assertTrue($result[1][0]->phonenumbers[0] instanceof CmsPhonenumber);
|
||||
$this->assertTrue($result[1][0]->articles[0] instanceof CmsArticle);
|
||||
$this->assertTrue($result[1][0]->articles[1] instanceof CmsArticle);
|
||||
} else if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_ARRAY) {
|
||||
// first user => 2 phonenumbers, 2 articles
|
||||
$this->assertEquals(2, count($result[0][0]['phonenumbers']));
|
||||
$this->assertEquals(2, count($result[0][0]['articles']));
|
||||
@ -518,21 +553,6 @@ class Orm_Hydration_BasicHydrationTest extends Doctrine_OrmTestCase
|
||||
$this->assertEquals('ZendCon', $result[0][0]['articles'][1]['topic']);
|
||||
$this->assertEquals('LINQ', $result[1][0]['articles'][0]['topic']);
|
||||
$this->assertEquals('PHP6', $result[1][0]['articles'][1]['topic']);
|
||||
}
|
||||
|
||||
if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_OBJECT) {
|
||||
$this->assertTrue($result[0][0] instanceof Doctrine_ORM_Entity);
|
||||
$this->assertTrue($result[0][0]['phonenumbers'] instanceof Doctrine_ORM_Collection);
|
||||
$this->assertTrue($result[0][0]['phonenumbers'][0] instanceof Doctrine_ORM_Entity);
|
||||
$this->assertTrue($result[0][0]['phonenumbers'][1] instanceof Doctrine_ORM_Entity);
|
||||
$this->assertTrue($result[0][0]['articles'] instanceof Doctrine_ORM_Collection);
|
||||
$this->assertTrue($result[0][0]['articles'][0] instanceof Doctrine_ORM_Entity);
|
||||
$this->assertTrue($result[0][0]['articles'][1] instanceof Doctrine_ORM_Entity);
|
||||
$this->assertTrue($result[1][0] instanceof Doctrine_ORM_Entity);
|
||||
$this->assertTrue($result[1][0]['phonenumbers'] instanceof Doctrine_ORM_Collection);
|
||||
$this->assertTrue($result[1][0]['phonenumbers'][0] instanceof Doctrine_ORM_Entity);
|
||||
$this->assertTrue($result[1][0]['articles'][0] instanceof Doctrine_ORM_Entity);
|
||||
$this->assertTrue($result[1][0]['articles'][1] instanceof Doctrine_ORM_Entity);
|
||||
} else if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_SCALAR) {
|
||||
//...
|
||||
$this->assertEquals(6, count($result));
|
||||
@ -675,7 +695,36 @@ class Orm_Hydration_BasicHydrationTest extends Doctrine_OrmTestCase
|
||||
$this->assertTrue(is_array($result));
|
||||
$this->assertTrue(is_array($result[0]));
|
||||
$this->assertTrue(is_array($result[1]));
|
||||
}
|
||||
|
||||
if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_OBJECT) {
|
||||
$this->assertTrue($result[0][0] instanceof CmsUser);
|
||||
$this->assertTrue($result[1][0] instanceof CmsUser);
|
||||
// phonenumbers
|
||||
$this->assertTrue($result[0][0]->phonenumbers instanceof Doctrine_ORM_Collection);
|
||||
$this->assertTrue($result[0][0]->phonenumbers[0] instanceof CmsPhonenumber);
|
||||
$this->assertTrue($result[0][0]->phonenumbers[1] instanceof CmsPhonenumber);
|
||||
$this->assertTrue($result[1][0]->phonenumbers instanceof Doctrine_ORM_Collection);
|
||||
$this->assertTrue($result[1][0]->phonenumbers[0] instanceof CmsPhonenumber);
|
||||
// articles
|
||||
$this->assertTrue($result[0][0]->articles instanceof Doctrine_ORM_Collection);
|
||||
$this->assertTrue($result[0][0]->articles[0] instanceof CmsArticle);
|
||||
$this->assertTrue($result[0][0]->articles[1] instanceof CmsArticle);
|
||||
$this->assertTrue($result[1][0]->articles[0] instanceof CmsArticle);
|
||||
$this->assertTrue($result[1][0]->articles[1] instanceof CmsArticle);
|
||||
// article comments
|
||||
$this->assertTrue($result[0][0]->articles[0]->comments instanceof Doctrine_ORM_Collection);
|
||||
$this->assertTrue($result[0][0]->articles[0]->comments[0] instanceof CmsComment);
|
||||
// empty comment collections
|
||||
$this->assertTrue($result[0][0]->articles[1]->comments instanceof Doctrine_ORM_Collection);
|
||||
$this->assertEquals(0, count($result[0][0]->articles[1]->comments));
|
||||
$this->assertTrue($result[1][0]->articles[0]->comments instanceof Doctrine_ORM_Collection);
|
||||
$this->assertEquals(0, count($result[1][0]->articles[0]->comments));
|
||||
$this->assertTrue($result[1][0]->articles[1]->comments instanceof Doctrine_ORM_Collection);
|
||||
$this->assertEquals(0, count($result[1][0]->articles[1]->comments));
|
||||
} else if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_SCALAR) {
|
||||
//...
|
||||
} else if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_ARRAY) {
|
||||
// first user => 2 phonenumbers, 2 articles, 1 comment on first article
|
||||
$this->assertEquals(2, count($result[0][0]['phonenumbers']));
|
||||
$this->assertEquals(2, count($result[0][0]['articles']));
|
||||
@ -698,41 +747,6 @@ class Orm_Hydration_BasicHydrationTest extends Doctrine_OrmTestCase
|
||||
$this->assertEquals('First!', $result[0][0]['articles'][0]['comments'][0]['topic']);
|
||||
|
||||
$this->assertTrue(isset($result[0][0]['articles'][0]['comments']));
|
||||
// empty collections/arrays
|
||||
$this->assertTrue(isset($result[0][0]['articles'][1]['comments']));
|
||||
$this->assertTrue(isset($result[1][0]['articles'][0]['comments']));
|
||||
$this->assertTrue(isset($result[1][0]['articles'][1]['comments']));
|
||||
}
|
||||
|
||||
if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_OBJECT) {
|
||||
$this->assertTrue($result[0][0] instanceof Doctrine_ORM_Entity);
|
||||
$this->assertTrue($result[1][0] instanceof Doctrine_ORM_Entity);
|
||||
// phonenumbers
|
||||
$this->assertTrue($result[0][0]['phonenumbers'] instanceof Doctrine_ORM_Collection);
|
||||
$this->assertTrue($result[0][0]['phonenumbers'][0] instanceof Doctrine_ORM_Entity);
|
||||
$this->assertTrue($result[0][0]['phonenumbers'][1] instanceof Doctrine_ORM_Entity);
|
||||
$this->assertTrue($result[1][0]['phonenumbers'] instanceof Doctrine_ORM_Collection);
|
||||
$this->assertTrue($result[1][0]['phonenumbers'][0] instanceof Doctrine_ORM_Entity);
|
||||
// articles
|
||||
$this->assertTrue($result[0][0]['articles'] instanceof Doctrine_ORM_Collection);
|
||||
$this->assertTrue($result[0][0]['articles'][0] instanceof Doctrine_ORM_Entity);
|
||||
$this->assertTrue($result[0][0]['articles'][1] instanceof Doctrine_ORM_Entity);
|
||||
$this->assertTrue($result[1][0]['articles'][0] instanceof Doctrine_ORM_Entity);
|
||||
$this->assertTrue($result[1][0]['articles'][1] instanceof Doctrine_ORM_Entity);
|
||||
// article comments
|
||||
$this->assertTrue($result[0][0]['articles'][0]['comments'] instanceof Doctrine_ORM_Collection);
|
||||
$this->assertTrue($result[0][0]['articles'][0]['comments'][0] instanceof Doctrine_ORM_Entity);
|
||||
// empty comment collections
|
||||
$this->assertTrue($result[0][0]['articles'][1]['comments'] instanceof Doctrine_ORM_Collection);
|
||||
$this->assertEquals(0, count($result[0][0]['articles'][1]['comments']));
|
||||
$this->assertTrue($result[1][0]['articles'][0]['comments'] instanceof Doctrine_ORM_Collection);
|
||||
$this->assertEquals(0, count($result[1][0]['articles'][0]['comments']));
|
||||
$this->assertTrue($result[1][0]['articles'][1]['comments'] instanceof Doctrine_ORM_Collection);
|
||||
$this->assertEquals(0, count($result[1][0]['articles'][1]['comments']));
|
||||
} else if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_SCALAR) {
|
||||
//...
|
||||
} else if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_ARRAY) {
|
||||
//...
|
||||
|
||||
// empty comment collections
|
||||
$this->assertTrue(is_array($result[0][0]['articles'][1]['comments']));
|
||||
@ -798,7 +812,7 @@ class Orm_Hydration_BasicHydrationTest extends Doctrine_OrmTestCase
|
||||
'c__name' => 'First',
|
||||
'b__id' => '1',
|
||||
'b__position' => '0',
|
||||
'b__category_id' => '1'
|
||||
//'b__category_id' => '1'
|
||||
),
|
||||
array(
|
||||
'c__id' => '2',
|
||||
@ -806,7 +820,7 @@ class Orm_Hydration_BasicHydrationTest extends Doctrine_OrmTestCase
|
||||
'c__name' => 'Second',
|
||||
'b__id' => '2',
|
||||
'b__position' => '0',
|
||||
'b__category_id' => '2'
|
||||
//'b__category_id' => '2'
|
||||
),
|
||||
array(
|
||||
'c__id' => '1',
|
||||
@ -814,7 +828,7 @@ class Orm_Hydration_BasicHydrationTest extends Doctrine_OrmTestCase
|
||||
'c__name' => 'First',
|
||||
'b__id' => '3',
|
||||
'b__position' => '1',
|
||||
'b__category_id' => '1'
|
||||
//'b__category_id' => '1'
|
||||
),
|
||||
array(
|
||||
'c__id' => '1',
|
||||
@ -822,7 +836,7 @@ class Orm_Hydration_BasicHydrationTest extends Doctrine_OrmTestCase
|
||||
'c__name' => 'First',
|
||||
'b__id' => '4',
|
||||
'b__position' => '2',
|
||||
'b__category_id' => '1'
|
||||
//'b__category_id' => '1'
|
||||
)
|
||||
);
|
||||
|
||||
@ -837,20 +851,26 @@ class Orm_Hydration_BasicHydrationTest extends Doctrine_OrmTestCase
|
||||
|
||||
if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_ARRAY || $hydrationMode == Doctrine_ORM_Query::HYDRATE_OBJECT) {
|
||||
$this->assertEquals(2, count($result));
|
||||
$this->assertTrue(isset($result[0]['boards']));
|
||||
$this->assertEquals(3, count($result[0]['boards']));
|
||||
$this->assertTrue(isset($result[1]['boards']));
|
||||
$this->assertEquals(1, count($result[1]['boards']));
|
||||
}
|
||||
|
||||
if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_ARRAY) {
|
||||
$this->assertTrue(is_array($result));
|
||||
$this->assertTrue(is_array($result[0]));
|
||||
$this->assertTrue(is_array($result[1]));
|
||||
$this->assertTrue(isset($result[0]['boards']));
|
||||
$this->assertEquals(3, count($result[0]['boards']));
|
||||
$this->assertTrue(isset($result[1]['boards']));
|
||||
$this->assertEquals(1, count($result[1]['boards']));
|
||||
} else if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_OBJECT) {
|
||||
$this->assertTrue($result instanceof Doctrine_ORM_Collection);
|
||||
$this->assertTrue($result[0] instanceof Doctrine_ORM_Entity);
|
||||
$this->assertTrue($result[1] instanceof Doctrine_ORM_Entity);
|
||||
$this->assertTrue($result[0] instanceof ForumCategory);
|
||||
$this->assertTrue($result[1] instanceof ForumCategory);
|
||||
$this->assertEquals(1, $result[0]->getId());
|
||||
$this->assertEquals(2, $result[1]->getId());
|
||||
$this->assertTrue(isset($result[0]->boards));
|
||||
$this->assertEquals(3, count($result[0]->boards));
|
||||
$this->assertTrue(isset($result[1]->boards));
|
||||
$this->assertEquals(1, count($result[1]->boards));
|
||||
} else if ($hydrationMode == Doctrine_ORM_Query::HYDRATE_SCALAR) {
|
||||
//...
|
||||
}
|
||||
@ -938,4 +958,77 @@ class Orm_Hydration_BasicHydrationTest extends Doctrine_OrmTestCase
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* select u.id, u.status, p.phonenumber, upper(u.name) nameUpper from User u
|
||||
* join u.phonenumbers p
|
||||
* =
|
||||
* select u.id, u.status, p.phonenumber, upper(u.name) as u__0 from USERS u
|
||||
* INNER JOIN PHONENUMBERS p ON u.id = p.user_id
|
||||
*
|
||||
* @dataProvider hydrationModeProvider
|
||||
*/
|
||||
/*public function testNewHydrationMixedQueryFetchJoinPerformance($hydrationMode)
|
||||
{
|
||||
// Faked query components
|
||||
$queryComponents = array(
|
||||
'u' => array(
|
||||
'metadata' => $this->_em->getClassMetadata('CmsUser'),
|
||||
'parent' => null,
|
||||
'relation' => null,
|
||||
'map' => null,
|
||||
'agg' => array('0' => 'nameUpper')
|
||||
),
|
||||
'p' => array(
|
||||
'metadata' => $this->_em->getClassMetadata('CmsPhonenumber'),
|
||||
'parent' => 'u',
|
||||
'relation' => $this->_em->getClassMetadata('CmsUser')->getAssociationMapping('phonenumbers'),
|
||||
'map' => null
|
||||
)
|
||||
);
|
||||
|
||||
// Faked table alias map
|
||||
$tableAliasMap = array(
|
||||
'u' => 'u',
|
||||
'p' => 'p'
|
||||
);
|
||||
|
||||
// Faked result set
|
||||
$resultSet = array(
|
||||
//row1
|
||||
array(
|
||||
'u__id' => '1',
|
||||
'u__status' => 'developer',
|
||||
'u__0' => 'ROMANB',
|
||||
'p__phonenumber' => '42',
|
||||
),
|
||||
array(
|
||||
'u__id' => '1',
|
||||
'u__status' => 'developer',
|
||||
'u__0' => 'ROMANB',
|
||||
'p__phonenumber' => '43',
|
||||
),
|
||||
array(
|
||||
'u__id' => '2',
|
||||
'u__status' => 'developer',
|
||||
'u__0' => 'JWAGE',
|
||||
'p__phonenumber' => '91'
|
||||
)
|
||||
);
|
||||
for ($i=4; $i<5000; $i++) {
|
||||
$resultSet[] = array(
|
||||
'u__id' => $i,
|
||||
'u__status' => 'developer',
|
||||
'u__0' => 'JWAGE' . $i,
|
||||
'p__phonenumber' => '91'
|
||||
);
|
||||
}
|
||||
|
||||
$stmt = new Doctrine_HydratorMockStatement($resultSet);
|
||||
$hydrator = new Doctrine_ORM_Internal_Hydration_StandardHydrator($this->_em);
|
||||
|
||||
$result = $hydrator->hydrateResultSet($this->_createParserResult(
|
||||
$stmt, $queryComponents, $tableAliasMap, $hydrationMode, true));
|
||||
}*/
|
||||
|
||||
}
|
||||
|
@ -24,21 +24,15 @@ class Orm_UnitOfWorkTest extends Doctrine_OrmTestCase
|
||||
private $_persisterMock;
|
||||
// The EntityManager mock that provides the mock persister
|
||||
private $_emMock;
|
||||
private $_platformMock;
|
||||
private $_classMetadataMock;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->_connectionMock = new Doctrine_ConnectionMock(array());
|
||||
$this->_platformMock = new Doctrine_DatabasePlatformMock();
|
||||
$this->_platformMock->setPrefersIdentityColumns(true);
|
||||
$this->_emMock = Doctrine_EntityManagerMock::create($this->_connectionMock, "uowMockEm");
|
||||
$this->_idGeneratorMock = new Doctrine_SequenceMock($this->_emMock);
|
||||
$this->_connectionMock->setDatabasePlatform($this->_platformMock);
|
||||
|
||||
$this->_classMetadataMock = new Doctrine_ClassMetadataMock("ForumUser", $this->_emMock);
|
||||
$this->_classMetadataMock->setIdGenerator($this->_idGeneratorMock);
|
||||
$this->_emMock->setIdGenerator('ForumUser', $this->_idGeneratorMock);
|
||||
$this->_emMock->setIdGenerator('ForumAvatar', $this->_idGeneratorMock);
|
||||
|
||||
$this->_persisterMock = new Doctrine_EntityPersisterMock(
|
||||
$this->_emMock, $this->_emMock->getClassMetadata("ForumUser"));
|
||||
@ -55,7 +49,7 @@ class Orm_UnitOfWorkTest extends Doctrine_OrmTestCase
|
||||
}
|
||||
|
||||
protected function tearDown() {
|
||||
$this->_user->free();
|
||||
//$this->_user->free();
|
||||
}
|
||||
|
||||
/* Basic registration tests */
|
||||
@ -83,16 +77,6 @@ class Orm_UnitOfWorkTest extends Doctrine_OrmTestCase
|
||||
echo $e - $s . " seconds" . PHP_EOL;
|
||||
}*/
|
||||
|
||||
public function testRegisterDirty()
|
||||
{
|
||||
$this->assertEquals(Doctrine_ORM_Entity::STATE_NEW, $this->_user->_state());
|
||||
$this->assertFalse($this->_unitOfWork->isInIdentityMap($this->_user));
|
||||
$this->_unitOfWork->registerDirty($this->_user);
|
||||
$this->assertTrue($this->_unitOfWork->isRegisteredDirty($this->_user));
|
||||
$this->assertFalse($this->_unitOfWork->isRegisteredNew($this->_user));
|
||||
$this->assertFalse($this->_unitOfWork->isRegisteredRemoved($this->_user));
|
||||
}
|
||||
|
||||
public function testRegisterRemovedOnNewEntityIsIgnored()
|
||||
{
|
||||
$this->assertFalse($this->_unitOfWork->isRegisteredRemoved($this->_user));
|
||||
@ -105,8 +89,6 @@ class Orm_UnitOfWorkTest extends Doctrine_OrmTestCase
|
||||
|
||||
public function testSavingSingleEntityWithIdentityColumnForcesInsert()
|
||||
{
|
||||
$this->assertEquals(Doctrine_ORM_Entity::STATE_NEW, $this->_user->_state());
|
||||
|
||||
$this->_unitOfWork->save($this->_user);
|
||||
|
||||
$this->assertEquals(1, count($this->_persisterMock->getInserts())); // insert forced
|
||||
@ -114,7 +96,6 @@ class Orm_UnitOfWorkTest extends Doctrine_OrmTestCase
|
||||
$this->assertEquals(0, count($this->_persisterMock->getDeletes()));
|
||||
|
||||
$this->assertTrue($this->_unitOfWork->isInIdentityMap($this->_user));
|
||||
$this->assertEquals(Doctrine_ORM_Entity::STATE_MANAGED, $this->_user->_state());
|
||||
|
||||
// should no longer be scheduled for insert
|
||||
$this->assertFalse($this->_unitOfWork->isRegisteredNew($this->_user));
|
||||
@ -149,7 +130,7 @@ class Orm_UnitOfWorkTest extends Doctrine_OrmTestCase
|
||||
|
||||
//...
|
||||
}
|
||||
|
||||
/*
|
||||
public function testSavingSingleEntityWithSequenceIdGeneratorSchedulesInsert()
|
||||
{
|
||||
//...
|
||||
@ -189,5 +170,5 @@ class Orm_UnitOfWorkTest extends Doctrine_OrmTestCase
|
||||
{
|
||||
//...
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
@ -8,11 +8,6 @@ class Doctrine_DbalTestCase extends Doctrine_TestCase
|
||||
|
||||
/**
|
||||
* setUp()
|
||||
*
|
||||
* Note: This setUp() and the one of OrmTestCase currently look identical. However,
|
||||
* please dont pull this method up. In the future with a separation of Dbal/Orm
|
||||
* this setUp() will take care of a DBAL connection and the ORM setUp() will take care
|
||||
* of an ORM connection/session/manager.
|
||||
*/
|
||||
protected function setUp()
|
||||
{
|
||||
|
@ -22,24 +22,6 @@ class Doctrine_OrmFunctionalTestCase extends Doctrine_OrmTestCase
|
||||
*/
|
||||
private static $_exportedTables = array();
|
||||
|
||||
/**
|
||||
* setUp()
|
||||
*
|
||||
* Note: This setUp() and the one of DbalTestCase currently look identical. However,
|
||||
* please dont pull this method up. In the future with a separation of Dbal/Orm
|
||||
* this setUp() will take care of a ORM connection/session/manager initialization
|
||||
* and the DBAL setUp() will take care of just a DBAL connection.
|
||||
*/
|
||||
protected function setUp()
|
||||
{
|
||||
// Setup a db connection if there is none, yet. This makes it possible
|
||||
// to run tests that use a connection standalone.
|
||||
if ( ! isset($this->sharedFixture['em'])) {
|
||||
$this->sharedFixture['em'] = new Doctrine_EntityManager(
|
||||
Doctrine_TestUtil::getConnection());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a data fixture into the database. This method must only be called
|
||||
* from within the setUp() method of testcases. The database will then be
|
||||
@ -78,7 +60,7 @@ class Doctrine_OrmFunctionalTestCase extends Doctrine_OrmTestCase
|
||||
$tableName = $classMetadata->getTableName();
|
||||
|
||||
if ( ! in_array($tableName, self::$_exportedTables)) {
|
||||
$em->getConnection()->export->exportClasses(array($fixture['model']));
|
||||
$em->getConnection()->getSchemaManager()->exportClasses(array($fixture['model']));
|
||||
self::$_exportedTables[] = $tableName;
|
||||
}
|
||||
|
||||
|
@ -10,8 +10,6 @@ class Doctrine_OrmFunctionalTestSuite extends Doctrine_OrmTestSuite
|
||||
{
|
||||
protected function setUp()
|
||||
{
|
||||
$this->sharedFixture['em'] = new Doctrine_EntityManager(
|
||||
Doctrine_TestUtil::getConnection());
|
||||
}
|
||||
|
||||
protected function tearDown()
|
||||
|
@ -10,7 +10,6 @@ require_once 'lib/mocks/Doctrine_ConnectionMock.php';
|
||||
class Doctrine_OrmTestCase extends Doctrine_TestCase
|
||||
{
|
||||
protected $_em;
|
||||
protected $_emf;
|
||||
|
||||
protected function setUp() {
|
||||
if (isset($this->sharedFixture['em'])) {
|
||||
|
@ -13,8 +13,6 @@ class Doctrine_TestUtil
|
||||
'host' => $GLOBALS['db_host'],
|
||||
'database' => $GLOBALS['db_name']
|
||||
);
|
||||
//$dsn = "{$GLOBALS['db_type']}://{$GLOBALS['db_username']}:{$GLOBALS['db_password']}@{$GLOBALS['db_host']}/{$GLOBALS['db_name']}";
|
||||
//return Doctrine_Manager::connection($dsn, 'testconn');
|
||||
} else {
|
||||
$params = array(
|
||||
'driver' => 'pdo_sqlite',
|
||||
@ -24,13 +22,4 @@ class Doctrine_TestUtil
|
||||
|
||||
return Doctrine_DBAL_DriverManager::getConnection($params);
|
||||
}
|
||||
/*
|
||||
public static function autoloadModel($className)
|
||||
{
|
||||
$modelDir = dirname(__CLASS__) . '/../models/';
|
||||
$fileName = $modelDir . str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';
|
||||
if (file_exists($fileName)) {
|
||||
require $fileName;
|
||||
}
|
||||
}*/
|
||||
}
|
@ -2,12 +2,10 @@
|
||||
|
||||
class Doctrine_ClassMetadataMock extends Doctrine_ORM_Mapping_ClassMetadata
|
||||
{
|
||||
|
||||
|
||||
/* Mock API */
|
||||
|
||||
public function setIdGenerator(Doctrine_ORM_Id_AbstractIdGenerator $g) {
|
||||
$this->_idGenerator = $g;
|
||||
public function setIdGeneratorType($type) {
|
||||
$this->_generatorType = $type;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5,20 +5,33 @@ require_once 'lib/mocks/Doctrine_EntityPersisterMock.php';
|
||||
class Doctrine_EntityManagerMock extends Doctrine_ORM_EntityManager
|
||||
{
|
||||
private $_persisterMock;
|
||||
private $_uowMock;
|
||||
private $_idGenerators = array();
|
||||
|
||||
/**
|
||||
* Enter description here...
|
||||
*
|
||||
* @param unknown_type $entityName
|
||||
* @override
|
||||
*/
|
||||
public function getEntityPersister($entityName)
|
||||
{
|
||||
return $this->_persisterMock;
|
||||
return isset($this->_persisterMock) ? $this->_persisterMock :
|
||||
parent::getEntityPersister($entityName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public function getUnitOfWork()
|
||||
{
|
||||
return isset($this->_uowMock) ? $this->_uowMock : parent::getUnitOfWork();
|
||||
}
|
||||
|
||||
/* Mock API */
|
||||
|
||||
public function setUnitOfWork($uow)
|
||||
{
|
||||
$this->_uowMock = $uow;
|
||||
}
|
||||
|
||||
public function setEntityPersister($persister)
|
||||
{
|
||||
$this->_persisterMock = $persister;
|
||||
@ -45,6 +58,19 @@ class Doctrine_EntityManagerMock extends Doctrine_ORM_EntityManager
|
||||
|
||||
return new Doctrine_EntityManagerMock($conn, $name, $config, $eventManager);
|
||||
}
|
||||
|
||||
public function setIdGenerator($className, $generator)
|
||||
{
|
||||
$this->_idGenerators[$className] = $generator;
|
||||
}
|
||||
|
||||
public function getIdGenerator($className)
|
||||
{
|
||||
if (isset($this->_idGenerators[$className])) {
|
||||
return $this->_idGenerators[$className];
|
||||
}
|
||||
return parent::getIdGenerator($className);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -8,10 +8,11 @@ class Doctrine_EntityPersisterMock extends Doctrine_ORM_Persisters_StandardEntit
|
||||
|
||||
private $_identityColumnValueCounter = 0;
|
||||
|
||||
public function insert(Doctrine_ORM_Entity $entity)
|
||||
public function insert($entity)
|
||||
{
|
||||
if ($entity->getClass()->isIdGeneratorIdentity()) {
|
||||
$entity->_assignIdentifier($this->_identityColumnValueCounter++);
|
||||
$class = $this->_em->getClassMetadata(get_class($entity));
|
||||
if ($class->isIdGeneratorIdentity()) {
|
||||
$class->setEntityIdentifier($entity, $this->_identityColumnValueCounter++);
|
||||
$this->_em->getUnitOfWork()->addToIdentityMap($entity);
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@ class Doctrine_SequenceMock extends Doctrine_ORM_Id_SequenceGenerator
|
||||
* @param Doctrine_Entity $entity
|
||||
* @override
|
||||
*/
|
||||
public function generate(Doctrine_ORM_Entity $entity)
|
||||
public function generate($entity)
|
||||
{
|
||||
return $this->_sequenceNumber++;
|
||||
}
|
||||
|
31
tests/lib/mocks/Doctrine_UnitOfWorkMock.php
Normal file
31
tests/lib/mocks/Doctrine_UnitOfWorkMock.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Description of Doctrine_UnitOfWorkMock
|
||||
*
|
||||
* @author robo
|
||||
*/
|
||||
class Doctrine_UnitOfWorkMock extends Doctrine_ORM_UnitOfWork {
|
||||
private $_mockDataChangeSets = array();
|
||||
|
||||
/**
|
||||
* @param <type> $entity
|
||||
* @override
|
||||
*/
|
||||
public function getDataChangeSet($entity) {
|
||||
$oid = spl_object_id($entity);
|
||||
return isset($this->_mockDataChangeSets[$oid]) ?
|
||||
$this->_mockDataChangeSets[$oid] : parent::getDataChangeSet($entity);
|
||||
}
|
||||
|
||||
/* MOCK API */
|
||||
|
||||
public function setDataChangeSet($entity, array $mockChangeSet) {
|
||||
$this->_mockDataChangeSets[spl_object_id($entity)] = $mockChangeSet;
|
||||
}
|
||||
}
|
||||
|
@ -4,19 +4,28 @@
|
||||
|
||||
#use Doctrine::ORM::Entity;
|
||||
|
||||
class CmsArticle extends Doctrine_ORM_Entity
|
||||
class CmsArticle
|
||||
{
|
||||
#protected $id;
|
||||
#protected $topic;
|
||||
#protected $text;
|
||||
#protected $user_id;
|
||||
public $id;
|
||||
public $topic;
|
||||
public $text;
|
||||
public $user;
|
||||
public $comments;
|
||||
|
||||
/*static function construct() {
|
||||
Doctrine_Common_VirtualPropertySystem::register(__CLASS__, 'id', 'int');
|
||||
Doctrine_Common_VirtualPropertySystem::register(__CLASS__, 'topic', 'string');
|
||||
Doctrine_Common_VirtualPropertySystem::register(__CLASS__, 'text', 'string');
|
||||
Doctrine_Common_VirtualPropertySystem::register(__CLASS__, 'user_id', 'int');
|
||||
Doctrine_Common_VirtualPropertySystem::register(__CLASS__, 'user', 'CmsUser');
|
||||
Doctrine_Common_VirtualPropertySystem::register(__CLASS__, 'comments', 'collection');
|
||||
}*/
|
||||
|
||||
public static function initMetadata($mapping)
|
||||
{
|
||||
$mapping->mapField(array(
|
||||
'fieldName' => 'id',
|
||||
'type' => 'integer',
|
||||
'length' => 4,
|
||||
'id' => true,
|
||||
'idGenerator' => 'auto'
|
||||
));
|
||||
@ -31,11 +40,9 @@ class CmsArticle extends Doctrine_ORM_Entity
|
||||
));
|
||||
$mapping->mapField(array(
|
||||
'fieldName' => 'user_id',
|
||||
'type' => 'integer',
|
||||
'length' => 4
|
||||
'type' => 'integer'
|
||||
));
|
||||
|
||||
|
||||
$mapping->mapOneToMany(array(
|
||||
'fieldName' => 'comments',
|
||||
'targetEntity' => 'CmsComment',
|
||||
|
@ -4,19 +4,26 @@
|
||||
|
||||
#use Doctrine::ORM::Entity;
|
||||
|
||||
class CmsComment extends Doctrine_ORM_Entity
|
||||
class CmsComment
|
||||
{
|
||||
#protected $id;
|
||||
#protected $topic;
|
||||
#protected $text;
|
||||
#protected $article_id;
|
||||
public $id;
|
||||
public $topic;
|
||||
public $text;
|
||||
public $article;
|
||||
|
||||
/*static function construct() {
|
||||
Doctrine_Common_VirtualPropertySystem::register(__CLASS__, 'id', 'int');
|
||||
Doctrine_Common_VirtualPropertySystem::register(__CLASS__, 'topic', 'string');
|
||||
Doctrine_Common_VirtualPropertySystem::register(__CLASS__, 'text', 'string');
|
||||
Doctrine_Common_VirtualPropertySystem::register(__CLASS__, 'article_id', 'int');
|
||||
Doctrine_Common_VirtualPropertySystem::register(__CLASS__, 'article', 'CmsArticle');
|
||||
}*/
|
||||
|
||||
public static function initMetadata($mapping)
|
||||
{
|
||||
$mapping->mapField(array(
|
||||
'fieldName' => 'id',
|
||||
'type' => 'integer',
|
||||
'length' => 4,
|
||||
'id' => true,
|
||||
'generatorType' => 'auto'
|
||||
));
|
||||
@ -31,8 +38,7 @@ class CmsComment extends Doctrine_ORM_Entity
|
||||
));
|
||||
$mapping->mapField(array(
|
||||
'fieldName' => 'article_id',
|
||||
'type' => 'integer',
|
||||
'length' => 4
|
||||
'type' => 'integer'
|
||||
));
|
||||
|
||||
$mapping->mapManyToOne(array(
|
||||
|
@ -1,15 +1,20 @@
|
||||
<?php
|
||||
class CmsPhonenumber extends Doctrine_ORM_Entity
|
||||
class CmsPhonenumber
|
||||
{
|
||||
#protected $user_id;
|
||||
#protected $phonenumber;
|
||||
public $phonenumber;
|
||||
public $user;
|
||||
|
||||
/*static function construct() {
|
||||
Doctrine_Common_VirtualPropertySystem::register(__CLASS__, 'user_id', 'int');
|
||||
Doctrine_Common_VirtualPropertySystem::register(__CLASS__, 'phonenumber', 'string');
|
||||
Doctrine_Common_VirtualPropertySystem::register(__CLASS__, 'user', 'CmsUser');
|
||||
}*/
|
||||
|
||||
public static function initMetadata($mapping)
|
||||
{
|
||||
$mapping->mapField(array(
|
||||
'fieldName' => 'user_id',
|
||||
'type' => 'integer',
|
||||
'length' => 4
|
||||
'type' => 'integer'
|
||||
));
|
||||
$mapping->mapField(array(
|
||||
'fieldName' => 'phonenumber',
|
||||
|
@ -1,22 +1,48 @@
|
||||
<?php
|
||||
|
||||
#namespace Doctrine::Test::ORM::Models;
|
||||
#namespace Doctrine\Tests\ORM\Models\Cms;
|
||||
|
||||
#use Doctrine::ORM::Entity;
|
||||
#use Doctrine\ORM\Entity;
|
||||
#use Doctrine\Common\VirtualPropertySystem;
|
||||
|
||||
class CmsUser extends Doctrine_ORM_Entity
|
||||
class CmsUser
|
||||
{
|
||||
#protected $id;
|
||||
#protected $status;
|
||||
#protected $username;
|
||||
#protected $name;
|
||||
public $id;
|
||||
public $status;
|
||||
public $username;
|
||||
public $name;
|
||||
public $phonenumbers;
|
||||
public $articles;
|
||||
|
||||
/*static function construct() {
|
||||
Doctrine_Common_VirtualPropertySystem::register(__CLASS__, 'id', 'int');
|
||||
Doctrine_Common_VirtualPropertySystem::register(__CLASS__, 'status', 'int');
|
||||
Doctrine_Common_VirtualPropertySystem::register(__CLASS__, 'username', 'string');
|
||||
Doctrine_Common_VirtualPropertySystem::register(__CLASS__, 'name', 'string');
|
||||
Doctrine_Common_VirtualPropertySystem::register(__CLASS__, 'phonenumbers', 'CmsPhonenumber');
|
||||
Doctrine_Common_VirtualPropertySystem::register(__CLASS__, 'articles', 'CmsArticle');
|
||||
}*/
|
||||
|
||||
public static function initMetadata($mapping)
|
||||
{
|
||||
/* NEW
|
||||
$mapping->addFieldMetadata('id', array(
|
||||
'doctrine.id' => true, 'doctrine.idGenerator' => 'auto'
|
||||
));
|
||||
$mapping->addFieldMetadata('status', array(
|
||||
'doctrine.length' => 50
|
||||
));
|
||||
$mapping->addFieldMetadata('phonenumbers', array(
|
||||
'doctrine.oneToMany' => array('mappedBy' => 'user')
|
||||
));
|
||||
$mapping->addFieldMetadata('articles', array(
|
||||
'doctrine.oneToMany' => array('mappedBy' => 'user')
|
||||
));
|
||||
*/
|
||||
|
||||
$mapping->mapField(array(
|
||||
'fieldName' => 'id',
|
||||
'type' => 'integer',
|
||||
'length' => 4,
|
||||
'id' => true,
|
||||
'idGenerator' => 'auto'
|
||||
));
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
class CompanyEmployee extends Doctrine_ORM_Entity
|
||||
class CompanyEmployee
|
||||
{
|
||||
#protected $id;
|
||||
#protected $salary;
|
||||
|
@ -2,15 +2,14 @@
|
||||
|
||||
class ForumAdministrator extends ForumUser
|
||||
{
|
||||
public $accessLevel;
|
||||
|
||||
public static function initMetadata($mapping)
|
||||
{
|
||||
$mapping->mapField(array(
|
||||
'fieldName' => 'accessLevel',
|
||||
'columnName' => 'access_level',
|
||||
'type' => 'integer',
|
||||
'length' => 1
|
||||
'type' => 'integer'
|
||||
));
|
||||
}
|
||||
|
||||
public function banUser(ForumUser $user) {}
|
||||
}
|
@ -1,19 +1,27 @@
|
||||
<?php
|
||||
|
||||
class ForumAvatar extends Doctrine_ORM_Entity
|
||||
#namespace Doctrine\Tests\ORM\Models\Forum;
|
||||
|
||||
#use Doctrine\ORM\Entity;
|
||||
#use Doctrine\Common\VirtualPropertySystem;
|
||||
|
||||
class ForumAvatar
|
||||
{
|
||||
public $id;
|
||||
|
||||
/*static function construct() {
|
||||
Doctrine_Common_VirtualPropertySystem::register(__CLASS__, 'id', 'int');
|
||||
}*/
|
||||
|
||||
public static function initMetadata($mapping)
|
||||
{
|
||||
$mapping->mapField(array(
|
||||
'fieldName' => 'id',
|
||||
'type' => 'integer',
|
||||
'length' => 4,
|
||||
'id' => true,
|
||||
'idGenerator' => 'auto'
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,19 +1,15 @@
|
||||
<?php
|
||||
class ForumBoard extends Doctrine_ORM_Entity
|
||||
class ForumBoard
|
||||
{
|
||||
public $id;
|
||||
public $position;
|
||||
public $category;
|
||||
|
||||
public static function initMetadata($mapping)
|
||||
{
|
||||
/*$metadata->mapField(array(
|
||||
'fieldName' => 'id',
|
||||
'id' => true,
|
||||
'type' => 'integer',
|
||||
'length' => 4
|
||||
));
|
||||
*/
|
||||
$mapping->mapField(array(
|
||||
'fieldName' => 'id',
|
||||
'type' => 'integer',
|
||||
'length' => 4,
|
||||
'id' => true
|
||||
));
|
||||
$mapping->mapField(array(
|
||||
|
@ -1,13 +1,20 @@
|
||||
<?php
|
||||
class ForumCategory extends Doctrine_ORM_Entity
|
||||
class ForumCategory
|
||||
{
|
||||
private $id;
|
||||
public $position;
|
||||
public $name;
|
||||
public $boards;
|
||||
|
||||
public function getId() {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public static function initMetadata($mapping)
|
||||
{
|
||||
$mapping->mapField(array(
|
||||
'fieldName' => 'id',
|
||||
'type' => 'integer',
|
||||
'length' => 4,
|
||||
'id' => true
|
||||
));
|
||||
$mapping->mapField(array(
|
||||
|
@ -6,15 +6,19 @@
|
||||
|
||||
class ForumEntry extends Doctrine_ORM_Entity
|
||||
{
|
||||
#protected $id;
|
||||
#protected $topic;
|
||||
public $id;
|
||||
public $topic;
|
||||
|
||||
static function construct() {
|
||||
Doctrine_Common_VirtualPropertySystem::register(__CLASS__, 'id', 'int');
|
||||
Doctrine_Common_VirtualPropertySystem::register(__CLASS__, 'topic', 'string');
|
||||
}
|
||||
|
||||
public static function initMetadata($mapping)
|
||||
{
|
||||
$mapping->mapField(array(
|
||||
'fieldName' => 'id',
|
||||
'type' => 'integer',
|
||||
'length' => 4,
|
||||
'id' => true,
|
||||
'idGenerator' => 'auto'
|
||||
));
|
||||
|
@ -1,14 +1,15 @@
|
||||
<?php
|
||||
|
||||
#namespace Doctrine::Tests::ORM::Models::Forum;
|
||||
#namespace Doctrine\Tests\ORM\Models\Forum;
|
||||
|
||||
#use Doctrine::ORM::Entity;
|
||||
#use Doctrine\ORM\Entity;
|
||||
#use Doctrine\Common\VirtualPropertySystem;
|
||||
|
||||
class ForumUser extends Doctrine_ORM_Entity
|
||||
class ForumUser
|
||||
{
|
||||
#protected $id;
|
||||
#protected $username;
|
||||
#protected $avatar;
|
||||
public $id;
|
||||
public $username;
|
||||
public $avatar;
|
||||
|
||||
public static function initMetadata($mapping)
|
||||
{
|
||||
@ -26,7 +27,6 @@ class ForumUser extends Doctrine_ORM_Entity
|
||||
$mapping->mapField(array(
|
||||
'fieldName' => 'id',
|
||||
'type' => 'integer',
|
||||
'length' => 4,
|
||||
'id' => true,
|
||||
'idGenerator' => 'auto'
|
||||
));
|
||||
@ -42,7 +42,5 @@ class ForumUser extends Doctrine_ORM_Entity
|
||||
'joinColumns' => array('avatar_id' => 'id'),
|
||||
'cascade' => array('save')
|
||||
));
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user