Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
D
doctrine-dbal
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Tomáš Trávníček
doctrine-dbal
Commits
2eb4a16d
Commit
2eb4a16d
authored
Feb 06, 2009
by
romanb
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[2.0] More progress on the UnitOfWork and collections. First basic functional many-many test.
parent
deb095f2
Changes
14
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
267 additions
and
955 deletions
+267
-955
VirtualPropertyObject.php
lib/Doctrine/Common/VirtualPropertyObject.php
+0
-260
VirtualPropertySystem.php
lib/Doctrine/Common/VirtualPropertySystem.php
+0
-241
Connection.php
lib/Doctrine/DBAL/Connection.php
+2
-1
Frontbase.php
lib/Doctrine/ORM/Export/Frontbase.php
+0
-316
Reporter.php
lib/Doctrine/ORM/Export/Reporter.php
+0
-45
AnnotationDriver.php
lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php
+3
-1
ManyToManyMapping.php
lib/Doctrine/ORM/Mapping/ManyToManyMapping.php
+14
-0
PersistentCollection.php
lib/Doctrine/ORM/PersistentCollection.php
+3
-3
AbstractCollectionPersister.php
lib/Doctrine/ORM/Persisters/AbstractCollectionPersister.php
+27
-25
AbstractEntityPersister.php
lib/Doctrine/ORM/Persisters/AbstractEntityPersister.php
+2
-7
ManyToManyPersister.php
lib/Doctrine/ORM/Persisters/ManyToManyPersister.php
+81
-9
OneToManyPersister.php
lib/Doctrine/ORM/Persisters/OneToManyPersister.php
+4
-13
UnitOfWork.php
lib/Doctrine/ORM/UnitOfWork.php
+68
-29
BasicCRUDTest.php
tests/Doctrine/Tests/ORM/Functional/BasicCRUDTest.php
+63
-5
No files found.
lib/Doctrine/Common/VirtualPropertyObject.php
deleted
100644 → 0
View file @
deb095f2
<?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 */
}
?>
lib/Doctrine/Common/VirtualPropertySystem.php
deleted
100644 → 0
View file @
deb095f2
<?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
;
}
}
?>
lib/Doctrine/DBAL/Connection.php
View file @
2eb4a16d
...
...
@@ -542,8 +542,9 @@ class Connection
public
function
exec
(
$query
,
array
$params
=
array
())
{
$this
->
connect
();
try
{
echo
$query
.
PHP_EOL
;
if
(
!
empty
(
$params
))
{
//
var_dump($params);
var_dump
(
$params
);
$stmt
=
$this
->
prepare
(
$query
);
$stmt
->
execute
(
$params
);
return
$stmt
->
rowCount
();
...
...
lib/Doctrine/ORM/Export/Frontbase.php
deleted
100644 → 0
View file @
deb095f2
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.org>.
*/
/**
* Doctrine_Export_Frontbase
*
* @package Doctrine
* @subpackage Export
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.phpdoctrine.org
* @since 1.0
* @version $Revision$
*/
class
Doctrine_Export_Frontbase
extends
Doctrine_Export
{
/**
* create a new database
*
* @param string $name name of the database that should be created
* @return string
*/
public
function
createDatabaseSql
(
$name
)
{
$name
=
$this
->
conn
->
quoteIdentifier
(
$name
,
true
);
return
'CREATE DATABASE '
.
$name
;
}
/**
* drop an existing database
*
* @param string $name name of the database that should be dropped
* @return string
*/
public
function
dropDatabaseSql
(
$name
)
{
$name
=
$this
->
conn
->
quoteIdentifier
(
$name
,
true
);
return
'DELETE DATABASE '
.
$name
;
}
/**
* drop an existing table
*
* @param object $this->conns database object that is extended by this class
* @param string $name name of the table that should be dropped
* @return string
*/
public
function
dropTableSql
(
$name
)
{
$name
=
$this
->
conn
->
quoteIdentifier
(
$name
,
true
);
return
'DROP TABLE '
.
$name
.
' CASCADE'
;
}
/**
* alter an existing table
*
* @param string $name name of the table that is intended to be changed.
* @param array $changes associative array that contains the details of each type
* of change that is intended to be performed. The types of
* changes that are currently supported are defined as follows:
*
* name
*
* New name for the table.
*
* add
*
* Associative array with the names of fields to be added as
* indexes of the array. The value of each entry of the array
* should be set to another associative array with the properties
* of the fields to be added. The properties of the fields should
* be the same as defined by the MDB2 parser.
*
*
* remove
*
* Associative array with the names of fields to be removed as indexes
* of the array. Currently the values assigned to each entry are ignored.
* An empty array should be used for future compatibility.
*
* rename
*
* Associative array with the names of fields to be renamed as indexes
* of the array. The value of each entry of the array should be set to
* another associative array with the entry named name with the new
* field name and the entry named Declaration that is expected to contain
* the portion of the field declaration already in DBMS specific SQL code
* as it is used in the CREATE TABLE statement.
*
* change
*
* Associative array with the names of the fields to be changed as indexes
* of the array. Keep in mind that if it is intended to change either the
* name of a field and any other properties, the change array entries
* should have the new names of the fields as array indexes.
*
* The value of each entry of the array should be set to another associative
* array with the properties of the fields to that are meant to be changed as
* array entries. These entries should be assigned to the new values of the
* respective properties. The properties of the fields should be the same
* as defined by the MDB2 parser.
*
* Example
* array(
* 'name' => 'userlist',
* 'add' => array(
* 'quota' => array(
* 'type' => 'integer',
* 'unsigned' => 1
* )
* ),
* 'remove' => array(
* 'file_limit' => array(),
* 'time_limit' => array()
* ),
* 'change' => array(
* 'name' => array(
* 'length' => '20',
* 'definition' => array(
* 'type' => 'text',
* 'length' => 20,
* ),
* )
* ),
* 'rename' => array(
* 'sex' => array(
* 'name' => 'gender',
* 'definition' => array(
* 'type' => 'text',
* 'length' => 1,
* 'default' => 'M',
* ),
* )
* )
* )
*
* @param boolean $check indicates whether the function should just check if the DBMS driver
* can perform the requested table alterations if the value is true or
* actually perform them otherwise.
* @access public
*
* @return boolean
*/
public
function
alterTable
(
$name
,
array
$changes
,
$check
=
false
)
{
foreach
(
$changes
as
$changeName
=>
$change
)
{
switch
(
$changeName
)
{
case
'add'
:
case
'remove'
:
case
'change'
:
case
'rename'
:
case
'name'
:
break
;
default
:
throw
new
Doctrine_Export_Exception
(
'change type "'
.
$changeName
.
'" not yet supported'
);
}
}
if
(
$check
)
{
return
true
;
}
$query
=
''
;
if
(
!
empty
(
$changes
[
'name'
]))
{
$changeName
=
$this
->
conn
->
quoteIdentifier
(
$changes
[
'name'
],
true
);
$query
.=
'RENAME TO '
.
$changeName
;
}
if
(
!
empty
(
$changes
[
'add'
])
&&
is_array
(
$changes
[
'add'
]))
{
foreach
(
$changes
[
'add'
]
as
$fieldName
=>
$field
)
{
if
(
$query
)
{
$query
.=
', '
;
}
$query
.=
'ADD '
.
$this
->
conn
->
getDeclaration
(
$fieldName
,
$field
);
}
}
if
(
!
empty
(
$changes
[
'remove'
])
&&
is_array
(
$changes
[
'remove'
]))
{
foreach
(
$changes
[
'remove'
]
as
$fieldName
=>
$field
)
{
if
(
$query
)
{
$query
.=
', '
;
}
$fieldName
=
$this
->
conn
->
quoteIdentifier
(
$fieldName
,
true
);
$query
.=
'DROP '
.
$fieldName
;
}
}
$rename
=
array
();
if
(
!
empty
(
$changes
[
'rename'
])
&&
is_array
(
$changes
[
'rename'
]))
{
foreach
(
$changes
[
'rename'
]
as
$fieldName
=>
$field
)
{
$rename
[
$field
[
'name'
]]
=
$fieldName
;
}
}
if
(
!
empty
(
$changes
[
'change'
])
&&
is_array
(
$changes
[
'change'
]))
{
foreach
(
$changes
[
'change'
]
as
$fieldName
=>
$field
)
{
if
(
$query
)
{
$query
.=
', '
;
}
if
(
isset
(
$rename
[
$fieldName
]))
{
$oldFieldName
=
$rename
[
$fieldName
];
unset
(
$rename
[
$fieldName
]);
}
else
{
$oldFieldName
=
$fieldName
;
}
$oldFieldName
=
$this
->
conn
->
quoteIdentifier
(
$oldFieldName
,
true
);
$query
.=
'CHANGE '
.
$oldFieldName
.
' '
.
$this
->
conn
->
getDeclaration
(
$oldFieldName
,
$field
[
'definition'
]);
}
}
if
(
!
empty
(
$rename
)
&&
is_array
(
$rename
))
{
foreach
(
$rename
as
$renamedFieldName
=>
$renamed_field
)
{
if
(
$query
)
{
$query
.=
', '
;
}
$oldFieldName
=
$rename
[
$renamedFieldName
];
$field
=
$changes
[
'rename'
][
$oldFieldName
];
$query
.=
'CHANGE '
.
$this
->
conn
->
getDeclaration
(
$oldFieldName
,
$field
[
'definition'
]);
}
}
if
(
!
$query
)
{
return
true
;
}
$name
=
$this
->
conn
->
quoteIdentifier
(
$name
,
true
);
return
$this
->
conn
->
exec
(
'ALTER TABLE '
.
$name
.
' '
.
$query
);
}
/**
* create sequence
*
* @param string $seqName name of the sequence to be created
* @param string $start start value of the sequence; default is 1
* @param array $options An associative array of table options:
* array(
* 'comment' => 'Foo',
* 'charset' => 'utf8',
* 'collate' => 'utf8_unicode_ci',
* );
* @return void
*/
public
function
createSequence
(
$sequenceName
,
$start
=
1
,
array
$options
=
array
())
{
$sequenceName
=
$this
->
conn
->
quoteIdentifier
(
$this
->
conn
->
getSequenceName
(
$sequenceName
),
true
);
$seqcolName
=
$this
->
conn
->
quoteIdentifier
(
$this
->
conn
->
getAttribute
(
Doctrine
::
ATTR_SEQCOL_NAME
),
true
);
$query
=
'CREATE TABLE '
.
$sequenceName
.
' ('
.
$seqcolName
.
' INTEGER DEFAULT UNIQUE, PRIMARY KEY('
.
$seqcolName
.
'))'
;
$res
=
$this
->
conn
->
exec
(
$query
);
$res
=
$this
->
conn
->
exec
(
'SET UNIQUE = 1 FOR '
.
$sequenceName
);
if
(
$start
==
1
)
{
return
true
;
}
try
{
$this
->
conn
->
exec
(
'INSERT INTO '
.
$sequenceName
.
' ('
.
$seqcolName
.
') VALUES ('
.
(
$start
-
1
)
.
')'
);
}
catch
(
Doctrine_Connection_Exception
$e
)
{
// Handle error
try
{
$this
->
conn
->
exec
(
'DROP TABLE '
.
$sequenceName
);
}
catch
(
Doctrine_Connection_Exception
$e
)
{
throw
new
Doctrine_Export_Exception
(
'could not drop inconsistent sequence table'
);
}
throw
new
Doctrine_Export_Exception
(
'could not create sequence table'
);
}
}
/**
* drop existing sequence
*
* @param string $seqName name of the sequence to be dropped
* @return string
*/
public
function
dropSequenceSql
(
$seqName
)
{
$sequenceName
=
$this
->
conn
->
quoteIdentifier
(
$this
->
conn
->
getSequenceName
(
$seqName
),
true
);
return
'DROP TABLE '
.
$sequenceName
.
' CASCADE'
;
}
/**
* drop existing index
*
* @param string $table name of table that should be used in method
* @param string $name name of the index to be dropped
* @return boolean
*/
public
function
dropIndexSql
(
$table
,
$name
)
{
$table
=
$this
->
conn
->
quoteIdentifier
(
$table
,
true
);
$name
=
$this
->
conn
->
quoteIdentifier
(
$this
->
conn
->
getIndexName
(
$name
),
true
);
return
'ALTER TABLE '
.
$table
.
' DROP INDEX '
.
$name
;
}
}
\ No newline at end of file
lib/Doctrine/ORM/Export/Reporter.php
deleted
100644 → 0
View file @
deb095f2
<?php
/*
* $Id: Reporter.php 3882 2008-02-22 18:11:35Z jwage $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.org>.
*/
/**
* Doctrine_Export_Reporter
*
* @package Doctrine
* @subpackage Export
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.phpdoctrine.org
* @since 1.0
* @version $Revision: 3882 $
*/
class
Doctrine_Export_Reporter
implements
IteratorAggregate
{
protected
$messages
=
array
();
public
function
add
(
$code
,
$message
)
{
$this
->
messages
[]
=
array
(
$code
,
$message
);
}
public
function
pop
()
{
return
array_pop
(
$this
->
messages
);
}
public
function
getIterator
()
{
return
new
ArrayIterator
(
$this
->
messages
);
}
}
\ No newline at end of file
lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php
View file @
2eb4a16d
...
...
@@ -31,9 +31,11 @@ if ( ! class_exists('\Addendum', false)) {
require
__DIR__
.
'/DoctrineAnnotations.php'
;
/**
* The AnnotationDriver reads the mapping metadata from docblock annotations.
* The AnnotationDriver reads the mapping metadata from docblock annotations
* with the help of the Addendum reflection extensions.
*
* @author robo
* @since 2.0
*/
class
AnnotationDriver
{
...
...
lib/Doctrine/ORM/Mapping/ManyToManyMapping.php
View file @
2eb4a16d
...
...
@@ -51,6 +51,11 @@ class ManyToManyMapping extends AssociationMapping
* Maps the columns in the target table to the columns in the relation table.
*/
private
$_targetToRelationKeyColumns
=
array
();
/**
* The columns on the join table.
*/
private
$_joinTableColumns
=
array
();
/**
* Initializes a new ManyToManyMapping.
...
...
@@ -76,25 +81,34 @@ class ManyToManyMapping extends AssociationMapping
if
(
!
isset
(
$mapping
[
'joinTable'
]))
{
throw
MappingException
::
joinTableRequired
(
$mapping
[
'fieldName'
]);
}
// owning side MUST specify joinColumns
if
(
!
isset
(
$mapping
[
'joinTable'
][
'joinColumns'
]))
{
throw
MappingException
::
invalidMapping
(
$this
->
_sourceFieldName
);
}
foreach
(
$mapping
[
'joinTable'
][
'joinColumns'
]
as
$joinColumn
)
{
$this
->
_sourceToRelationKeyColumns
[
$joinColumn
[
'referencedColumnName'
]]
=
$joinColumn
[
'name'
];
$this
->
_joinTableColumns
[]
=
$joinColumn
[
'name'
];
}
$this
->
_sourceKeyColumns
=
array_keys
(
$this
->
_sourceToRelationKeyColumns
);
// owning side MUST specify inverseJoinColumns
if
(
!
isset
(
$mapping
[
'joinTable'
][
'inverseJoinColumns'
]))
{
throw
MappingException
::
invalidMapping
(
$this
->
_sourceFieldName
);
}
foreach
(
$mapping
[
'joinTable'
][
'inverseJoinColumns'
]
as
$inverseJoinColumn
)
{
$this
->
_targetToRelationKeyColumns
[
$inverseJoinColumn
[
'referencedColumnName'
]]
=
$inverseJoinColumn
[
'name'
];
$this
->
_joinTableColumns
[]
=
$inverseJoinColumn
[
'name'
];
}
$this
->
_targetKeyColumns
=
array_keys
(
$this
->
_targetToRelationKeyColumns
);
}
}
public
function
getJoinTableColumns
()
{
return
$this
->
_joinTableColumns
;
}
public
function
getSourceToRelationKeyColumns
()
{
return
$this
->
_sourceToRelationKeyColumns
;
...
...
lib/Doctrine/ORM/PersistentCollection.php
View file @
2eb4a16d
...
...
@@ -27,11 +27,11 @@ use Doctrine\ORM\Mapping\AssociationMapping;
* A PersistentCollection represents a collection of elements that have persistent state.
* Collections of entities represent only the associations (links) to those entities.
* That means, if the collection is part of a many-many mapping and you remove
* entities from the collection, only the links in the
xref
table are removed (on flush).
* entities from the collection, only the links in the
relation
table are removed (on flush).
* Similarly, if you remove entities from a collection that is part of a one-many
* mapping this will only result in the nulling out of the foreign keys on flush
* (or removal of the links in the
xref table if the one-many is mapped through an
*
xref
table). If you want entities in a one-many collection to be removed when
* (or removal of the links in the
relation table if the one-many is mapped through a
*
relation
table). If you want entities in a one-many collection to be removed when
* they're removed from the collection, use deleteOrphans => true on the one-many
* mapping.
*
...
...
lib/Doctrine/ORM/Persisters/AbstractCollectionPersister.php
View file @
2eb4a16d
...
...
@@ -55,54 +55,54 @@ abstract class AbstractCollectionPersister
}
//...
}
/**
* Deletes the persistent state represented by the given collection.
*
* @param PersistentCollection $coll
*/
public
function
delete
(
PersistentCollection
$coll
)
{
if
(
$coll
->
get
Relation
()
->
isInverseSide
())
{
return
;
if
(
$coll
->
get
Mapping
()
->
isInverseSide
())
{
return
;
// ignore inverse side
}
//...
$sql
=
$this
->
_getDeleteSql
(
$coll
);
$this
->
_conn
->
exec
(
$sql
,
$this
->
_getDeleteSqlParameters
(
$coll
));
}
abstract
protected
function
_getDeleteSql
(
PersistentCollection
$coll
);
abstract
protected
function
_getDeleteSqlParameters
(
PersistentCollection
$coll
);
public
function
update
(
PersistentCollection
$coll
)
{
if
(
$coll
->
getMapping
()
->
isInverseSide
())
{
return
;
// ignore inverse side
}
$this
->
deleteRows
(
$coll
);
$this
->
updateRows
(
$coll
);
//
$this->updateRows($coll);
$this
->
insertRows
(
$coll
);
}
/* collection update actions */
public
function
deleteRows
(
PersistentCollection
$coll
)
{
if
(
$coll
->
getMapping
()
->
isInverseSide
())
{
return
;
// ignore inverse side
}
{
$deleteDiff
=
$coll
->
getDeleteDiff
();
$sql
=
$this
->
_getDeleteRowSql
(
$coll
);
$uow
=
$this
->
_em
->
getUnitOfWork
();
foreach
(
$deleteDiff
as
$element
)
{
$this
->
_conn
->
exec
(
$sql
,
$this
->
_getDeleteRowSqlParameters
(
$element
));
$this
->
_conn
->
exec
(
$sql
,
$this
->
_getDeleteRowSqlParameters
(
$
coll
,
$
element
));
}
}
public
function
updateRows
(
PersistentCollection
$coll
)
{
}
{}
public
function
insertRows
(
PersistentCollection
$coll
)
{
if
(
$coll
->
getMapping
()
->
isInverseSide
())
{
return
;
// ignore inverse side
}
$insertDiff
=
$coll
->
getInsertDiff
();
$sql
=
$this
->
_getInsertRowSql
(
$coll
);
$uow
=
$this
->
_em
->
getUnitOfWork
();
foreach
(
$insertDiff
as
$element
)
{
$this
->
_conn
->
exec
(
$sql
/*, $uow->getEntityIdentifier($element)*/
);
$this
->
_conn
->
exec
(
$sql
,
$this
->
_getInsertRowSqlParameters
(
$coll
,
$element
)
);
}
}
...
...
@@ -120,13 +120,15 @@ abstract class AbstractCollectionPersister
*
* @param PersistentCollection $coll
*/
abstract
protected
function
_getUpdateRowSql
();
abstract
protected
function
_getUpdateRowSql
(
PersistentCollection
$coll
);
/**
* Gets the SQL statement used for inserting a row from to the collection.
*
* @param PersistentCollection $coll
*/
abstract
protected
function
_getInsertRowSql
();
abstract
protected
function
_getInsertRowSql
(
PersistentCollection
$coll
);
abstract
protected
function
_getInsertRowSqlParameters
(
PersistentCollection
$coll
,
$element
);
}
lib/Doctrine/ORM/Persisters/AbstractEntityPersister.php
View file @
2eb4a16d
...
...
@@ -171,13 +171,8 @@ abstract class AbstractEntityPersister
protected
function
_prepareData
(
$entity
,
array
&
$result
,
$isInsert
=
false
)
{
foreach
(
$this
->
_em
->
getUnitOfWork
()
->
getEntityChangeSet
(
$entity
)
as
$field
=>
$change
)
{
if
(
is_array
(
$change
))
{
$oldVal
=
$change
[
0
];
$newVal
=
$change
[
1
];
}
else
{
$oldVal
=
null
;
$newVal
=
$change
;
}
$oldVal
=
$change
[
0
];
$newVal
=
$change
[
1
];
$type
=
$this
->
_classMetadata
->
getTypeOfField
(
$field
);
$columnName
=
$this
->
_classMetadata
->
getColumnName
(
$field
);
...
...
lib/Doctrine/ORM/Persisters/ManyToManyPersister.php
View file @
2eb4a16d
...
...
@@ -21,40 +21,112 @@
namespace
Doctrine\ORM\Persisters
;
use
Doctrine\ORM\PersistentCollection
;
/**
* Persister for many-to-many collections.
*
* @author robo
* @since 2.0
*/
class
ManyToManyPersister
extends
AbstractCollectionPersister
{
/**
* {@inheritdoc}
*
* @param <type> $coll
* @override
* @todo Identifier quoting.
* @see _getDeleteRowSqlParameters()
*/
protected
function
_getDeleteRowSql
(
PersistentCollection
$coll
)
{
$mapping
=
$coll
->
getMapping
();
$joinTable
=
$mapping
->
getJoinTable
();
$columns
=
array_merge
(
$mapping
->
getSourceKeyColumns
(),
$mapping
->
getTargetKeyColumns
()
);
return
"DELETE FROM
$joinTable
WHERE "
.
implode
(
' = ?,
'
,
$columns
)
.
' = ?'
;
$columns
=
$mapping
->
getJoinTableColumns
(
);
return
"DELETE FROM
{
$joinTable
[
'name'
]
}
WHERE "
.
implode
(
' = ? AND
'
,
$columns
)
.
' = ?'
;
}
/**
* {@inheritdoc}
*
* @param <type> $element
* @override
* @see _getDeleteRowSql()
*/
protected
function
_getDeleteRowSqlParameters
(
PersistentCollection
$coll
,
$element
)
{
$owner
=
$coll
->
getOwner
();
$params
=
array_merge
(
$this
->
_uow
->
getEntityIdentifier
(
$coll
->
getOwner
()),
$this
->
_uow
->
getEntityIdentifier
(
$element
)
);
//var_dump($params);
return
$params
;
}
/**
* {@inheritdoc}
*
* @override
*/
protected
function
_getUpdateRowSql
(
PersistentCollection
$coll
)
{
}
/**
* {@inheritdoc}
*
* @override
*/
protected
function
_getInsertRowSql
(
PersistentCollection
$coll
)
{
$mapping
=
$coll
->
getMapping
();
$joinTable
=
$mapping
->
getJoinTable
();
$columns
=
$mapping
->
getJoinTableColumns
();
return
"INSERT INTO
{
$joinTable
[
'name'
]
}
("
.
implode
(
', '
,
$columns
)
.
")"
.
" VALUES ("
.
implode
(
', '
,
array_fill
(
0
,
count
(
$columns
),
'?'
))
.
')'
;
}
/**
* {@inheritdoc}
*
* @override
*/
protected
function
_getInsertRowSqlParameters
(
PersistentCollection
$coll
,
$element
)
{
//FIXME: This is still problematic for composite keys because we silently
// rely on a specific ordering of the columns.
$params
=
array_merge
(
$this
->
_uow
->
getEntityIdentifier
(
$coll
->
getOwner
()),
$this
->
_uow
->
getEntityIdentifier
(
$element
)
);
var_dump
(
$params
);
return
$params
;
}
/**
* {@inheritdoc}
*
* @override
*/
protected
function
_getDeleteSql
(
PersistentCollection
$coll
)
{
$mapping
=
$coll
->
getMapping
();
$joinTable
=
$mapping
->
getJoinTable
();
$whereClause
=
''
;
foreach
(
$mapping
->
getSourceToRelationKeyColumns
()
as
$relationColumn
)
{
if
(
$whereClause
!==
''
)
$whereClause
.=
' AND '
;
$whereClause
.=
"
$relationColumn
= ?"
;
}
return
"DELETE FROM
{
$joinTable
[
'name'
]
}
WHERE
$whereClause
"
;
}
/**
* {@inheritdoc}
*
* @override
*/
protected
function
_getDeleteSqlParameters
(
PersistentCollection
$coll
)
{
//FIXME: This is still problematic for composite keys because we silently
// rely on a specific ordering of the columns.
return
$this
->
_uow
->
getEntityIdentifier
(
$coll
->
getOwner
());
}
}
lib/Doctrine/ORM/Persisters/OneToManyPersister.php
View file @
2eb4a16d
...
...
@@ -25,8 +25,11 @@ use Doctrine\ORM\PersistentCollection;
/**
* Persister for one-to-many collections.
*
* This persister is only used for uni-directional one-to-many mappings.
*
* @since 2.0
* @author Roman Borschel <roman@code-factory.org>
*/
class
OneToManyPersister
extends
AbstractCollectionPersister
{
...
...
@@ -57,19 +60,7 @@ class OneToManyPersister extends AbstractCollectionPersister
$whereClause
.=
"
$idColumn
= ?"
;
}
return
"UPDATE
$table
SET
$setClause
WHERE
$whereClause
"
;
}
/**
* {@inheritdoc}
*
* @param <type> $element
* @return <type>
* @override
*/
protected
function
_getDeleteRowSqlParameters
(
PersistentCollection
$coll
,
$element
)
{
return
$this
->
_uow
->
getEntityIdentifier
(
$element
);
return
array
(
"UPDATE
$table
SET
$setClause
WHERE
$whereClause
"
,
$this
->
_uow
->
getEntityIdentifier
(
$element
));
}
protected
function
_getInsertRowSql
()
...
...
lib/Doctrine/ORM/UnitOfWork.php
View file @
2eb4a16d
...
...
@@ -24,6 +24,8 @@ namespace Doctrine\ORM;
use
Doctrine\ORM\Internal\CommitOrderCalculator
;
use
Doctrine\ORM\Internal\CommitOrderNode
;
use
Doctrine\ORM\PersistentCollection
;
use
Doctrine\ORM\Mapping
;
use
Doctrine\ORM\Persisters
;
use
Doctrine\ORM\EntityManager
;
use
Doctrine\ORM\Exceptions\UnitOfWorkException
;
...
...
@@ -227,7 +229,8 @@ class UnitOfWork
if
(
empty
(
$this
->
_newEntities
)
&&
empty
(
$this
->
_deletedEntities
)
&&
empty
(
$this
->
_dirtyEntities
)
&&
empty
(
$this
->
_collectionUpdates
))
{
empty
(
$this
->
_collectionUpdates
)
&&
empty
(
$this
->
_collectionDeletions
))
{
return
;
// Nothing to do.
}
...
...
@@ -243,8 +246,12 @@ class UnitOfWork
$this
->
_executeUpdates
(
$class
);
}
//TODO: collection deletions (deletions of complete collections)
//TODO: collection updates (deleteRows, updateRows, insertRows)
// Collection deletions (deletions of complete collections)
foreach
(
$this
->
_collectionDeletions
as
$collectionToDelete
)
{
$this
->
getCollectionPersister
(
$collectionToDelete
->
getMapping
())
->
delete
(
$collectionToDelete
);
}
// Collection updates (deleteRows, updateRows, insertRows)
foreach
(
$this
->
_collectionUpdates
as
$collectionToUpdate
)
{
$this
->
getCollectionPersister
(
$collectionToUpdate
->
getMapping
())
->
update
(
$collectionToUpdate
);
...
...
@@ -269,6 +276,7 @@ class UnitOfWork
$this
->
_deletedEntities
=
array
();
$this
->
_entityChangeSets
=
array
();
$this
->
_collectionUpdates
=
array
();
$this
->
_collectionDeletions
=
array
();
$this
->
_visitedCollections
=
array
();
}
...
...
@@ -328,24 +336,31 @@ class UnitOfWork
$actualData
[
$name
]
=
$refProp
->
getValue
(
$entity
);
}
if
(
$class
->
isCollectionValuedAssociation
(
$name
)
&&
!
(
$actualData
[
$name
]
instanceof
PersistentCollection
))
{
// Inject PersistentCollection
if
(
$class
->
isCollectionValuedAssociation
(
$name
)
&&
!
is_null
(
$actualData
[
$name
])
&&
!
(
$actualData
[
$name
]
instanceof
PersistentCollection
))
{
//TODO: If $actualData[$name] is Collection then unwrap the array
$assoc
=
$class
->
getAssociationMapping
(
$name
);
$coll
=
new
PersistentCollection
(
$this
->
_em
,
$assoc
->
getTargetEntityName
(),
if
(
$assoc
->
isOwningSide
())
{
// Inject PersistentCollection
$coll
=
new
PersistentCollection
(
$this
->
_em
,
$assoc
->
getTargetEntityName
(),
$actualData
[
$name
]
?
$actualData
[
$name
]
:
array
());
$coll
->
_setOwner
(
$entity
,
$assoc
);
if
(
!
$coll
->
isEmpty
())
$coll
->
setDirty
(
true
);
$class
->
getReflectionProperty
(
$name
)
->
setValue
(
$entity
,
$coll
);
$actualData
[
$name
]
=
$coll
;
$coll
->
_setOwner
(
$entity
,
$assoc
);
if
(
!
$coll
->
isEmpty
())
$coll
->
setDirty
(
true
);
$class
->
getReflectionProperty
(
$name
)
->
setValue
(
$entity
,
$coll
);
$actualData
[
$name
]
=
$coll
;
}
}
}
if
(
!
isset
(
$this
->
_originalEntityData
[
$oid
]))
{
// Entity is either NEW or MANAGED but not yet fully persisted
// (only has an id). These result in an INSERT.
$this
->
_entityChangeSets
[
$oid
]
=
$actualData
;
$this
->
_originalEntityData
[
$oid
]
=
$actualData
;
$this
->
_entityChangeSets
[
$oid
]
=
array_map
(
function
(
$e
)
{
return
array
(
null
,
$e
);
},
$actualData
);
}
else
{
// Entity is "fully" MANAGED: it was already fully persisted before
// and we have a copy of the original data
...
...
@@ -366,11 +381,16 @@ class UnitOfWork
$assoc
=
$class
->
getAssociationMapping
(
$propName
);
if
(
$assoc
->
isOneToOne
()
&&
$assoc
->
isOwningSide
())
{
$entityIsDirty
=
true
;
}
else
if
(
/*is_null($actualValue) && */
$orgValue
instanceof
PersistentCollection
)
{
// A PersistentCollection was de-referenced, so delete it.
if
(
!
in_array
(
$orgValue
,
$this
->
_collectionDeletions
,
true
))
{
$this
->
_collectionDeletions
[]
=
$orgValue
;
}
}
}
else
{
$entityIsDirty
=
true
;
}
}
}
}
if
(
$changeSet
)
{
if
(
$entityIsDirty
)
{
...
...
@@ -403,6 +423,10 @@ class UnitOfWork
*/
private
function
_computeAssociationChanges
(
$assoc
,
$value
)
{
/*if ( ! $assoc->isCascadeSave()) {
return; // "Persistence by reachability" only if save cascade enabled
}*/
if
(
$assoc
->
isOneToOne
())
{
$value
=
array
(
$value
);
}
...
...
@@ -428,13 +452,27 @@ class UnitOfWork
// NEW entities are INSERTed within the current unit of work.
$data
=
array
();
$changeSet
=
array
();
foreach
(
$targetClass
->
getReflectionProperties
()
as
$name
=>
$refProp
)
{
$data
[
$name
]
=
$refProp
->
getValue
(
$entry
);
$changeSet
[
$name
]
=
array
(
null
,
$data
[
$name
]);
// --
/*if ($targetClass->isCollectionValuedAssociation($name) && ! ($data[$name] instanceof PersistentCollection)) {
// Inject PersistentCollection
//TODO: If $actualData[$name] is Collection then unwrap the array
$assoc = $targetClass->getAssociationMapping($name);
$coll = new PersistentCollection($this->_em, $assoc->getTargetEntityName(),
$data[$name] ? $data[$name] : array());
$coll->_setOwner($entry, $assoc);
if ( ! $coll->isEmpty()) $coll->setDirty(true);
$targetClass->getReflectionProperty($name)->setValue($entry, $coll);
$data[$name] = $coll;
}*/
//--
}
$oid
=
spl_object_hash
(
$entry
);
$this
->
_newEntities
[
$oid
]
=
$entry
;
$this
->
_entityChangeSets
[
$oid
]
=
$
data
;
$this
->
_entityChangeSets
[
$oid
]
=
$
changeSet
;
$this
->
_originalEntityData
[
$oid
]
=
$data
;
}
else
if
(
$state
==
self
::
STATE_DELETED
)
{
throw
new
DoctrineException
(
"Deleted entity in collection detected during flush."
);
...
...
@@ -481,11 +519,6 @@ class UnitOfWork
}
}
private
function
_executeCollectionUpdate
(
$collectionToUpdate
)
{
//...
}
/**
* Executes all entity updates for entities of the specified type.
*
...
...
@@ -784,7 +817,7 @@ class UnitOfWork
{
$oid
=
spl_object_hash
(
$entity
);
if
(
!
isset
(
$this
->
_entityStates
[
$oid
]))
{
if
(
isset
(
$this
->
_entityIdentifiers
[
$oid
]))
{
if
(
isset
(
$this
->
_entityIdentifiers
[
$oid
])
&&
!
isset
(
$this
->
_newEntities
[
$oid
])
)
{
$this
->
_entityStates
[
$oid
]
=
self
::
STATE_DETACHED
;
}
else
{
$this
->
_entityStates
[
$oid
]
=
self
::
STATE_NEW
;
...
...
@@ -824,7 +857,7 @@ class UnitOfWork
*
* @param string $idHash
* @param string $rootClassName
* @return
Doctrine\ORM\Entity
* @return
object
*/
public
function
getByIdHash
(
$idHash
,
$rootClassName
)
{
...
...
@@ -1071,8 +1104,8 @@ class UnitOfWork
}
$relatedEntities
=
$class
->
getReflectionProperty
(
$assocMapping
->
getSourceFieldName
())
->
getValue
(
$entity
);
if
(
$relatedEntities
instanceof
\Doctrine\Common\Collections\Collection
&&
count
(
$relatedEntities
)
>
0
)
{
if
(
$relatedEntities
instanceof
\Doctrine\Common\Collections\Collection
||
is_array
(
$relatedEntities
)
&&
count
(
$relatedEntities
)
>
0
)
{
foreach
(
$relatedEntities
as
$relatedEntity
)
{
$this
->
_doDelete
(
$relatedEntity
,
$visited
);
}
...
...
@@ -1323,23 +1356,29 @@ class UnitOfWork
if
(
!
isset
(
$this
->
_persisters
[
$entityName
]))
{
$class
=
$this
->
_em
->
getClassMetadata
(
$entityName
);
if
(
$class
->
isInheritanceTypeJoined
())
{
$persister
=
new
\Doctrine\ORM\
Persisters\JoinedSubclassPersister
(
$this
->
_em
,
$class
);
$persister
=
new
Persisters\JoinedSubclassPersister
(
$this
->
_em
,
$class
);
}
else
{
$persister
=
new
\Doctrine\ORM\
Persisters\StandardEntityPersister
(
$this
->
_em
,
$class
);
$persister
=
new
Persisters\StandardEntityPersister
(
$this
->
_em
,
$class
);
}
$this
->
_persisters
[
$entityName
]
=
$persister
;
}
return
$this
->
_persisters
[
$entityName
];
}
/**
* Gets a collection persister for a collection-valued association.
*
* @param AssociationMapping $association
* @return AbstractCollectionPersister
*/
public
function
getCollectionPersister
(
$association
)
{
$type
=
get_class
(
$association
);
if
(
!
isset
(
$this
->
_collectionPersisters
[
$type
]))
{
if
(
$association
instanceof
\Doctrine\ORM\
Mapping\OneToManyMapping
)
{
$persister
=
new
\Doctrine\ORM\
Persisters\OneToManyPersister
(
$this
->
_em
);
}
else
if
(
$association
instanceof
\Doctrine\ORM\
Mapping\ManyToManyMapping
)
{
$persister
=
new
\Doctrine\ORM\
Persisters\ManyToManyPersister
(
$this
->
_em
);
if
(
$association
instanceof
Mapping\OneToManyMapping
)
{
$persister
=
new
Persisters\OneToManyPersister
(
$this
->
_em
);
}
else
if
(
$association
instanceof
Mapping\ManyToManyMapping
)
{
$persister
=
new
Persisters\ManyToManyPersister
(
$this
->
_em
);
}
$this
->
_collectionPersisters
[
$type
]
=
$persister
;
}
...
...
tests/Doctrine/Tests/ORM/Functional/BasicCRUDTest.php
View file @
2eb4a16d
...
...
@@ -6,8 +6,7 @@ use Doctrine\ORM\Export\ClassExporter;
use
Doctrine\Tests\Models\CMS\CmsUser
;
use
Doctrine\Tests\Models\CMS\CmsPhonenumber
;
use
Doctrine\Tests\Models\CMS\CmsAddress
;
use
Doctrine\Tests\Models\Forum\ForumUser
;
use
Doctrine\Tests\Models\Forum\ForumAvatar
;
use
Doctrine\Tests\Models\CMS\CmsGroup
;
require_once
__DIR__
.
'/../../TestInit.php'
;
...
...
@@ -25,7 +24,8 @@ class BasicCRUDTest extends \Doctrine\Tests\OrmFunctionalTestCase {
$exporter
->
exportClasses
(
array
(
$this
->
_em
->
getClassMetadata
(
'Doctrine\Tests\Models\CMS\CmsUser'
),
$this
->
_em
->
getClassMetadata
(
'Doctrine\Tests\Models\CMS\CmsPhonenumber'
),
$this
->
_em
->
getClassMetadata
(
'Doctrine\Tests\Models\CMS\CmsAddress'
)
$this
->
_em
->
getClassMetadata
(
'Doctrine\Tests\Models\CMS\CmsAddress'
),
$this
->
_em
->
getClassMetadata
(
'Doctrine\Tests\Models\CMS\CmsGroup'
)
));
// Create
...
...
@@ -48,7 +48,7 @@ class BasicCRUDTest extends \Doctrine\Tests\OrmFunctionalTestCase {
$em
->
flush
();
$this
->
assertTrue
(
$em
->
contains
(
$ph
));
$this
->
assertTrue
(
$em
->
contains
(
$user
));
$this
->
assertTrue
(
$user
->
phonenumbers
instanceof
\Doctrine\ORM\PersistentCollection
);
//
$this->assertTrue($user->phonenumbers instanceof \Doctrine\ORM\PersistentCollection);
// Update name
$user
->
name
=
'guilherme'
;
...
...
@@ -90,7 +90,7 @@ class BasicCRUDTest extends \Doctrine\Tests\OrmFunctionalTestCase {
$this
->
_em
->
save
(
$user
);
$this
->
_em
->
flush
();
$this
->
assertTrue
(
$user
->
phonenumbers
instanceof
\Doctrine\ORM\PersistentCollection
);
//
$this->assertTrue($user->phonenumbers instanceof \Doctrine\ORM\PersistentCollection);
// Remove the first element from the collection
unset
(
$user
->
phonenumbers
[
0
]);
...
...
@@ -125,5 +125,63 @@ class BasicCRUDTest extends \Doctrine\Tests\OrmFunctionalTestCase {
array
(
$address
->
id
))
->
fetchColumn
();
$this
->
assertTrue
(
is_numeric
(
$userId
));
}
public
function
testBasicManyToMany
()
{
$user
=
new
CmsUser
;
$user
->
name
=
'Guilherme'
;
$user
->
username
=
'gblanco'
;
$user
->
status
=
'developer'
;
$group
=
new
CmsGroup
;
$group
->
name
=
'Developers'
;
$user
->
groups
[]
=
$group
;
$group
->
users
[]
=
$user
;
$this
->
_em
->
save
(
$user
);
$this
->
_em
->
save
(
$group
);
$this
->
_em
->
flush
();
unset
(
$group
->
users
[
0
]);
// inverse side
unset
(
$user
->
groups
[
0
]);
// owning side!
$this
->
_em
->
flush
();
// Check that the link in the association table has been deleted
$count
=
$this
->
_em
->
getConnection
()
->
execute
(
"SELECT COUNT(*) FROM cms_users_groups"
,
array
())
->
fetchColumn
();
$this
->
assertEquals
(
0
,
$count
);
}
public
function
testManyToManyCollectionClearing
()
{
$user
=
new
CmsUser
;
$user
->
name
=
'Guilherme'
;
$user
->
username
=
'gblanco'
;
$user
->
status
=
'developer'
;
for
(
$i
=
0
;
$i
<
10
;
++
$i
)
{
$group
=
new
CmsGroup
;
$group
->
name
=
'Developers_'
.
$i
;
$user
->
groups
[]
=
$group
;
$group
->
users
[]
=
$user
;
}
$this
->
_em
->
save
(
$user
);
// Saves the user, cause of post-insert ID
$this
->
_em
->
flush
();
// Saves the groups, cause they're attached to a persistent entity ($user)
//$user->groups->clear();
unset
(
$user
->
groups
);
$this
->
_em
->
flush
();
// Check that the links in the association table have been deleted
$count
=
$this
->
_em
->
getConnection
()
->
execute
(
"SELECT COUNT(*) FROM cms_users_groups"
,
array
())
->
fetchColumn
();
$this
->
assertEquals
(
0
,
$count
);
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment