Merge branch 'master' into DDC-551
Conflicts: lib/Doctrine/ORM/Configuration.php lib/Doctrine/ORM/Persisters/BasicEntityPersister.php lib/Doctrine/ORM/Persisters/ManyToManyPersister.php
This commit is contained in:
commit
097d573d26
@ -1,3 +1,19 @@
|
|||||||
# Removed support for onUpdate in @JoinColumn
|
# Removed support for onUpdate in @JoinColumn
|
||||||
|
|
||||||
The onUpdate foreign key handling makes absolutly no sense in an ORM. Additionally Oracle doesn't even support it. Support for it is removed.
|
The onUpdate foreign key handling makes absolutly no sense in an ORM. Additionally Oracle doesn't even support it. Support for it is removed.
|
||||||
|
|
||||||
|
# Changes in Annotation Handling
|
||||||
|
|
||||||
|
There have been some changes to the annotation handling in Common 2.2 again, that affect how people with old configurations
|
||||||
|
from 2.0 have to configure the annotation driver if they don't use `Configuration::newDefaultAnnotationDriver()`:
|
||||||
|
|
||||||
|
// Register the ORM Annotations in the AnnotationRegistry
|
||||||
|
AnnotationRegistry::registerFile('path/to/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php');
|
||||||
|
|
||||||
|
$reader = new \Doctrine\Common\Annotations\SimpleAnnotationReader();
|
||||||
|
$reader->addNamespace('Doctrine\ORM\Mapping');
|
||||||
|
$reader = new \Doctrine\Common\Annotations\CachedReader($reader, new ArrayCache());
|
||||||
|
|
||||||
|
$driver = new AnnotationDriver($reader, (array)$paths);
|
||||||
|
|
||||||
|
$config->setMetadataDriverImpl($driver);
|
@ -8,6 +8,7 @@ report.dir=reports
|
|||||||
log.archive.dir=logs
|
log.archive.dir=logs
|
||||||
project.pirum_dir=
|
project.pirum_dir=
|
||||||
project.download_dir=
|
project.download_dir=
|
||||||
|
project.xsd_dir=
|
||||||
test.phpunit_configuration_file=
|
test.phpunit_configuration_file=
|
||||||
test.phpunit_generate_coverage=0
|
test.phpunit_generate_coverage=0
|
||||||
test.pmd_reports=0
|
test.pmd_reports=0
|
||||||
|
@ -223,7 +223,12 @@
|
|||||||
|
|
||||||
<target name="distribute-download">
|
<target name="distribute-download">
|
||||||
<copy file="dist/DoctrineORM-${version}-full.tar.gz" todir="${project.download_dir}" />
|
<copy file="dist/DoctrineORM-${version}-full.tar.gz" todir="${project.download_dir}" />
|
||||||
<copy file="${dist.dir}/doctrine-orm-${version}.phar" todir="${project.download_dir}" />
|
<!--<copy file="${dist.dir}/doctrine-orm-${version}.phar" todir="${project.download_dir}" />-->
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="distribute-xsd">
|
||||||
|
<php expression="substr('${version}', 0, 3)" returnProperty="minorVersion" /><!-- not too robust -->
|
||||||
|
<copy file="${project.basedir}/doctrine-mapping.xsd" tofile="${project.xsd_dir}/doctrine-mapping-${minorVersion}.xsd" />
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="update-dev-version">
|
<target name="update-dev-version">
|
||||||
@ -235,7 +240,7 @@
|
|||||||
<exec command="git commit -m 'Bump Dev Version to ${next_version}-DEV'" passthru="true" />
|
<exec command="git commit -m 'Bump Dev Version to ${next_version}-DEV'" passthru="true" />
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="release" depends="git-tag,build-packages,package-phar,distribute-download,pirum-release,update-dev-version" />
|
<target name="release" depends="git-tag,build-packages,distribute-download,pirum-release,update-dev-version,distribute-xsd" />
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Builds distributable PEAR packages for the Symfony Dependencies
|
Builds distributable PEAR packages for the Symfony Dependencies
|
||||||
|
20
composer.json
Normal file
20
composer.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"name": "doctrine/orm",
|
||||||
|
"type": "library",
|
||||||
|
"description": "Object-Relational-Mapper for PHP",
|
||||||
|
"keywords": ["orm", "database"],
|
||||||
|
"homepage": "http://www.doctrine-project.org",
|
||||||
|
"license": "LGPL",
|
||||||
|
"authors": [
|
||||||
|
{"name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com"},
|
||||||
|
{"name": "Roman Borschel", "email": "roman@code-factory.org"},
|
||||||
|
{"name": "Benjamin Eberlei", "email": "kontakt@beberlei.de"},
|
||||||
|
{"name": "Jonathan Wage", "email": "jonwage@gmail.com"}
|
||||||
|
],
|
||||||
|
"require": {
|
||||||
|
"php": ">=5.3.2",
|
||||||
|
"ext-pdo": "*",
|
||||||
|
"doctrine/common": "master-dev",
|
||||||
|
"doctrine/dbal": "master-dev"
|
||||||
|
}
|
||||||
|
}
|
@ -92,7 +92,7 @@
|
|||||||
<xs:element name="discriminator-map" type="orm:discriminator-map" minOccurs="0"/>
|
<xs:element name="discriminator-map" type="orm:discriminator-map" minOccurs="0"/>
|
||||||
<xs:element name="lifecycle-callbacks" type="orm:lifecycle-callbacks" minOccurs="0" maxOccurs="1" />
|
<xs:element name="lifecycle-callbacks" type="orm:lifecycle-callbacks" minOccurs="0" maxOccurs="1" />
|
||||||
<xs:element name="named-queries" type="orm:named-queries" minOccurs="0" maxOccurs="1" />
|
<xs:element name="named-queries" type="orm:named-queries" minOccurs="0" maxOccurs="1" />
|
||||||
<xs:element name="id" type="orm:id" minOccurs="0" maxOccurs="1" />
|
<xs:element name="id" type="orm:id" minOccurs="0" maxOccurs="unbounded" />
|
||||||
<xs:element name="field" type="orm:field" minOccurs="0" maxOccurs="unbounded"/>
|
<xs:element name="field" type="orm:field" minOccurs="0" maxOccurs="unbounded"/>
|
||||||
<xs:element name="one-to-one" type="orm:one-to-one" minOccurs="0" maxOccurs="unbounded"/>
|
<xs:element name="one-to-one" type="orm:one-to-one" minOccurs="0" maxOccurs="unbounded"/>
|
||||||
<xs:element name="one-to-many" type="orm:one-to-many" minOccurs="0" maxOccurs="unbounded" />
|
<xs:element name="one-to-many" type="orm:one-to-many" minOccurs="0" maxOccurs="unbounded" />
|
||||||
|
@ -162,6 +162,16 @@ abstract class AbstractQuery
|
|||||||
{
|
{
|
||||||
return $this->_params;
|
return $this->_params;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all defined parameter types.
|
||||||
|
*
|
||||||
|
* @return array The defined query parameter types.
|
||||||
|
*/
|
||||||
|
public function getParameterTypes()
|
||||||
|
{
|
||||||
|
return $this->_paramTypes;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a query parameter.
|
* Gets a query parameter.
|
||||||
@ -174,6 +184,17 @@ abstract class AbstractQuery
|
|||||||
return isset($this->_params[$key]) ? $this->_params[$key] : null;
|
return isset($this->_params[$key]) ? $this->_params[$key] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a query parameter type.
|
||||||
|
*
|
||||||
|
* @param mixed $key The key (index or name) of the bound parameter.
|
||||||
|
* @return mixed The parameter type of the bound parameter.
|
||||||
|
*/
|
||||||
|
public function getParameterType($key)
|
||||||
|
{
|
||||||
|
return isset($this->_paramTypes[$key]) ? $this->_paramTypes[$key] : null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the SQL query that corresponds to this query object.
|
* Gets the SQL query that corresponds to this query object.
|
||||||
* The returned SQL syntax depends on the connection driver that is used
|
* The returned SQL syntax depends on the connection driver that is used
|
||||||
|
@ -528,4 +528,32 @@ class Configuration extends \Doctrine\DBAL\Configuration
|
|||||||
return isset($this->_attributes['filters'][$name]) ?
|
return isset($this->_attributes['filters'][$name]) ?
|
||||||
$this->_attributes['filters'][$name] : null;
|
$this->_attributes['filters'][$name] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set default repository class.
|
||||||
|
*
|
||||||
|
* @since 2.2
|
||||||
|
* @param string $className
|
||||||
|
* @throws ORMException If not is a Doctrine\ORM\EntityRepository
|
||||||
|
*/
|
||||||
|
public function setDefaultRepositoryClassName($className)
|
||||||
|
{
|
||||||
|
if ($className != "Doctrine\ORM\EntityRepository" &&
|
||||||
|
!is_subclass_of($className, 'Doctrine\ORM\EntityRepository')){
|
||||||
|
throw ORMException::invalidEntityRepository($className);
|
||||||
|
}
|
||||||
|
$this->_attributes['defaultRepositoryClassName'] = $className;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get default repository class.
|
||||||
|
*
|
||||||
|
* @since 2.2
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getDefaultRepositoryClassName()
|
||||||
|
{
|
||||||
|
return isset($this->_attributes['defaultRepositoryClassName']) ?
|
||||||
|
$this->_attributes['defaultRepositoryClassName'] : 'Doctrine\ORM\EntityRepository';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -584,7 +584,8 @@ class EntityManager implements ObjectManager
|
|||||||
if ($customRepositoryClassName !== null) {
|
if ($customRepositoryClassName !== null) {
|
||||||
$repository = new $customRepositoryClassName($this, $metadata);
|
$repository = new $customRepositoryClassName($this, $metadata);
|
||||||
} else {
|
} else {
|
||||||
$repository = new EntityRepository($this, $metadata);
|
$repositoryClass = $this->config->getDefaultRepositoryClassName();
|
||||||
|
$repository = new $repositoryClass($this, $metadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->repositories[$entityName] = $repository;
|
$this->repositories[$entityName] = $repository;
|
||||||
|
110
lib/Doctrine/ORM/Event/EntityEventDelegator.php
Normal file
110
lib/Doctrine/ORM/Event/EntityEventDelegator.php
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* 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.doctrine-project.org>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Doctrine\ORM\Event;
|
||||||
|
|
||||||
|
use \Doctrine\Common\EventSubscriber;
|
||||||
|
use \LogicException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delegate events only for certain entities they are registered for.
|
||||||
|
*
|
||||||
|
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||||
|
* @since 2.2
|
||||||
|
*/
|
||||||
|
class EntityEventDelegator implements EventSubscriber
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Keeps track of all the event listeners.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $listeners = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If frozen no new event listeners can be added.
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private $frozen = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an event listener that listens on the specified events.
|
||||||
|
*
|
||||||
|
* @param string|array $events The event(s) to listen on.
|
||||||
|
* @param string|array $entities The entities to trigger this listener for
|
||||||
|
* @param object $listener The listener object.
|
||||||
|
*/
|
||||||
|
public function addEventListener($events, $entities, $listener)
|
||||||
|
{
|
||||||
|
if ($this->frozen) {
|
||||||
|
throw new LogicException("Cannot add event listeners after EntityEventDelegator::getSubscribedEvents() " .
|
||||||
|
"is called once. This happens when you register the delegator with the event manager.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Picks the hash code related to that listener
|
||||||
|
$hash = spl_object_hash($listener);
|
||||||
|
|
||||||
|
foreach ((array) $events as $event) {
|
||||||
|
// Overrides listener if a previous one was associated already
|
||||||
|
// Prevents duplicate listeners on same event (same instance only)
|
||||||
|
$this->listeners[$event][$hash] = array('listener' => $listener, 'entities' => array_flip((array)$entities));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an EventSubscriber. The subscriber is asked for all the events he is
|
||||||
|
* interested in and added as a listener for these events.
|
||||||
|
*
|
||||||
|
* @param Doctrine\Common\EventSubscriber $subscriber The subscriber.
|
||||||
|
*/
|
||||||
|
public function addEventSubscriber(EventSubscriber $subscriber, $entities)
|
||||||
|
{
|
||||||
|
$this->addEventListener($subscriber->getSubscribedEvents(), $entities, $subscriber);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array of events this subscriber wants to listen to.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getSubscribedEvents()
|
||||||
|
{
|
||||||
|
$this->frozen = true;
|
||||||
|
return array_keys($this->listeners);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delegate the event to an appropriate listener
|
||||||
|
*
|
||||||
|
* @param $eventName
|
||||||
|
* @param $event
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __call($eventName, $args)
|
||||||
|
{
|
||||||
|
$event = $args[0];
|
||||||
|
foreach ($this->listeners[$eventName] AS $listenerData) {
|
||||||
|
$class = get_class($event->getEntity());
|
||||||
|
if (isset($listenerData['entities'][$class])) {
|
||||||
|
$listenerData['listener']->$eventName($event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -90,7 +90,7 @@ class PreUpdateEventArgs extends LifecycleEventArgs
|
|||||||
if (!isset($this->_entityChangeSet[$field])) {
|
if (!isset($this->_entityChangeSet[$field])) {
|
||||||
throw new \InvalidArgumentException(
|
throw new \InvalidArgumentException(
|
||||||
"Field '".$field."' is not a valid field of the entity ".
|
"Field '".$field."' is not a valid field of the entity ".
|
||||||
"'".get_class($this->getEntity())."' in PreInsertUpdateEventArgs."
|
"'".get_class($this->getEntity())."' in PreUpdateEventArgs."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
167
lib/Doctrine/ORM/Mapping/Builder/AssociationBuilder.php
Normal file
167
lib/Doctrine/ORM/Mapping/Builder/AssociationBuilder.php
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* 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.doctrine-project.org>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
namespace Doctrine\ORM\Mapping\Builder;
|
||||||
|
|
||||||
|
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||||
|
|
||||||
|
class AssociationBuilder
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var ClassMetadataBuilder
|
||||||
|
*/
|
||||||
|
protected $builder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $mapping;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $joinColumns;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
protected $type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ClassMetadataBuilder $builder
|
||||||
|
* @param array $mapping
|
||||||
|
*/
|
||||||
|
public function __construct(ClassMetadataBuilder $builder, array $mapping, $type)
|
||||||
|
{
|
||||||
|
$this->builder = $builder;
|
||||||
|
$this->mapping = $mapping;
|
||||||
|
$this->type = $type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function mappedBy($fieldName)
|
||||||
|
{
|
||||||
|
$this->mapping['mappedBy'] = $fieldName;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function inversedBy($fieldName)
|
||||||
|
{
|
||||||
|
$this->mapping['inversedBy'] = $fieldName;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function cascadeAll()
|
||||||
|
{
|
||||||
|
$this->mapping['cascade'] = array("ALL");
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function cascadePersist()
|
||||||
|
{
|
||||||
|
$this->mapping['cascade'][] = "persist";
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function cascadeRemove()
|
||||||
|
{
|
||||||
|
$this->mapping['cascade'][] = "remove";
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function cascadeMerge()
|
||||||
|
{
|
||||||
|
$this->mapping['cascade'][] = "merge";
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function cascadeDetach()
|
||||||
|
{
|
||||||
|
$this->mapping['cascade'][] = "detach";
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function cascadeRefresh()
|
||||||
|
{
|
||||||
|
$this->mapping['cascade'][] = "refresh";
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function fetchExtraLazy()
|
||||||
|
{
|
||||||
|
$this->mapping['fetch'] = ClassMetadata::FETCH_EXTRA_LAZY;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function fetchEager()
|
||||||
|
{
|
||||||
|
$this->mapping['fetch'] = ClassMetadata::FETCH_EAGER;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function fetchLazy()
|
||||||
|
{
|
||||||
|
$this->mapping['fetch'] = ClassMetadata::FETCH_LAZY;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add Join Columns
|
||||||
|
*
|
||||||
|
* @param string $columnName
|
||||||
|
* @param string $referencedColumnName
|
||||||
|
* @param bool $nullable
|
||||||
|
* @param bool $unique
|
||||||
|
* @param string $onDelete
|
||||||
|
* @param string $columnDef
|
||||||
|
*/
|
||||||
|
public function addJoinColumn($columnName, $referencedColumnName, $nullable = true, $unique = false, $onDelete = null, $columnDef = null)
|
||||||
|
{
|
||||||
|
$this->joinColumns[] = array(
|
||||||
|
'name' => $columnName,
|
||||||
|
'referencedColumnName' => $referencedColumnName,
|
||||||
|
'nullable' => $nullable,
|
||||||
|
'unique' => $unique,
|
||||||
|
'onDelete' => $onDelete,
|
||||||
|
'columnDefinition' => $columnDef,
|
||||||
|
);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return ClassMetadataBuilder
|
||||||
|
*/
|
||||||
|
public function build()
|
||||||
|
{
|
||||||
|
$mapping = $this->mapping;
|
||||||
|
if ($this->joinColumns) {
|
||||||
|
$mapping['joinColumns'] = $this->joinColumns;
|
||||||
|
}
|
||||||
|
$cm = $this->builder->getClassMetadata();
|
||||||
|
if ($this->type == ClassMetadata::MANY_TO_ONE) {
|
||||||
|
$cm->mapManyToOne($mapping);
|
||||||
|
} else if ($this->type == ClassMetadata::ONE_TO_ONE) {
|
||||||
|
$cm->mapOneToOne($mapping);
|
||||||
|
} else {
|
||||||
|
throw new \InvalidArgumentException("Type should be a ToOne Assocation here");
|
||||||
|
}
|
||||||
|
return $this->builder;
|
||||||
|
}
|
||||||
|
}
|
407
lib/Doctrine/ORM/Mapping/Builder/ClassMetadataBuilder.php
Normal file
407
lib/Doctrine/ORM/Mapping/Builder/ClassMetadataBuilder.php
Normal file
@ -0,0 +1,407 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* 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.doctrine-project.org>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Doctrine\ORM\Mapping\Builder;
|
||||||
|
|
||||||
|
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builder Object for ClassMetadata
|
||||||
|
*
|
||||||
|
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||||
|
* @link www.doctrine-project.com
|
||||||
|
* @since 2.2
|
||||||
|
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||||
|
*/
|
||||||
|
class ClassMetadataBuilder
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var ClassMetadata
|
||||||
|
*/
|
||||||
|
private $cm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ClassMetadata $cm
|
||||||
|
*/
|
||||||
|
public function __construct(ClassMetadata $cm)
|
||||||
|
{
|
||||||
|
$this->cm = $cm;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return ClassMetadata
|
||||||
|
*/
|
||||||
|
public function getClassMetadata()
|
||||||
|
{
|
||||||
|
return $this->cm;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark the class as mapped superclass.
|
||||||
|
*
|
||||||
|
* @return ClassMetadataBuilder
|
||||||
|
*/
|
||||||
|
public function setMappedSuperClass()
|
||||||
|
{
|
||||||
|
$this->cm->isMappedSuperclass = true;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set custom Repository class name
|
||||||
|
*
|
||||||
|
* @param string $repositoryClassName
|
||||||
|
* @return ClassMetadataBuilder
|
||||||
|
*/
|
||||||
|
public function setCustomRepositoryClass($repositoryClassName)
|
||||||
|
{
|
||||||
|
$this->cm->setCustomRepositoryClass($repositoryClassName);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark class read only
|
||||||
|
*
|
||||||
|
* @return ClassMetadataBuilder
|
||||||
|
*/
|
||||||
|
public function setReadOnly()
|
||||||
|
{
|
||||||
|
$this->cm->markReadOnly();
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the table name
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @return ClassMetadataBuilder
|
||||||
|
*/
|
||||||
|
public function setTable($name)
|
||||||
|
{
|
||||||
|
$this->cm->setPrimaryTable(array('name' => $name));
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add Index
|
||||||
|
*
|
||||||
|
* @param array $columns
|
||||||
|
* @param string $name
|
||||||
|
* @return ClassMetadataBuilder
|
||||||
|
*/
|
||||||
|
public function addIndex(array $columns, $name)
|
||||||
|
{
|
||||||
|
if (!isset($this->cm->table['indexes'])) {
|
||||||
|
$this->cm->table['indexes'] = array();
|
||||||
|
}
|
||||||
|
$this->cm->table['indexes'][$name] = array('columns' => $columns);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add Unique Constraint
|
||||||
|
*
|
||||||
|
* @param array $columns
|
||||||
|
* @param string $name
|
||||||
|
* @return ClassMetadataBuilder
|
||||||
|
*/
|
||||||
|
public function addUniqueConstraint(array $columns, $name)
|
||||||
|
{
|
||||||
|
if (!isset($this->cm->table['uniqueConstraints'])) {
|
||||||
|
$this->cm->table['uniqueConstraints'] = array();
|
||||||
|
}
|
||||||
|
$this->cm->table['uniqueConstraints'][$name] = array('columns' => $columns);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add named query
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @param string $dqlQuery
|
||||||
|
* @return ClassMetadataBuilder
|
||||||
|
*/
|
||||||
|
public function addNamedQuery($name, $dqlQuery)
|
||||||
|
{
|
||||||
|
$this->cm->addNamedQuery(array(
|
||||||
|
'name' => $name,
|
||||||
|
'query' => $dqlQuery,
|
||||||
|
));
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set class as root of a joined table inheritance hierachy.
|
||||||
|
*
|
||||||
|
* @return ClassMetadataBuilder
|
||||||
|
*/
|
||||||
|
public function setJoinedTableInheritance()
|
||||||
|
{
|
||||||
|
$this->cm->setInheritanceType(ClassMetadata::INHERITANCE_TYPE_JOINED);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set class as root of a single table inheritance hierachy.
|
||||||
|
*
|
||||||
|
* @return ClassMetadataBuilder
|
||||||
|
*/
|
||||||
|
public function setSingleTableInheritance()
|
||||||
|
{
|
||||||
|
$this->cm->setInheritanceType(ClassMetadata::INHERITANCE_TYPE_SINGLE_TABLE);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the discriminator column details.
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @param string $type
|
||||||
|
*/
|
||||||
|
public function setDiscriminatorColumn($name, $type = 'string', $length = 255)
|
||||||
|
{
|
||||||
|
$this->cm->setDiscriminatorColumn(array(
|
||||||
|
'name' => $name,
|
||||||
|
'type' => $type,
|
||||||
|
'length' => $length,
|
||||||
|
));
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a subclass to this inheritance hierachy.
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @param string $class
|
||||||
|
* @return ClassMetadataBuilder
|
||||||
|
*/
|
||||||
|
public function addDiscriminatorMapClass($name, $class)
|
||||||
|
{
|
||||||
|
$this->cm->addDiscriminatorMapClass($name, $class);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set deferred explicit change tracking policy.
|
||||||
|
*
|
||||||
|
* @return ClassMetadataBuilder
|
||||||
|
*/
|
||||||
|
public function setChangeTrackingPolicyDeferredExplicit()
|
||||||
|
{
|
||||||
|
$this->cm->setChangeTrackingPolicy(ClassMetadata::CHANGETRACKING_DEFERRED_EXPLICIT);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set notify change tracking policy.
|
||||||
|
*
|
||||||
|
* @return ClassMetadataBuilder
|
||||||
|
*/
|
||||||
|
public function setChangeTrackingPolicyNotify()
|
||||||
|
{
|
||||||
|
$this->cm->setChangeTrackingPolicy(ClassMetadata::CHANGETRACKING_NOTIFY);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add lifecycle event
|
||||||
|
*
|
||||||
|
* @param string $methodName
|
||||||
|
* @param string $event
|
||||||
|
* @return ClassMetadataBuilder
|
||||||
|
*/
|
||||||
|
public function addLifecycleEvent($methodName, $event)
|
||||||
|
{
|
||||||
|
$this->cm->addLifecycleCallback($methodName, $event);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add Field
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @param string $type
|
||||||
|
* @param array $mapping
|
||||||
|
*/
|
||||||
|
public function addField($name, $type, array $mapping = array())
|
||||||
|
{
|
||||||
|
$mapping['fieldName'] = $name;
|
||||||
|
$mapping['type'] = $type;
|
||||||
|
$this->cm->mapField($mapping);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a field builder.
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @param string $type
|
||||||
|
* @return FieldBuilder
|
||||||
|
*/
|
||||||
|
public function createField($name, $type)
|
||||||
|
{
|
||||||
|
return new FieldBuilder($this, array('fieldName' => $name, 'type' => $type));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a simple many to one association, optionally with the inversed by field.
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @param string $targetEntity
|
||||||
|
* @param string|null $inversedBy
|
||||||
|
* @return ClassMetadataBuilder
|
||||||
|
*/
|
||||||
|
public function addManyToOne($name, $targetEntity, $inversedBy = null)
|
||||||
|
{
|
||||||
|
$builder = $this->createManyToOne($name, $targetEntity);
|
||||||
|
if ($inversedBy) {
|
||||||
|
$builder->setInversedBy($inversedBy);
|
||||||
|
}
|
||||||
|
return $builder->build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a ManyToOne Assocation Builder.
|
||||||
|
*
|
||||||
|
* Note: This method does not add the association, you have to call build() on the AssociationBuilder.
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @param string $targetEntity
|
||||||
|
* @return AssociationBuilder
|
||||||
|
*/
|
||||||
|
public function createManyToOne($name, $targetEntity)
|
||||||
|
{
|
||||||
|
return new AssociationBuilder($this, array('fieldName' => $name, 'targetEntity' => $targetEntity), ClassMetadata::MANY_TO_ONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create OneToOne Assocation Builder
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @param string $targetEntity
|
||||||
|
* @return AssociationBuilder
|
||||||
|
*/
|
||||||
|
public function createOneToOne($name, $targetEntity)
|
||||||
|
{
|
||||||
|
return new AssociationBuilder($this, array('fieldName' => $name, 'targetEntity' => $targetEntity), ClassMetadata::ONE_TO_ONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add simple inverse one-to-one assocation.
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @param string $targetEntity
|
||||||
|
* @param string $mappedBy
|
||||||
|
* @return ClassMetadataBuilder
|
||||||
|
*/
|
||||||
|
public function addInverseOneToOne($name, $targetEntity, $mappedBy)
|
||||||
|
{
|
||||||
|
$builder = $this->createOneToOne($name, $targetEntity);
|
||||||
|
$builder->setMappedBy($mappedBy);
|
||||||
|
return $builder->build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add simple owning one-to-one assocation.
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @param string $targetEntity
|
||||||
|
* @param string $inversedBy
|
||||||
|
* @return ClassMetadataBuilder
|
||||||
|
*/
|
||||||
|
public function addOwningOneToOne($name, $targetEntity, $inversedBy = null)
|
||||||
|
{
|
||||||
|
$builder = $this->createOneToOne($name, $targetEntity);
|
||||||
|
if ($inversedBy) {
|
||||||
|
$builder->setInversedBy($inversedBy);
|
||||||
|
}
|
||||||
|
return $builder->build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create ManyToMany Assocation Builder
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @param string $targetEntity
|
||||||
|
* @return ManyToManyAssociationBuilder
|
||||||
|
*/
|
||||||
|
public function createManyToMany($name, $targetEntity)
|
||||||
|
{
|
||||||
|
return new ManyToManyAssociationBuilder($this, array('fieldName' => $name, 'targetEntity' => $targetEntity), ClassMetadata::MANY_TO_MANY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a simple owning many to many assocation.
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @param string $targetEntity
|
||||||
|
* @param string|null $inversedBy
|
||||||
|
* @return ClassMetadataBuilder
|
||||||
|
*/
|
||||||
|
public function addOwningManyToMany($name, $targetEntity, $inversedBy = null)
|
||||||
|
{
|
||||||
|
$builder = $this->createManyToMany($name, $targetEntity);
|
||||||
|
if ($inversedBy) {
|
||||||
|
$builder->setInversedBy($inversedBy);
|
||||||
|
}
|
||||||
|
return $builder->build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a simple inverse many to many assocation.
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @param string $targetEntity
|
||||||
|
* @param string $mappedBy
|
||||||
|
* @return ClassMetadataBuilder
|
||||||
|
*/
|
||||||
|
public function addInverseManyToMany($name, $targetEntity, $mappedBy)
|
||||||
|
{
|
||||||
|
$builder = $this->createManyToMany($name, $targetEntity);
|
||||||
|
$builder->setMappedBy($mappedBy);
|
||||||
|
return $builder->build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a one to many assocation builder
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @param string $targetEntity
|
||||||
|
* @return OneToManyAssociationBuilder
|
||||||
|
*/
|
||||||
|
public function createOneToMany($name, $targetEntity)
|
||||||
|
{
|
||||||
|
return new OneToManyAssociationBuilder($this, array('fieldName' => $name, 'targetEntity' => $targetEntity), ClassMetadata::ONE_TO_MANY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add simple OneToMany assocation.
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @param string $targetEntity
|
||||||
|
* @param string $mappedBy
|
||||||
|
* @return ClassMetadataBuilder
|
||||||
|
*/
|
||||||
|
public function addOneToMany($name, $targetEntity, $mappedBy)
|
||||||
|
{
|
||||||
|
$builder = $this->createOneToMany($name, $targetEntity);
|
||||||
|
$builder->setMappedBy($mappedBy);
|
||||||
|
return $builder->build();
|
||||||
|
}
|
||||||
|
}
|
223
lib/Doctrine/ORM/Mapping/Builder/FieldBuilder.php
Normal file
223
lib/Doctrine/ORM/Mapping/Builder/FieldBuilder.php
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* 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.doctrine-project.org>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
namespace Doctrine\ORM\Mapping\Builder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Field Builder
|
||||||
|
*
|
||||||
|
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||||
|
* @link www.doctrine-project.com
|
||||||
|
* @since 2.2
|
||||||
|
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||||
|
*/
|
||||||
|
class FieldBuilder
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var ClassMetadataBuilder
|
||||||
|
*/
|
||||||
|
private $builder;
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $mapping;
|
||||||
|
/**
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private $version;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $generatedValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $sequenceDef;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param ClassMetadataBuilder $builder
|
||||||
|
* @param array $mapping
|
||||||
|
*/
|
||||||
|
public function __construct(ClassMetadataBuilder $builder, array $mapping)
|
||||||
|
{
|
||||||
|
$this->builder = $builder;
|
||||||
|
$this->mapping = $mapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set length.
|
||||||
|
*
|
||||||
|
* @param int $length
|
||||||
|
* @return FieldBuilder
|
||||||
|
*/
|
||||||
|
public function length($length)
|
||||||
|
{
|
||||||
|
$this->mapping['length'] = $length;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set nullable
|
||||||
|
*
|
||||||
|
* @param bool
|
||||||
|
* @return FieldBuilder
|
||||||
|
*/
|
||||||
|
public function nullable($flag = true)
|
||||||
|
{
|
||||||
|
$this->mapping['nullable'] = (bool)$flag;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Unique
|
||||||
|
*
|
||||||
|
* @param bool
|
||||||
|
* @return FieldBuilder
|
||||||
|
*/
|
||||||
|
public function unique($flag = true)
|
||||||
|
{
|
||||||
|
$this->mapping['unique'] = (bool)$flag;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set column name
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @return FieldBuilder
|
||||||
|
*/
|
||||||
|
public function columnName($name)
|
||||||
|
{
|
||||||
|
$this->mapping['columnName'] = $name;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Precision
|
||||||
|
*
|
||||||
|
* @param int $p
|
||||||
|
* @return FieldBuilder
|
||||||
|
*/
|
||||||
|
public function precision($p)
|
||||||
|
{
|
||||||
|
$this->mapping['precision'] = $p;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set scale.
|
||||||
|
*
|
||||||
|
* @param int $s
|
||||||
|
* @return FieldBuilder
|
||||||
|
*/
|
||||||
|
public function scale($s)
|
||||||
|
{
|
||||||
|
$this->mapping['scale'] = $s;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set field as primary key.
|
||||||
|
*
|
||||||
|
* @return FieldBuilder
|
||||||
|
*/
|
||||||
|
public function isPrimaryKey()
|
||||||
|
{
|
||||||
|
$this->mapping['id'] = true;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $strategy
|
||||||
|
* @return FieldBuilder
|
||||||
|
*/
|
||||||
|
public function generatedValue($strategy = 'AUTO')
|
||||||
|
{
|
||||||
|
$this->generatedValue = $strategy;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set field versioned
|
||||||
|
*
|
||||||
|
* @return FieldBuilder
|
||||||
|
*/
|
||||||
|
public function isVersionField()
|
||||||
|
{
|
||||||
|
$this->version = true;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Sequence Generator
|
||||||
|
*
|
||||||
|
* @param string $sequenceName
|
||||||
|
* @param int $allocationSize
|
||||||
|
* @param int $initialValue
|
||||||
|
* @return FieldBuilder
|
||||||
|
*/
|
||||||
|
public function setSequenceGenerator($sequenceName, $allocationSize = 1, $initialValue = 1)
|
||||||
|
{
|
||||||
|
$this->sequenceDef = array(
|
||||||
|
'sequenceName' => $sequenceName,
|
||||||
|
'allocationSize' => $allocationSize,
|
||||||
|
'initialValue' => $initialValue,
|
||||||
|
);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set column definition.
|
||||||
|
*
|
||||||
|
* @param string $def
|
||||||
|
* @return FieldBuilder
|
||||||
|
*/
|
||||||
|
public function columnDefinition($def)
|
||||||
|
{
|
||||||
|
$this->mapping['columnDefinition'] = $def;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finalize this field and attach it to the ClassMetadata.
|
||||||
|
*
|
||||||
|
* Without this call a FieldBuilder has no effect on the ClassMetadata.
|
||||||
|
*
|
||||||
|
* @return ClassMetadataBuilder
|
||||||
|
*/
|
||||||
|
public function build()
|
||||||
|
{
|
||||||
|
$cm = $this->builder->getClassMetadata();
|
||||||
|
if ($this->generatedValue) {
|
||||||
|
$cm->setIdGeneratorType(constant('Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_' . $this->generatedValue));
|
||||||
|
}
|
||||||
|
if ($this->version) {
|
||||||
|
$cm->setVersionMapping($this->mapping);
|
||||||
|
}
|
||||||
|
$cm->mapField($this->mapping);
|
||||||
|
if ($this->sequenceDef) {
|
||||||
|
$cm->setSequenceGeneratorDefinition($this->sequenceDef);
|
||||||
|
}
|
||||||
|
return $this->builder;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,86 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* 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.doctrine-project.org>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
namespace Doctrine\ORM\Mapping\Builder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ManyToMany Association Builder
|
||||||
|
*
|
||||||
|
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||||
|
* @link www.doctrine-project.com
|
||||||
|
* @since 2.0
|
||||||
|
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||||
|
*/
|
||||||
|
class ManyToManyAssociationBuilder extends OneToManyAssociationBuilder
|
||||||
|
{
|
||||||
|
private $joinTableName;
|
||||||
|
|
||||||
|
private $inverseJoinColumns = array();
|
||||||
|
|
||||||
|
public function setJoinTable($name)
|
||||||
|
{
|
||||||
|
$this->joinTableName = $name;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add Inverse Join Columns
|
||||||
|
*
|
||||||
|
* @param string $columnName
|
||||||
|
* @param string $referencedColumnName
|
||||||
|
* @param bool $nullable
|
||||||
|
* @param bool $unique
|
||||||
|
* @param string $onDelete
|
||||||
|
* @param string $columnDef
|
||||||
|
*/
|
||||||
|
public function addInverseJoinColumn($columnName, $referencedColumnName, $nullable = true, $unique = false, $onDelete = null, $columnDef = null)
|
||||||
|
{
|
||||||
|
$this->inverseJoinColumns[] = array(
|
||||||
|
'name' => $columnName,
|
||||||
|
'referencedColumnName' => $referencedColumnName,
|
||||||
|
'nullable' => $nullable,
|
||||||
|
'unique' => $unique,
|
||||||
|
'onDelete' => $onDelete,
|
||||||
|
'columnDefinition' => $columnDef,
|
||||||
|
);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return ClassMetadataBuilder
|
||||||
|
*/
|
||||||
|
public function build()
|
||||||
|
{
|
||||||
|
$mapping = $this->mapping;
|
||||||
|
$mapping['joinTable'] = array();
|
||||||
|
if ($this->joinColumns) {
|
||||||
|
$mapping['joinTable']['joinColumns'] = $this->joinColumns;
|
||||||
|
}
|
||||||
|
if ($this->inverseJoinColumns) {
|
||||||
|
$mapping['joinTable']['inverseJoinColumns'] = $this->inverseJoinColumns;
|
||||||
|
}
|
||||||
|
if ($this->joinTableName) {
|
||||||
|
$mapping['joinTable']['name'] = $this->joinTableName;
|
||||||
|
}
|
||||||
|
$cm = $this->builder->getClassMetadata();
|
||||||
|
$cm->mapManyToMany($mapping);
|
||||||
|
return $this->builder;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* 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.doctrine-project.org>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
namespace Doctrine\ORM\Mapping\Builder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OneToMany Association Builder
|
||||||
|
*
|
||||||
|
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||||
|
* @link www.doctrine-project.com
|
||||||
|
* @since 2.0
|
||||||
|
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||||
|
*/
|
||||||
|
class OneToManyAssociationBuilder extends AssociationBuilder
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param array $fieldNames
|
||||||
|
* @return OneToManyAssociationBuilder
|
||||||
|
*/
|
||||||
|
public function setOrderBy(array $fieldNames)
|
||||||
|
{
|
||||||
|
$this->mapping['orderBy'] = $fieldNames;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setIndexBy($fieldName)
|
||||||
|
{
|
||||||
|
$this->mapping['indexBy'] = $fieldName;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return ClassMetadataBuilder
|
||||||
|
*/
|
||||||
|
public function build()
|
||||||
|
{
|
||||||
|
$mapping = $this->mapping;
|
||||||
|
if ($this->joinColumns) {
|
||||||
|
$mapping['joinColumns'] = $this->joinColumns;
|
||||||
|
}
|
||||||
|
$cm = $this->builder->getClassMetadata();
|
||||||
|
$cm->mapOneToMany($mapping);
|
||||||
|
return $this->builder;
|
||||||
|
}
|
||||||
|
}
|
@ -343,4 +343,17 @@ class ClassMetadata extends ClassMetadataInfo
|
|||||||
}
|
}
|
||||||
return clone $this->_prototype;
|
return clone $this->_prototype;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $callback
|
||||||
|
* @param string $event
|
||||||
|
*/
|
||||||
|
public function addLifecycleCallback($callback, $event)
|
||||||
|
{
|
||||||
|
if ( !$this->reflClass->hasMethod($callback) ||
|
||||||
|
($this->reflClass->getMethod($callback)->getModifiers() & \ReflectionMethod::IS_PUBLIC) == 0) {
|
||||||
|
throw MappingException::lifecycleCallbackMethodNotFound($this->name, $callback);
|
||||||
|
}
|
||||||
|
return parent::addLifecycleCallback($callback, $event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface
|
|||||||
private $targetPlatform;
|
private $targetPlatform;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Driver\Driver
|
* @var \Doctrine\ORM\Mapping\Driver\Driver
|
||||||
*/
|
*/
|
||||||
private $driver;
|
private $driver;
|
||||||
|
|
||||||
@ -274,6 +274,9 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface
|
|||||||
$class->setDiscriminatorMap($parent->discriminatorMap);
|
$class->setDiscriminatorMap($parent->discriminatorMap);
|
||||||
$class->setLifecycleCallbacks($parent->lifecycleCallbacks);
|
$class->setLifecycleCallbacks($parent->lifecycleCallbacks);
|
||||||
$class->setChangeTrackingPolicy($parent->changeTrackingPolicy);
|
$class->setChangeTrackingPolicy($parent->changeTrackingPolicy);
|
||||||
|
if ($parent->isMappedSuperclass) {
|
||||||
|
$class->setCustomRepositoryClass($parent->customRepositoryClassName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invoke driver
|
// Invoke driver
|
||||||
@ -448,7 +451,7 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface
|
|||||||
// <table>_<column>_seq in PostgreSQL for SERIAL columns.
|
// <table>_<column>_seq in PostgreSQL for SERIAL columns.
|
||||||
// Not pretty but necessary and the simplest solution that currently works.
|
// Not pretty but necessary and the simplest solution that currently works.
|
||||||
$seqName = $this->targetPlatform instanceof Platforms\PostgreSQLPlatform ?
|
$seqName = $this->targetPlatform instanceof Platforms\PostgreSQLPlatform ?
|
||||||
$class->table['name'] . '_' . $class->columnNames[$class->identifier[0]] . '_seq' :
|
$class->getTableName() . '_' . $class->columnNames[$class->identifier[0]] . '_seq' :
|
||||||
null;
|
null;
|
||||||
$class->setIdGenerator(new \Doctrine\ORM\Id\IdentityGenerator($seqName));
|
$class->setIdGenerator(new \Doctrine\ORM\Id\IdentityGenerator($seqName));
|
||||||
break;
|
break;
|
||||||
@ -478,4 +481,15 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface
|
|||||||
throw new ORMException("Unknown generator type: " . $class->generatorType);
|
throw new ORMException("Unknown generator type: " . $class->generatorType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if this class is mapped by this EntityManager + ClassMetadata configuration
|
||||||
|
*
|
||||||
|
* @param $class
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isTransient($class)
|
||||||
|
{
|
||||||
|
return $this->driver->isTransient($class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -774,9 +774,13 @@ class ClassMetadataInfo implements ClassMetadata
|
|||||||
// If targetEntity is unqualified, assume it is in the same namespace as
|
// If targetEntity is unqualified, assume it is in the same namespace as
|
||||||
// the sourceEntity.
|
// the sourceEntity.
|
||||||
$mapping['sourceEntity'] = $this->name;
|
$mapping['sourceEntity'] = $this->name;
|
||||||
if (isset($mapping['targetEntity']) && strpos($mapping['targetEntity'], '\\') === false
|
|
||||||
&& strlen($this->namespace) > 0) {
|
if (isset($mapping['targetEntity'])) {
|
||||||
$mapping['targetEntity'] = $this->namespace . '\\' . $mapping['targetEntity'];
|
if (strlen($this->namespace) > 0 && strpos($mapping['targetEntity'], '\\') === false) {
|
||||||
|
$mapping['targetEntity'] = $this->namespace . '\\' . $mapping['targetEntity'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$mapping['targetEntity'] = ltrim($mapping['targetEntity'], '\\');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Complete id mapping
|
// Complete id mapping
|
||||||
@ -904,9 +908,8 @@ class ClassMetadataInfo implements ClassMetadata
|
|||||||
$mapping['targetToSourceKeyColumns'] = array_flip($mapping['sourceToTargetKeyColumns']);
|
$mapping['targetToSourceKeyColumns'] = array_flip($mapping['sourceToTargetKeyColumns']);
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: if orphanRemoval, cascade=remove is implicit!
|
$mapping['orphanRemoval'] = isset($mapping['orphanRemoval']) ? (bool) $mapping['orphanRemoval'] : false;
|
||||||
$mapping['orphanRemoval'] = isset($mapping['orphanRemoval']) ?
|
$mapping['isCascadeRemove'] = $mapping['orphanRemoval'] ? true : $mapping['isCascadeRemove'];
|
||||||
(bool) $mapping['orphanRemoval'] : false;
|
|
||||||
|
|
||||||
if (isset($mapping['id']) && $mapping['id'] === true && !$mapping['isOwningSide']) {
|
if (isset($mapping['id']) && $mapping['id'] === true && !$mapping['isOwningSide']) {
|
||||||
throw MappingException::illegalInverseIdentifierAssocation($this->name, $mapping['fieldName']);
|
throw MappingException::illegalInverseIdentifierAssocation($this->name, $mapping['fieldName']);
|
||||||
@ -931,9 +934,8 @@ class ClassMetadataInfo implements ClassMetadata
|
|||||||
throw MappingException::oneToManyRequiresMappedBy($mapping['fieldName']);
|
throw MappingException::oneToManyRequiresMappedBy($mapping['fieldName']);
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: if orphanRemoval, cascade=remove is implicit!
|
$mapping['orphanRemoval'] = isset($mapping['orphanRemoval']) ? (bool) $mapping['orphanRemoval'] : false;
|
||||||
$mapping['orphanRemoval'] = isset($mapping['orphanRemoval']) ?
|
$mapping['isCascadeRemove'] = $mapping['orphanRemoval'] ? true : $mapping['isCascadeRemove'];
|
||||||
(bool) $mapping['orphanRemoval'] : false;
|
|
||||||
|
|
||||||
if (isset($mapping['orderBy'])) {
|
if (isset($mapping['orderBy'])) {
|
||||||
if ( ! is_array($mapping['orderBy'])) {
|
if ( ! is_array($mapping['orderBy'])) {
|
||||||
@ -1268,7 +1270,7 @@ class ClassMetadataInfo implements ClassMetadata
|
|||||||
public function getTemporaryIdTableName()
|
public function getTemporaryIdTableName()
|
||||||
{
|
{
|
||||||
// replace dots with underscores because PostgreSQL creates temporary tables in a special schema
|
// replace dots with underscores because PostgreSQL creates temporary tables in a special schema
|
||||||
return str_replace('.', '_', $this->table['name'] . '_id_tmp');
|
return str_replace('.', '_', $this->getTableName() . '_id_tmp');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1367,9 +1369,11 @@ class ClassMetadataInfo implements ClassMetadata
|
|||||||
$this->table['name'] = $table['name'];
|
$this->table['name'] = $table['name'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($table['indexes'])) {
|
if (isset($table['indexes'])) {
|
||||||
$this->table['indexes'] = $table['indexes'];
|
$this->table['indexes'] = $table['indexes'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($table['uniqueConstraints'])) {
|
if (isset($table['uniqueConstraints'])) {
|
||||||
$this->table['uniqueConstraints'] = $table['uniqueConstraints'];
|
$this->table['uniqueConstraints'] = $table['uniqueConstraints'];
|
||||||
}
|
}
|
||||||
@ -1518,6 +1522,10 @@ class ClassMetadataInfo implements ClassMetadata
|
|||||||
*/
|
*/
|
||||||
public function setCustomRepositoryClass($repositoryClassName)
|
public function setCustomRepositoryClass($repositoryClassName)
|
||||||
{
|
{
|
||||||
|
if ($repositoryClassName !== null && strpos($repositoryClassName, '\\') === false
|
||||||
|
&& strlen($this->namespace) > 0) {
|
||||||
|
$repositoryClassName = $this->namespace . '\\' . $repositoryClassName;
|
||||||
|
}
|
||||||
$this->customRepositoryClassName = $repositoryClassName;
|
$this->customRepositoryClassName = $repositoryClassName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1560,9 +1568,6 @@ class ClassMetadataInfo implements ClassMetadata
|
|||||||
/**
|
/**
|
||||||
* Adds a lifecycle callback for entities of this class.
|
* Adds a lifecycle callback for entities of this class.
|
||||||
*
|
*
|
||||||
* Note: If the same callback is registered more than once, the old one
|
|
||||||
* will be overridden.
|
|
||||||
*
|
|
||||||
* @param string $callback
|
* @param string $callback
|
||||||
* @param string $event
|
* @param string $event
|
||||||
*/
|
*/
|
||||||
@ -1621,20 +1626,33 @@ class ClassMetadataInfo implements ClassMetadata
|
|||||||
public function setDiscriminatorMap(array $map)
|
public function setDiscriminatorMap(array $map)
|
||||||
{
|
{
|
||||||
foreach ($map as $value => $className) {
|
foreach ($map as $value => $className) {
|
||||||
if (strpos($className, '\\') === false && strlen($this->namespace)) {
|
$this->addDiscriminatorMapClass($value, $className);
|
||||||
$className = $this->namespace . '\\' . $className;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add one entry of the discriminator map with a new class and corresponding name.
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @param string $className
|
||||||
|
*/
|
||||||
|
public function addDiscriminatorMapClass($name, $className)
|
||||||
|
{
|
||||||
|
if (strlen($this->namespace) > 0 && strpos($className, '\\') === false) {
|
||||||
|
$className = $this->namespace . '\\' . $className;
|
||||||
|
}
|
||||||
|
|
||||||
|
$className = ltrim($className, '\\');
|
||||||
|
$this->discriminatorMap[$name] = $className;
|
||||||
|
|
||||||
|
if ($this->name == $className) {
|
||||||
|
$this->discriminatorValue = $name;
|
||||||
|
} else {
|
||||||
|
if ( ! class_exists($className)) {
|
||||||
|
throw MappingException::invalidClassInDiscriminatorMap($className, $this->name);
|
||||||
}
|
}
|
||||||
$className = ltrim($className, '\\');
|
if (is_subclass_of($className, $this->name)) {
|
||||||
$this->discriminatorMap[$value] = $className;
|
$this->subClasses[] = $className;
|
||||||
if ($this->name == $className) {
|
|
||||||
$this->discriminatorValue = $value;
|
|
||||||
} else {
|
|
||||||
if ( ! class_exists($className)) {
|
|
||||||
throw MappingException::invalidClassInDiscriminatorMap($className, $this->name);
|
|
||||||
}
|
|
||||||
if (is_subclass_of($className, $this->name)) {
|
|
||||||
$this->subClasses[] = $className;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1869,9 +1887,10 @@ class ClassMetadataInfo implements ClassMetadata
|
|||||||
*/
|
*/
|
||||||
public function getAssociationTargetClass($assocName)
|
public function getAssociationTargetClass($assocName)
|
||||||
{
|
{
|
||||||
if (!isset($this->associationMappings[$assocName])) {
|
if ( ! isset($this->associationMappings[$assocName])) {
|
||||||
throw new \InvalidArgumentException("Association name expected, '" . $assocName ."' is not an association.");
|
throw new \InvalidArgumentException("Association name expected, '" . $assocName ."' is not an association.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->associationMappings[$assocName]['targetEntity'];
|
return $this->associationMappings[$assocName]['targetEntity'];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1895,9 +1914,7 @@ class ClassMetadataInfo implements ClassMetadata
|
|||||||
*/
|
*/
|
||||||
public function getQuotedColumnName($field, $platform)
|
public function getQuotedColumnName($field, $platform)
|
||||||
{
|
{
|
||||||
return isset($this->fieldMappings[$field]['quoted']) ?
|
return isset($this->fieldMappings[$field]['quoted']) ? $platform->quoteIdentifier($this->fieldMappings[$field]['columnName']) : $this->fieldMappings[$field]['columnName'];
|
||||||
$platform->quoteIdentifier($this->fieldMappings[$field]['columnName']) :
|
|
||||||
$this->fieldMappings[$field]['columnName'];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1909,9 +1926,7 @@ class ClassMetadataInfo implements ClassMetadata
|
|||||||
*/
|
*/
|
||||||
public function getQuotedTableName($platform)
|
public function getQuotedTableName($platform)
|
||||||
{
|
{
|
||||||
return isset($this->table['quoted']) ?
|
return isset($this->table['quoted']) ? $platform->quoteIdentifier($this->table['name']) : $this->table['name'];
|
||||||
$platform->quoteIdentifier($this->table['name']) :
|
|
||||||
$this->table['name'];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1922,8 +1937,6 @@ class ClassMetadataInfo implements ClassMetadata
|
|||||||
*/
|
*/
|
||||||
public function getQuotedJoinTableName(array $assoc, $platform)
|
public function getQuotedJoinTableName(array $assoc, $platform)
|
||||||
{
|
{
|
||||||
return isset($assoc['joinTable']['quoted'])
|
return isset($assoc['joinTable']['quoted']) ? $platform->quoteIdentifier($assoc['joinTable']['name']) : $assoc['joinTable']['name'];
|
||||||
? $platform->quoteIdentifier($assoc['joinTable']['name'])
|
|
||||||
: $assoc['joinTable']['name'];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -147,12 +147,15 @@ class AnnotationDriver implements Driver
|
|||||||
// Evaluate Entity annotation
|
// Evaluate Entity annotation
|
||||||
if (isset($classAnnotations['Doctrine\ORM\Mapping\Entity'])) {
|
if (isset($classAnnotations['Doctrine\ORM\Mapping\Entity'])) {
|
||||||
$entityAnnot = $classAnnotations['Doctrine\ORM\Mapping\Entity'];
|
$entityAnnot = $classAnnotations['Doctrine\ORM\Mapping\Entity'];
|
||||||
$metadata->setCustomRepositoryClass($entityAnnot->repositoryClass);
|
if ($entityAnnot->repositoryClass !== null) {
|
||||||
|
$metadata->setCustomRepositoryClass($entityAnnot->repositoryClass);
|
||||||
|
}
|
||||||
if ($entityAnnot->readOnly) {
|
if ($entityAnnot->readOnly) {
|
||||||
$metadata->markReadOnly();
|
$metadata->markReadOnly();
|
||||||
}
|
}
|
||||||
} else if (isset($classAnnotations['Doctrine\ORM\Mapping\MappedSuperclass'])) {
|
} else if (isset($classAnnotations['Doctrine\ORM\Mapping\MappedSuperclass'])) {
|
||||||
|
$mappedSuperclassAnnot = $classAnnotations['Doctrine\ORM\Mapping\MappedSuperclass'];
|
||||||
|
$metadata->setCustomRepositoryClass($mappedSuperclassAnnot->repositoryClass);
|
||||||
$metadata->isMappedSuperclass = true;
|
$metadata->isMappedSuperclass = true;
|
||||||
} else {
|
} else {
|
||||||
throw MappingException::classIsNotAValidEntityOrMappedSuperClass($className);
|
throw MappingException::classIsNotAValidEntityOrMappedSuperClass($className);
|
||||||
|
@ -19,7 +19,8 @@
|
|||||||
|
|
||||||
namespace Doctrine\ORM\Mapping;
|
namespace Doctrine\ORM\Mapping;
|
||||||
|
|
||||||
use Doctrine\Common\Annotations\Annotation;
|
interface Annotation {}
|
||||||
|
|
||||||
|
|
||||||
/* Annotations */
|
/* Annotations */
|
||||||
|
|
||||||
@ -27,8 +28,10 @@ use Doctrine\Common\Annotations\Annotation;
|
|||||||
* @Annotation
|
* @Annotation
|
||||||
* @Target("CLASS")
|
* @Target("CLASS")
|
||||||
*/
|
*/
|
||||||
final class Entity extends Annotation {
|
final class Entity implements Annotation {
|
||||||
|
/** @var string */
|
||||||
public $repositoryClass;
|
public $repositoryClass;
|
||||||
|
/** @var boolean */
|
||||||
public $readOnly = false;
|
public $readOnly = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,42 +39,56 @@ final class Entity extends Annotation {
|
|||||||
* @Annotation
|
* @Annotation
|
||||||
* @Target("CLASS")
|
* @Target("CLASS")
|
||||||
*/
|
*/
|
||||||
final class MappedSuperclass extends Annotation {}
|
final class MappedSuperclass implements Annotation {
|
||||||
|
/** @var string */
|
||||||
/**
|
public $repositoryClass;
|
||||||
* @Annotation
|
|
||||||
* @Target("CLASS")
|
|
||||||
*/
|
|
||||||
final class InheritanceType extends Annotation {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Annotation
|
|
||||||
* @Target("CLASS")
|
|
||||||
*/
|
|
||||||
final class DiscriminatorColumn extends Annotation {
|
|
||||||
public $name;
|
|
||||||
public $fieldName; // field name used in non-object hydration (array/scalar)
|
|
||||||
public $type;
|
|
||||||
public $length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Annotation
|
* @Annotation
|
||||||
* @Target("CLASS")
|
* @Target("CLASS")
|
||||||
*/
|
*/
|
||||||
final class DiscriminatorMap extends Annotation {}
|
final class InheritanceType implements Annotation {
|
||||||
|
/** @var string */
|
||||||
|
public $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Annotation
|
||||||
|
* @Target("CLASS")
|
||||||
|
*/
|
||||||
|
final class DiscriminatorColumn implements Annotation {
|
||||||
|
/** @var string */
|
||||||
|
public $name;
|
||||||
|
/** @var string */
|
||||||
|
public $type;
|
||||||
|
/** @var integer */
|
||||||
|
public $length;
|
||||||
|
/** @var mixed */
|
||||||
|
public $fieldName; // field name used in non-object hydration (array/scalar)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Annotation
|
||||||
|
* @Target("CLASS")
|
||||||
|
*/
|
||||||
|
final class DiscriminatorMap implements Annotation {
|
||||||
|
/** @var array<string> */
|
||||||
|
public $value;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Annotation
|
* @Annotation
|
||||||
* @Target("PROPERTY")
|
* @Target("PROPERTY")
|
||||||
*/
|
*/
|
||||||
final class Id extends Annotation {}
|
final class Id implements Annotation {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Annotation
|
* @Annotation
|
||||||
* @Target("PROPERTY")
|
* @Target("PROPERTY")
|
||||||
*/
|
*/
|
||||||
final class GeneratedValue extends Annotation {
|
final class GeneratedValue implements Annotation {
|
||||||
|
/** @var string */
|
||||||
public $strategy = 'AUTO';
|
public $strategy = 'AUTO';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,43 +96,60 @@ final class GeneratedValue extends Annotation {
|
|||||||
* @Annotation
|
* @Annotation
|
||||||
* @Target("PROPERTY")
|
* @Target("PROPERTY")
|
||||||
*/
|
*/
|
||||||
final class Version extends Annotation {}
|
final class Version implements Annotation {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Annotation
|
* @Annotation
|
||||||
* @Target({"PROPERTY","ANNOTATION"})
|
* @Target({"PROPERTY","ANNOTATION"})
|
||||||
*/
|
*/
|
||||||
final class JoinColumn extends Annotation {
|
final class JoinColumn implements Annotation {
|
||||||
|
/** @var string */
|
||||||
public $name;
|
public $name;
|
||||||
public $fieldName; // field name used in non-object hydration (array/scalar)
|
/** @var string */
|
||||||
public $referencedColumnName = 'id';
|
public $referencedColumnName = 'id';
|
||||||
|
/** @var boolean */
|
||||||
public $unique = false;
|
public $unique = false;
|
||||||
|
/** @var boolean */
|
||||||
public $nullable = true;
|
public $nullable = true;
|
||||||
|
/** @var mixed */
|
||||||
public $onDelete;
|
public $onDelete;
|
||||||
|
/** @var string */
|
||||||
public $columnDefinition;
|
public $columnDefinition;
|
||||||
|
/** @var string */
|
||||||
|
public $fieldName; // field name used in non-object hydration (array/scalar)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Annotation
|
* @Annotation
|
||||||
* @Target("PROPERTY")
|
* @Target("PROPERTY")
|
||||||
*/
|
*/
|
||||||
final class JoinColumns extends Annotation {}
|
final class JoinColumns implements Annotation {
|
||||||
|
/** @var array<Doctrine\ORM\Mapping\JoinColumn> */
|
||||||
|
public $value;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Annotation
|
* @Annotation
|
||||||
* @Target("PROPERTY")
|
* @Target("PROPERTY")
|
||||||
*/
|
*/
|
||||||
final class Column extends Annotation {
|
final class Column implements Annotation {
|
||||||
public $type = 'string';
|
/** @var string */
|
||||||
public $length;
|
|
||||||
// The precision for a decimal (exact numeric) column (Applies only for decimal column)
|
|
||||||
public $precision = 0;
|
|
||||||
// The scale for a decimal (exact numeric) column (Applies only for decimal column)
|
|
||||||
public $scale = 0;
|
|
||||||
public $unique = false;
|
|
||||||
public $nullable = false;
|
|
||||||
public $name;
|
public $name;
|
||||||
|
/** @var mixed */
|
||||||
|
public $type = 'string';
|
||||||
|
/** @var integer */
|
||||||
|
public $length;
|
||||||
|
/** @var integer */
|
||||||
|
public $precision = 0; // The precision for a decimal (exact numeric) column (Applies only for decimal column)
|
||||||
|
/** @var integer */
|
||||||
|
public $scale = 0; // The scale for a decimal (exact numeric) column (Applies only for decimal column)
|
||||||
|
/** @var boolean */
|
||||||
|
public $unique = false;
|
||||||
|
/** @var boolean */
|
||||||
|
public $nullable = false;
|
||||||
|
/** @var array */
|
||||||
public $options = array();
|
public $options = array();
|
||||||
|
/** @var string */
|
||||||
public $columnDefinition;
|
public $columnDefinition;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,12 +157,18 @@ final class Column extends Annotation {
|
|||||||
* @Annotation
|
* @Annotation
|
||||||
* @Target("PROPERTY")
|
* @Target("PROPERTY")
|
||||||
*/
|
*/
|
||||||
final class OneToOne extends Annotation {
|
final class OneToOne implements Annotation {
|
||||||
|
/** @var string */
|
||||||
public $targetEntity;
|
public $targetEntity;
|
||||||
|
/** @var string */
|
||||||
public $mappedBy;
|
public $mappedBy;
|
||||||
|
/** @var string */
|
||||||
public $inversedBy;
|
public $inversedBy;
|
||||||
|
/** @var array<string> */
|
||||||
public $cascade;
|
public $cascade;
|
||||||
|
/** @var string */
|
||||||
public $fetch = 'LAZY';
|
public $fetch = 'LAZY';
|
||||||
|
/** @var boolean */
|
||||||
public $orphanRemoval = false;
|
public $orphanRemoval = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,12 +176,18 @@ final class OneToOne extends Annotation {
|
|||||||
* @Annotation
|
* @Annotation
|
||||||
* @Target("PROPERTY")
|
* @Target("PROPERTY")
|
||||||
*/
|
*/
|
||||||
final class OneToMany extends Annotation {
|
final class OneToMany implements Annotation {
|
||||||
|
/** @var string */
|
||||||
public $mappedBy;
|
public $mappedBy;
|
||||||
|
/** @var string */
|
||||||
public $targetEntity;
|
public $targetEntity;
|
||||||
|
/** @var array<string> */
|
||||||
public $cascade;
|
public $cascade;
|
||||||
|
/** @var string */
|
||||||
public $fetch = 'LAZY';
|
public $fetch = 'LAZY';
|
||||||
|
/** @var boolean */
|
||||||
public $orphanRemoval = false;
|
public $orphanRemoval = false;
|
||||||
|
/** @var string */
|
||||||
public $indexBy;
|
public $indexBy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,10 +195,14 @@ final class OneToMany extends Annotation {
|
|||||||
* @Annotation
|
* @Annotation
|
||||||
* @Target("PROPERTY")
|
* @Target("PROPERTY")
|
||||||
*/
|
*/
|
||||||
final class ManyToOne extends Annotation {
|
final class ManyToOne implements Annotation {
|
||||||
|
/** @var string */
|
||||||
public $targetEntity;
|
public $targetEntity;
|
||||||
|
/** @var array<string> */
|
||||||
public $cascade;
|
public $cascade;
|
||||||
|
/** @var string */
|
||||||
public $fetch = 'LAZY';
|
public $fetch = 'LAZY';
|
||||||
|
/** @var string */
|
||||||
public $inversedBy;
|
public $inversedBy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,12 +210,18 @@ final class ManyToOne extends Annotation {
|
|||||||
* @Annotation
|
* @Annotation
|
||||||
* @Target("PROPERTY")
|
* @Target("PROPERTY")
|
||||||
*/
|
*/
|
||||||
final class ManyToMany extends Annotation {
|
final class ManyToMany implements Annotation {
|
||||||
|
/** @var string */
|
||||||
public $targetEntity;
|
public $targetEntity;
|
||||||
|
/** @var string */
|
||||||
public $mappedBy;
|
public $mappedBy;
|
||||||
|
/** @var string */
|
||||||
public $inversedBy;
|
public $inversedBy;
|
||||||
|
/** @var array<string> */
|
||||||
public $cascade;
|
public $cascade;
|
||||||
|
/** @var string */
|
||||||
public $fetch = 'LAZY';
|
public $fetch = 'LAZY';
|
||||||
|
/** @var string */
|
||||||
public $indexBy;
|
public $indexBy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,7 +230,8 @@ final class ManyToMany extends Annotation {
|
|||||||
* @Target("ALL")
|
* @Target("ALL")
|
||||||
* @todo check available targets
|
* @todo check available targets
|
||||||
*/
|
*/
|
||||||
final class ElementCollection extends Annotation {
|
final class ElementCollection implements Annotation {
|
||||||
|
/** @var string */
|
||||||
public $tableName;
|
public $tableName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,10 +239,14 @@ final class ElementCollection extends Annotation {
|
|||||||
* @Annotation
|
* @Annotation
|
||||||
* @Target("CLASS")
|
* @Target("CLASS")
|
||||||
*/
|
*/
|
||||||
final class Table extends Annotation {
|
final class Table implements Annotation {
|
||||||
|
/** @var string */
|
||||||
public $name;
|
public $name;
|
||||||
|
/** @var string */
|
||||||
public $schema;
|
public $schema;
|
||||||
|
/** @var array<Doctrine\ORM\Mapping\Index> */
|
||||||
public $indexes;
|
public $indexes;
|
||||||
|
/** @var array<Doctrine\ORM\Mapping\UniqueConstraint> */
|
||||||
public $uniqueConstraints;
|
public $uniqueConstraints;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,8 +254,10 @@ final class Table extends Annotation {
|
|||||||
* @Annotation
|
* @Annotation
|
||||||
* @Target("ANNOTATION")
|
* @Target("ANNOTATION")
|
||||||
*/
|
*/
|
||||||
final class UniqueConstraint extends Annotation {
|
final class UniqueConstraint implements Annotation {
|
||||||
|
/** @var string */
|
||||||
public $name;
|
public $name;
|
||||||
|
/** @var array<string> */
|
||||||
public $columns;
|
public $columns;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,8 +265,10 @@ final class UniqueConstraint extends Annotation {
|
|||||||
* @Annotation
|
* @Annotation
|
||||||
* @Target("ANNOTATION")
|
* @Target("ANNOTATION")
|
||||||
*/
|
*/
|
||||||
final class Index extends Annotation {
|
final class Index implements Annotation {
|
||||||
|
/** @var string */
|
||||||
public $name;
|
public $name;
|
||||||
|
/** @var array<string> */
|
||||||
public $columns;
|
public $columns;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,10 +276,14 @@ final class Index extends Annotation {
|
|||||||
* @Annotation
|
* @Annotation
|
||||||
* @Target("PROPERTY")
|
* @Target("PROPERTY")
|
||||||
*/
|
*/
|
||||||
final class JoinTable extends Annotation {
|
final class JoinTable implements Annotation {
|
||||||
|
/** @var string */
|
||||||
public $name;
|
public $name;
|
||||||
|
/** @var string */
|
||||||
public $schema;
|
public $schema;
|
||||||
|
/** @var array<Doctrine\ORM\Mapping\JoinColumn> */
|
||||||
public $joinColumns = array();
|
public $joinColumns = array();
|
||||||
|
/** @var array<Doctrine\ORM\Mapping\JoinColumn> */
|
||||||
public $inverseJoinColumns = array();
|
public $inverseJoinColumns = array();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,9 +291,12 @@ final class JoinTable extends Annotation {
|
|||||||
* @Annotation
|
* @Annotation
|
||||||
* @Target("PROPERTY")
|
* @Target("PROPERTY")
|
||||||
*/
|
*/
|
||||||
final class SequenceGenerator extends Annotation {
|
final class SequenceGenerator implements Annotation {
|
||||||
|
/** @var string */
|
||||||
public $sequenceName;
|
public $sequenceName;
|
||||||
|
/** @var integer */
|
||||||
public $allocationSize = 1;
|
public $allocationSize = 1;
|
||||||
|
/** @var integer */
|
||||||
public $initialValue = 1;
|
public $initialValue = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,26 +304,37 @@ final class SequenceGenerator extends Annotation {
|
|||||||
* @Annotation
|
* @Annotation
|
||||||
* @Target("CLASS")
|
* @Target("CLASS")
|
||||||
*/
|
*/
|
||||||
final class ChangeTrackingPolicy extends Annotation {}
|
final class ChangeTrackingPolicy implements Annotation {
|
||||||
|
/** @var string */
|
||||||
|
public $value;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Annotation
|
* @Annotation
|
||||||
* @Target("PROPERTY")
|
* @Target("PROPERTY")
|
||||||
*/
|
*/
|
||||||
final class OrderBy extends Annotation {}
|
final class OrderBy implements Annotation {
|
||||||
|
/** @var array<string> */
|
||||||
|
public $value;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Annotation
|
* @Annotation
|
||||||
* @Target("CLASS")
|
* @Target("CLASS")
|
||||||
*/
|
*/
|
||||||
final class NamedQueries extends Annotation {}
|
final class NamedQueries implements Annotation {
|
||||||
|
/** @var array<Doctrine\ORM\Mapping\NamedQuery> */
|
||||||
|
public $value;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Annotation
|
* @Annotation
|
||||||
* @Target("ANNOTATION")
|
* @Target("ANNOTATION")
|
||||||
*/
|
*/
|
||||||
final class NamedQuery extends Annotation {
|
final class NamedQuery implements Annotation {
|
||||||
|
/** @var string */
|
||||||
public $name;
|
public $name;
|
||||||
|
/** @var string */
|
||||||
public $query;
|
public $query;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,46 +344,46 @@ final class NamedQuery extends Annotation {
|
|||||||
* @Annotation
|
* @Annotation
|
||||||
* @Target("CLASS")
|
* @Target("CLASS")
|
||||||
*/
|
*/
|
||||||
final class HasLifecycleCallbacks extends Annotation {}
|
final class HasLifecycleCallbacks implements Annotation {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Annotation
|
* @Annotation
|
||||||
* @Target("METHOD")
|
* @Target("METHOD")
|
||||||
*/
|
*/
|
||||||
final class PrePersist extends Annotation {}
|
final class PrePersist implements Annotation {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Annotation
|
* @Annotation
|
||||||
* @Target("METHOD")
|
* @Target("METHOD")
|
||||||
*/
|
*/
|
||||||
final class PostPersist extends Annotation {}
|
final class PostPersist implements Annotation {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Annotation
|
* @Annotation
|
||||||
* @Target("METHOD")
|
* @Target("METHOD")
|
||||||
*/
|
*/
|
||||||
final class PreUpdate extends Annotation {}
|
final class PreUpdate implements Annotation {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Annotation
|
* @Annotation
|
||||||
* @Target("METHOD")
|
* @Target("METHOD")
|
||||||
*/
|
*/
|
||||||
final class PostUpdate extends Annotation {}
|
final class PostUpdate implements Annotation {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Annotation
|
* @Annotation
|
||||||
* @Target("METHOD")
|
* @Target("METHOD")
|
||||||
*/
|
*/
|
||||||
final class PreRemove extends Annotation {}
|
final class PreRemove implements Annotation {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Annotation
|
* @Annotation
|
||||||
* @Target("METHOD")
|
* @Target("METHOD")
|
||||||
*/
|
*/
|
||||||
final class PostRemove extends Annotation {}
|
final class PostRemove implements Annotation {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Annotation
|
* @Annotation
|
||||||
* @Target("METHOD")
|
* @Target("METHOD")
|
||||||
*/
|
*/
|
||||||
final class PostLoad extends Annotation {}
|
final class PostLoad implements Annotation {}
|
||||||
|
176
lib/Doctrine/ORM/Mapping/Driver/SimplifiedXmlDriver.php
Normal file
176
lib/Doctrine/ORM/Mapping/Driver/SimplifiedXmlDriver.php
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* 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.doctrine-project.org>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Doctrine\ORM\Mapping\Driver;
|
||||||
|
|
||||||
|
use Doctrine\ORM\Mapping\MappingException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XmlDriver that additionally looks for mapping information in a global file.
|
||||||
|
*
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||||
|
* @license MIT
|
||||||
|
*/
|
||||||
|
class SimplifiedXmlDriver extends XmlDriver
|
||||||
|
{
|
||||||
|
protected $_prefixes = array();
|
||||||
|
protected $_globalBasename;
|
||||||
|
protected $_classCache;
|
||||||
|
protected $_fileExtension = '.orm.xml';
|
||||||
|
|
||||||
|
public function __construct($prefixes)
|
||||||
|
{
|
||||||
|
$this->addNamespacePrefixes($prefixes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setGlobalBasename($file)
|
||||||
|
{
|
||||||
|
$this->_globalBasename = $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getGlobalBasename()
|
||||||
|
{
|
||||||
|
return $this->_globalBasename;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addNamespacePrefixes($prefixes)
|
||||||
|
{
|
||||||
|
$this->_prefixes = array_merge($this->_prefixes, $prefixes);
|
||||||
|
$this->addPaths(array_flip($prefixes));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getNamespacePrefixes()
|
||||||
|
{
|
||||||
|
return $this->_prefixes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isTransient($className)
|
||||||
|
{
|
||||||
|
if (null === $this->_classCache) {
|
||||||
|
$this->initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
// The mapping is defined in the global mapping file
|
||||||
|
if (isset($this->_classCache[$className])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->_findMappingFile($className);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} catch (MappingException $e) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAllClassNames()
|
||||||
|
{
|
||||||
|
if (null === $this->_classCache) {
|
||||||
|
$this->initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
$classes = array();
|
||||||
|
|
||||||
|
if ($this->_paths) {
|
||||||
|
foreach ((array) $this->_paths as $path) {
|
||||||
|
if (!is_dir($path)) {
|
||||||
|
throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath($path);
|
||||||
|
}
|
||||||
|
|
||||||
|
$iterator = new \RecursiveIteratorIterator(
|
||||||
|
new \RecursiveDirectoryIterator($path),
|
||||||
|
\RecursiveIteratorIterator::LEAVES_ONLY
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ($iterator as $file) {
|
||||||
|
$fileName = $file->getBasename($this->_fileExtension);
|
||||||
|
|
||||||
|
if ($fileName == $file->getBasename() || $fileName == $this->_globalBasename) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: All files found here means classes are not transient!
|
||||||
|
if (isset($this->_prefixes[$path])) {
|
||||||
|
$classes[] = $this->_prefixes[$path].'\\'.str_replace('.', '\\', $fileName);
|
||||||
|
} else {
|
||||||
|
$classes[] = str_replace('.', '\\', $fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_merge($classes, array_keys($this->_classCache));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getElement($className)
|
||||||
|
{
|
||||||
|
if (null === $this->_classCache) {
|
||||||
|
$this->initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($this->_classCache[$className])) {
|
||||||
|
$this->_classCache[$className] = parent::getElement($className);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->_classCache[$className];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function initialize()
|
||||||
|
{
|
||||||
|
$this->_classCache = array();
|
||||||
|
if (null !== $this->_globalBasename) {
|
||||||
|
foreach ($this->_paths as $path) {
|
||||||
|
if (is_file($file = $path.'/'.$this->_globalBasename.$this->_fileExtension)) {
|
||||||
|
$this->_classCache = array_merge($this->_classCache, $this->_loadMappingFile($file));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function _findMappingFile($className)
|
||||||
|
{
|
||||||
|
$defaultFileName = str_replace('\\', '.', $className).$this->_fileExtension;
|
||||||
|
foreach ($this->_paths as $path) {
|
||||||
|
if (!isset($this->_prefixes[$path])) {
|
||||||
|
if (is_file($path.DIRECTORY_SEPARATOR.$defaultFileName)) {
|
||||||
|
return $path.DIRECTORY_SEPARATOR.$defaultFileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$prefix = $this->_prefixes[$path];
|
||||||
|
|
||||||
|
if (0 !== strpos($className, $prefix.'\\')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$filename = $path.'/'.strtr(substr($className, strlen($prefix)+1), '\\', '.').$this->_fileExtension;
|
||||||
|
if (is_file($filename)) {
|
||||||
|
return $filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw MappingException::mappingFileNotFound($className, $filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw MappingException::mappingFileNotFound($className, substr($className, strrpos($className, '\\') + 1).$this->_fileExtension);
|
||||||
|
}
|
||||||
|
}
|
182
lib/Doctrine/ORM/Mapping/Driver/SimplifiedYamlDriver.php
Normal file
182
lib/Doctrine/ORM/Mapping/Driver/SimplifiedYamlDriver.php
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* 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.doctrine-project.org>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Doctrine\ORM\Mapping\Driver;
|
||||||
|
|
||||||
|
use Doctrine\ORM\Mapping\MappingException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* YamlDriver that additionally looks for mapping information in a global file.
|
||||||
|
*
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||||
|
* @license MIT
|
||||||
|
*/
|
||||||
|
class SimplifiedYamlDriver extends YamlDriver
|
||||||
|
{
|
||||||
|
protected $_prefixes = array();
|
||||||
|
protected $_globalBasename;
|
||||||
|
protected $_classCache;
|
||||||
|
protected $_fileExtension = '.orm.yml';
|
||||||
|
|
||||||
|
public function __construct($prefixes)
|
||||||
|
{
|
||||||
|
$this->addNamespacePrefixes($prefixes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setGlobalBasename($file)
|
||||||
|
{
|
||||||
|
$this->_globalBasename = $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getGlobalBasename()
|
||||||
|
{
|
||||||
|
return $this->_globalBasename;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addNamespacePrefixes($prefixes)
|
||||||
|
{
|
||||||
|
$this->_prefixes = array_merge($this->_prefixes, $prefixes);
|
||||||
|
$this->addPaths(array_flip($prefixes));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addNamespacePrefix($prefix, $path)
|
||||||
|
{
|
||||||
|
$this->_prefixes[$path] = $prefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function getNamespacePrefixes()
|
||||||
|
{
|
||||||
|
return $this->_prefixes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isTransient($className)
|
||||||
|
{
|
||||||
|
if (null === $this->_classCache) {
|
||||||
|
$this->initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
// The mapping is defined in the global mapping file
|
||||||
|
if (isset($this->_classCache[$className])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->_findMappingFile($className);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} catch (MappingException $e) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAllClassNames()
|
||||||
|
{
|
||||||
|
if (null === $this->_classCache) {
|
||||||
|
$this->initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
$classes = array();
|
||||||
|
|
||||||
|
if ($this->_paths) {
|
||||||
|
foreach ((array) $this->_paths as $path) {
|
||||||
|
if (!is_dir($path)) {
|
||||||
|
throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath($path);
|
||||||
|
}
|
||||||
|
|
||||||
|
$iterator = new \RecursiveIteratorIterator(
|
||||||
|
new \RecursiveDirectoryIterator($path),
|
||||||
|
\RecursiveIteratorIterator::LEAVES_ONLY
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ($iterator as $file) {
|
||||||
|
$fileName = $file->getBasename($this->_fileExtension);
|
||||||
|
|
||||||
|
if ($fileName == $file->getBasename() || $fileName == $this->_globalBasename) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: All files found here means classes are not transient!
|
||||||
|
if (isset($this->_prefixes[$path])) {
|
||||||
|
$classes[] = $this->_prefixes[$path].'\\'.str_replace('.', '\\', $fileName);
|
||||||
|
} else {
|
||||||
|
$classes[] = str_replace('.', '\\', $fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_merge($classes, array_keys($this->_classCache));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getElement($className)
|
||||||
|
{
|
||||||
|
if (null === $this->_classCache) {
|
||||||
|
$this->initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($this->_classCache[$className])) {
|
||||||
|
$this->_classCache[$className] = parent::getElement($className);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->_classCache[$className];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function initialize()
|
||||||
|
{
|
||||||
|
$this->_classCache = array();
|
||||||
|
if (null !== $this->_globalBasename) {
|
||||||
|
foreach ($this->_paths as $path) {
|
||||||
|
if (is_file($file = $path.'/'.$this->_globalBasename.$this->_fileExtension)) {
|
||||||
|
$this->_classCache = array_merge($this->_classCache, $this->_loadMappingFile($file));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function _findMappingFile($className)
|
||||||
|
{
|
||||||
|
$defaultFileName = str_replace('\\', '.', $className).$this->_fileExtension;
|
||||||
|
foreach ($this->_paths as $path) {
|
||||||
|
if (!isset($this->_prefixes[$path])) {
|
||||||
|
if (is_file($path.DIRECTORY_SEPARATOR.$defaultFileName)) {
|
||||||
|
return $path.DIRECTORY_SEPARATOR.$defaultFileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$prefix = $this->_prefixes[$path];
|
||||||
|
|
||||||
|
if (0 !== strpos($className, $prefix.'\\')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$filename = $path.'/'.strtr(substr($className, strlen($prefix)+1), '\\', '.').$this->_fileExtension;
|
||||||
|
if (is_file($filename)) {
|
||||||
|
return $filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw MappingException::mappingFileNotFound($className, $filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw MappingException::mappingFileNotFound($className, substr($className, strrpos($className, '\\') + 1).$this->_fileExtension);
|
||||||
|
}
|
||||||
|
}
|
@ -52,13 +52,16 @@ class XmlDriver extends AbstractFileDriver
|
|||||||
$xmlRoot = $this->getElement($className);
|
$xmlRoot = $this->getElement($className);
|
||||||
|
|
||||||
if ($xmlRoot->getName() == 'entity') {
|
if ($xmlRoot->getName() == 'entity') {
|
||||||
$metadata->setCustomRepositoryClass(
|
if (isset($xmlRoot['repository-class'])) {
|
||||||
isset($xmlRoot['repository-class']) ? (string)$xmlRoot['repository-class'] : null
|
$metadata->setCustomRepositoryClass((string)$xmlRoot['repository-class']);
|
||||||
);
|
}
|
||||||
if (isset($xmlRoot['read-only']) && $xmlRoot['read-only'] == "true") {
|
if (isset($xmlRoot['read-only']) && $xmlRoot['read-only'] == "true") {
|
||||||
$metadata->markReadOnly();
|
$metadata->markReadOnly();
|
||||||
}
|
}
|
||||||
} else if ($xmlRoot->getName() == 'mapped-superclass') {
|
} else if ($xmlRoot->getName() == 'mapped-superclass') {
|
||||||
|
$metadata->setCustomRepositoryClass(
|
||||||
|
isset($xmlRoot['repository-class']) ? (string)$xmlRoot['repository-class'] : null
|
||||||
|
);
|
||||||
$metadata->isMappedSuperclass = true;
|
$metadata->isMappedSuperclass = true;
|
||||||
} else {
|
} else {
|
||||||
throw MappingException::classIsNotAValidEntityOrMappedSuperClass($className);
|
throw MappingException::classIsNotAValidEntityOrMappedSuperClass($className);
|
||||||
|
@ -46,13 +46,16 @@ class YamlDriver extends AbstractFileDriver
|
|||||||
$element = $this->getElement($className);
|
$element = $this->getElement($className);
|
||||||
|
|
||||||
if ($element['type'] == 'entity') {
|
if ($element['type'] == 'entity') {
|
||||||
$metadata->setCustomRepositoryClass(
|
if (isset($element['repositoryClass'])) {
|
||||||
isset($element['repositoryClass']) ? $element['repositoryClass'] : null
|
$metadata->setCustomRepositoryClass($element['repositoryClass']);
|
||||||
);
|
}
|
||||||
if (isset($element['readOnly']) && $element['readOnly'] == true) {
|
if (isset($element['readOnly']) && $element['readOnly'] == true) {
|
||||||
$metadata->markReadOnly();
|
$metadata->markReadOnly();
|
||||||
}
|
}
|
||||||
} else if ($element['type'] == 'mappedSuperclass') {
|
} else if ($element['type'] == 'mappedSuperclass') {
|
||||||
|
$metadata->setCustomRepositoryClass(
|
||||||
|
isset($element['repositoryClass']) ? $element['repositoryClass'] : null
|
||||||
|
);
|
||||||
$metadata->isMappedSuperclass = true;
|
$metadata->isMappedSuperclass = true;
|
||||||
} else {
|
} else {
|
||||||
throw MappingException::classIsNotAValidEntityOrMappedSuperClass($className);
|
throw MappingException::classIsNotAValidEntityOrMappedSuperClass($className);
|
||||||
|
@ -293,4 +293,9 @@ class MappingException extends \Doctrine\ORM\ORMException
|
|||||||
"to avoid this exception from occuring."
|
"to avoid this exception from occuring."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function lifecycleCallbackMethodNotFound($className, $methodName)
|
||||||
|
{
|
||||||
|
return new self("Entity '" . $className . "' has no method '" . $methodName . "' to be registered as lifecycle callback.");
|
||||||
|
}
|
||||||
}
|
}
|
@ -130,4 +130,10 @@ class ORMException extends Exception
|
|||||||
"Unknown Entity namespace alias '$entityNamespaceAlias'."
|
"Unknown Entity namespace alias '$entityNamespaceAlias'."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function invalidEntityRepository($className)
|
||||||
|
{
|
||||||
|
return new self("Invalid repository class '".$className."'. ".
|
||||||
|
"it must be a Doctrine\ORM\EntityRepository.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,9 +65,11 @@ abstract class AbstractCollectionPersister
|
|||||||
public function delete(PersistentCollection $coll)
|
public function delete(PersistentCollection $coll)
|
||||||
{
|
{
|
||||||
$mapping = $coll->getMapping();
|
$mapping = $coll->getMapping();
|
||||||
|
|
||||||
if ( ! $mapping['isOwningSide']) {
|
if ( ! $mapping['isOwningSide']) {
|
||||||
return; // ignore inverse side
|
return; // ignore inverse side
|
||||||
}
|
}
|
||||||
|
|
||||||
$sql = $this->_getDeleteSQL($coll);
|
$sql = $this->_getDeleteSQL($coll);
|
||||||
$this->_conn->executeUpdate($sql, $this->_getDeleteSQLParameters($coll));
|
$this->_conn->executeUpdate($sql, $this->_getDeleteSQLParameters($coll));
|
||||||
}
|
}
|
||||||
@ -96,9 +98,11 @@ abstract class AbstractCollectionPersister
|
|||||||
public function update(PersistentCollection $coll)
|
public function update(PersistentCollection $coll)
|
||||||
{
|
{
|
||||||
$mapping = $coll->getMapping();
|
$mapping = $coll->getMapping();
|
||||||
|
|
||||||
if ( ! $mapping['isOwningSide']) {
|
if ( ! $mapping['isOwningSide']) {
|
||||||
return; // ignore inverse side
|
return; // ignore inverse side
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->deleteRows($coll);
|
$this->deleteRows($coll);
|
||||||
//$this->updateRows($coll);
|
//$this->updateRows($coll);
|
||||||
$this->insertRows($coll);
|
$this->insertRows($coll);
|
||||||
@ -108,6 +112,7 @@ abstract class AbstractCollectionPersister
|
|||||||
{
|
{
|
||||||
$deleteDiff = $coll->getDeleteDiff();
|
$deleteDiff = $coll->getDeleteDiff();
|
||||||
$sql = $this->_getDeleteRowSQL($coll);
|
$sql = $this->_getDeleteRowSQL($coll);
|
||||||
|
|
||||||
foreach ($deleteDiff as $element) {
|
foreach ($deleteDiff as $element) {
|
||||||
$this->_conn->executeUpdate($sql, $this->_getDeleteRowSQLParameters($coll, $element));
|
$this->_conn->executeUpdate($sql, $this->_getDeleteRowSQLParameters($coll, $element));
|
||||||
}
|
}
|
||||||
@ -120,6 +125,7 @@ abstract class AbstractCollectionPersister
|
|||||||
{
|
{
|
||||||
$insertDiff = $coll->getInsertDiff();
|
$insertDiff = $coll->getInsertDiff();
|
||||||
$sql = $this->_getInsertRowSQL($coll);
|
$sql = $this->_getInsertRowSQL($coll);
|
||||||
|
|
||||||
foreach ($insertDiff as $element) {
|
foreach ($insertDiff as $element) {
|
||||||
$this->_conn->executeUpdate($sql, $this->_getInsertRowSQLParameters($coll, $element));
|
$this->_conn->executeUpdate($sql, $this->_getInsertRowSQLParameters($coll, $element));
|
||||||
}
|
}
|
||||||
|
@ -39,10 +39,12 @@ abstract class AbstractEntityInheritancePersister extends BasicEntityPersister
|
|||||||
protected function _prepareInsertData($entity)
|
protected function _prepareInsertData($entity)
|
||||||
{
|
{
|
||||||
$data = parent::_prepareInsertData($entity);
|
$data = parent::_prepareInsertData($entity);
|
||||||
|
|
||||||
// Populate the discriminator column
|
// Populate the discriminator column
|
||||||
$discColumn = $this->_class->discriminatorColumn;
|
$discColumn = $this->_class->discriminatorColumn;
|
||||||
$this->_columnTypes[$discColumn['name']] = $discColumn['type'];
|
$this->_columnTypes[$discColumn['name']] = $discColumn['type'];
|
||||||
$data[$this->_getDiscriminatorColumnTableName()][$discColumn['name']] = $this->_class->discriminatorValue;
|
$data[$this->_getDiscriminatorColumnTableName()][$discColumn['name']] = $this->_class->discriminatorValue;
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,7 +65,7 @@ abstract class AbstractEntityInheritancePersister extends BasicEntityPersister
|
|||||||
$columnAlias = $this->_platform->getSQLResultCasing($columnName . $this->_sqlAliasCounter++);
|
$columnAlias = $this->_platform->getSQLResultCasing($columnName . $this->_sqlAliasCounter++);
|
||||||
$this->_rsm->addFieldResult($alias, $columnAlias, $field, $class->name);
|
$this->_rsm->addFieldResult($alias, $columnAlias, $field, $class->name);
|
||||||
|
|
||||||
return "$sql AS $columnAlias";
|
return $sql . ' AS ' . $columnAlias;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getSelectJoinColumnSQL($tableAlias, $joinColumnName, $className)
|
protected function getSelectJoinColumnSQL($tableAlias, $joinColumnName, $className)
|
||||||
@ -72,6 +74,6 @@ abstract class AbstractEntityInheritancePersister extends BasicEntityPersister
|
|||||||
$resultColumnName = $this->_platform->getSQLResultCasing($columnAlias);
|
$resultColumnName = $this->_platform->getSQLResultCasing($columnAlias);
|
||||||
$this->_rsm->addMetaResult('r', $resultColumnName, $joinColumnName);
|
$this->_rsm->addMetaResult('r', $resultColumnName, $joinColumnName);
|
||||||
|
|
||||||
return $tableAlias . ".$joinColumnName AS $columnAlias";
|
return $tableAlias . '.' . $joinColumnName . ' AS ' . $columnAlias;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -222,7 +222,7 @@ class BasicEntityPersister
|
|||||||
$isPostInsertId = $idGen->isPostInsertGenerator();
|
$isPostInsertId = $idGen->isPostInsertGenerator();
|
||||||
|
|
||||||
$stmt = $this->_conn->prepare($this->_getInsertSQL());
|
$stmt = $this->_conn->prepare($this->_getInsertSQL());
|
||||||
$tableName = $this->_class->table['name'];
|
$tableName = $this->_class->getTableName();
|
||||||
|
|
||||||
foreach ($this->_queuedInserts as $entity) {
|
foreach ($this->_queuedInserts as $entity) {
|
||||||
$insertData = $this->_prepareInsertData($entity);
|
$insertData = $this->_prepareInsertData($entity);
|
||||||
@ -278,11 +278,14 @@ class BasicEntityPersister
|
|||||||
protected function fetchVersionValue($versionedClass, $id)
|
protected function fetchVersionValue($versionedClass, $id)
|
||||||
{
|
{
|
||||||
$versionField = $versionedClass->versionField;
|
$versionField = $versionedClass->versionField;
|
||||||
$identifier = $versionedClass->getIdentifierColumnNames();
|
$identifier = $versionedClass->getIdentifierColumnNames();
|
||||||
$versionFieldColumnName = $versionedClass->getColumnName($versionField);
|
|
||||||
|
$versionFieldColumnName = $versionedClass->getQuotedColumnName($versionField, $this->_platform);
|
||||||
|
|
||||||
//FIXME: Order with composite keys might not be correct
|
//FIXME: Order with composite keys might not be correct
|
||||||
$sql = "SELECT " . $versionFieldColumnName . " FROM " . $versionedClass->getQuotedTableName($this->_platform)
|
$sql = 'SELECT ' . $versionFieldColumnName
|
||||||
. " WHERE " . implode(' = ? AND ', $identifier) . " = ?";
|
. ' FROM ' . $versionedClass->getQuotedTableName($this->_platform)
|
||||||
|
. ' WHERE ' . implode(' = ? AND ', $identifier) . ' = ?';
|
||||||
$value = $this->_conn->fetchColumn($sql, array_values((array)$id));
|
$value = $this->_conn->fetchColumn($sql, array_values((array)$id));
|
||||||
|
|
||||||
return Type::getType($versionedClass->fieldMappings[$versionField]['type'])->convertToPHPValue($value, $this->_platform);
|
return Type::getType($versionedClass->fieldMappings[$versionField]['type'])->convertToPHPValue($value, $this->_platform);
|
||||||
@ -305,7 +308,8 @@ class BasicEntityPersister
|
|||||||
public function update($entity)
|
public function update($entity)
|
||||||
{
|
{
|
||||||
$updateData = $this->_prepareUpdateData($entity);
|
$updateData = $this->_prepareUpdateData($entity);
|
||||||
$tableName = $this->_class->table['name'];
|
$tableName = $this->_class->getTableName();
|
||||||
|
|
||||||
if (isset($updateData[$tableName]) && $updateData[$tableName]) {
|
if (isset($updateData[$tableName]) && $updateData[$tableName]) {
|
||||||
$this->_updateTable(
|
$this->_updateTable(
|
||||||
$entity, $this->_class->getQuotedTableName($this->_platform),
|
$entity, $this->_class->getQuotedTableName($this->_platform),
|
||||||
@ -333,17 +337,17 @@ class BasicEntityPersister
|
|||||||
$set = $params = $types = array();
|
$set = $params = $types = array();
|
||||||
|
|
||||||
foreach ($updateData as $columnName => $value) {
|
foreach ($updateData as $columnName => $value) {
|
||||||
if (isset($this->_class->fieldNames[$columnName])) {
|
$set[] = (isset($this->_class->fieldNames[$columnName]))
|
||||||
$set[] = $this->_class->getQuotedColumnName($this->_class->fieldNames[$columnName], $this->_platform) . ' = ?';
|
? $this->_class->getQuotedColumnName($this->_class->fieldNames[$columnName], $this->_platform) . ' = ?'
|
||||||
} else {
|
: $columnName . ' = ?';
|
||||||
$set[] = $columnName . ' = ?';
|
|
||||||
}
|
|
||||||
$params[] = $value;
|
$params[] = $value;
|
||||||
$types[] = $this->_columnTypes[$columnName];
|
$types[] = $this->_columnTypes[$columnName];
|
||||||
}
|
}
|
||||||
|
|
||||||
$where = array();
|
$where = array();
|
||||||
$id = $this->_em->getUnitOfWork()->getEntityIdentifier($entity);
|
$id = $this->_em->getUnitOfWork()->getEntityIdentifier($entity);
|
||||||
|
|
||||||
foreach ($this->_class->identifier as $idField) {
|
foreach ($this->_class->identifier as $idField) {
|
||||||
if (isset($this->_class->associationMappings[$idField])) {
|
if (isset($this->_class->associationMappings[$idField])) {
|
||||||
$targetMapping = $this->_em->getClassMetadata($this->_class->associationMappings[$idField]['targetEntity']);
|
$targetMapping = $this->_em->getClassMetadata($this->_class->associationMappings[$idField]['targetEntity']);
|
||||||
@ -361,18 +365,21 @@ class BasicEntityPersister
|
|||||||
$versionField = $this->_class->versionField;
|
$versionField = $this->_class->versionField;
|
||||||
$versionFieldType = $this->_class->fieldMappings[$versionField]['type'];
|
$versionFieldType = $this->_class->fieldMappings[$versionField]['type'];
|
||||||
$versionColumn = $this->_class->getQuotedColumnName($versionField, $this->_platform);
|
$versionColumn = $this->_class->getQuotedColumnName($versionField, $this->_platform);
|
||||||
|
|
||||||
if ($versionFieldType == Type::INTEGER) {
|
if ($versionFieldType == Type::INTEGER) {
|
||||||
$set[] = $versionColumn . ' = ' . $versionColumn . ' + 1';
|
$set[] = $versionColumn . ' = ' . $versionColumn . ' + 1';
|
||||||
} else if ($versionFieldType == Type::DATETIME) {
|
} else if ($versionFieldType == Type::DATETIME) {
|
||||||
$set[] = $versionColumn . ' = CURRENT_TIMESTAMP';
|
$set[] = $versionColumn . ' = CURRENT_TIMESTAMP';
|
||||||
}
|
}
|
||||||
|
|
||||||
$where[] = $versionColumn;
|
$where[] = $versionColumn;
|
||||||
$params[] = $this->_class->reflFields[$versionField]->getValue($entity);
|
$params[] = $this->_class->reflFields[$versionField]->getValue($entity);
|
||||||
$types[] = $this->_class->fieldMappings[$versionField]['type'];
|
$types[] = $this->_class->fieldMappings[$versionField]['type'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$sql = "UPDATE $quotedTableName SET " . implode(', ', $set)
|
$sql = 'UPDATE ' . $quotedTableName
|
||||||
. ' WHERE ' . implode(' = ? AND ', $where) . ' = ?';
|
. ' SET ' . implode(', ', $set)
|
||||||
|
. ' WHERE ' . implode(' = ? AND ', $where) . ' = ?';
|
||||||
|
|
||||||
$result = $this->_conn->executeUpdate($sql, $params, $types);
|
$result = $this->_conn->executeUpdate($sql, $params, $types);
|
||||||
|
|
||||||
@ -398,21 +405,29 @@ class BasicEntityPersister
|
|||||||
$relatedClass = $this->_em->getClassMetadata($mapping['targetEntity']);
|
$relatedClass = $this->_em->getClassMetadata($mapping['targetEntity']);
|
||||||
$mapping = $relatedClass->associationMappings[$mapping['mappedBy']];
|
$mapping = $relatedClass->associationMappings[$mapping['mappedBy']];
|
||||||
$keys = array_keys($mapping['relationToTargetKeyColumns']);
|
$keys = array_keys($mapping['relationToTargetKeyColumns']);
|
||||||
|
|
||||||
if ($selfReferential) {
|
if ($selfReferential) {
|
||||||
$otherKeys = array_keys($mapping['relationToSourceKeyColumns']);
|
$otherKeys = array_keys($mapping['relationToSourceKeyColumns']);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$keys = array_keys($mapping['relationToSourceKeyColumns']);
|
$keys = array_keys($mapping['relationToSourceKeyColumns']);
|
||||||
|
|
||||||
if ($selfReferential) {
|
if ($selfReferential) {
|
||||||
$otherKeys = array_keys($mapping['relationToTargetKeyColumns']);
|
$otherKeys = array_keys($mapping['relationToTargetKeyColumns']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! isset($mapping['isOnDeleteCascade'])) {
|
if ( ! isset($mapping['isOnDeleteCascade'])) {
|
||||||
$this->_conn->delete($mapping['joinTable']['name'], array_combine($keys, $identifier));
|
$this->_conn->delete(
|
||||||
|
$this->_class->getQuotedJoinTableName($mapping, $this->_platform),
|
||||||
|
array_combine($keys, $identifier)
|
||||||
|
);
|
||||||
|
|
||||||
if ($selfReferential) {
|
if ($selfReferential) {
|
||||||
$this->_conn->delete($mapping['joinTable']['name'], array_combine($otherKeys, $identifier));
|
$this->_conn->delete(
|
||||||
|
$this->_class->getQuotedJoinTableName($mapping, $this->_platform),
|
||||||
|
array_combine($otherKeys, $identifier)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -463,7 +478,7 @@ class BasicEntityPersister
|
|||||||
$result = array();
|
$result = array();
|
||||||
$uow = $this->_em->getUnitOfWork();
|
$uow = $this->_em->getUnitOfWork();
|
||||||
|
|
||||||
if ($versioned = $this->_class->isVersioned) {
|
if (($versioned = $this->_class->isVersioned) != false) {
|
||||||
$versionField = $this->_class->versionField;
|
$versionField = $this->_class->versionField;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -477,6 +492,7 @@ class BasicEntityPersister
|
|||||||
|
|
||||||
if (isset($this->_class->associationMappings[$field])) {
|
if (isset($this->_class->associationMappings[$field])) {
|
||||||
$assoc = $this->_class->associationMappings[$field];
|
$assoc = $this->_class->associationMappings[$field];
|
||||||
|
|
||||||
// Only owning side of x-1 associations can have a FK column.
|
// Only owning side of x-1 associations can have a FK column.
|
||||||
if ( ! $assoc['isOwningSide'] || ! ($assoc['type'] & ClassMetadata::TO_ONE)) {
|
if ( ! $assoc['isOwningSide'] || ! ($assoc['type'] & ClassMetadata::TO_ONE)) {
|
||||||
continue;
|
continue;
|
||||||
@ -484,6 +500,7 @@ class BasicEntityPersister
|
|||||||
|
|
||||||
if ($newVal !== null) {
|
if ($newVal !== null) {
|
||||||
$oid = spl_object_hash($newVal);
|
$oid = spl_object_hash($newVal);
|
||||||
|
|
||||||
if (isset($this->_queuedInserts[$oid]) || $uow->isScheduledForInsert($newVal)) {
|
if (isset($this->_queuedInserts[$oid]) || $uow->isScheduledForInsert($newVal)) {
|
||||||
// The associated entity $newVal is not yet persisted, so we must
|
// The associated entity $newVal is not yet persisted, so we must
|
||||||
// set $newVal = null, in order to insert a null value and schedule an
|
// set $newVal = null, in order to insert a null value and schedule an
|
||||||
@ -510,6 +527,7 @@ class BasicEntityPersister
|
|||||||
} else {
|
} else {
|
||||||
$result[$owningTable][$sourceColumn] = $newValId[$targetClass->fieldNames[$targetColumn]];
|
$result[$owningTable][$sourceColumn] = $newValId[$targetClass->fieldNames[$targetColumn]];
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->_columnTypes[$sourceColumn] = $targetClass->getTypeOfColumn($targetColumn);
|
$this->_columnTypes[$sourceColumn] = $targetClass->getTypeOfColumn($targetColumn);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -518,6 +536,7 @@ class BasicEntityPersister
|
|||||||
$result[$this->getOwningTable($field)][$columnName] = $newVal;
|
$result[$this->getOwningTable($field)][$columnName] = $newVal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -548,7 +567,7 @@ class BasicEntityPersister
|
|||||||
*/
|
*/
|
||||||
public function getOwningTable($fieldName)
|
public function getOwningTable($fieldName)
|
||||||
{
|
{
|
||||||
return $this->_class->table['name'];
|
return $this->_class->getTableName();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -574,12 +593,9 @@ class BasicEntityPersister
|
|||||||
$hints[Query::HINT_REFRESH_ENTITY] = $entity;
|
$hints[Query::HINT_REFRESH_ENTITY] = $entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->_selectJoinSql) {
|
$hydrator = $this->_em->newHydrator($this->_selectJoinSql ? Query::HYDRATE_OBJECT : Query::HYDRATE_SIMPLEOBJECT);
|
||||||
$hydrator = $this->_em->newHydrator(Query::HYDRATE_OBJECT);
|
|
||||||
} else {
|
|
||||||
$hydrator = $this->_em->newHydrator(Query::HYDRATE_SIMPLEOBJECT);
|
|
||||||
}
|
|
||||||
$entities = $hydrator->hydrateAll($stmt, $this->_rsm, $hints);
|
$entities = $hydrator->hydrateAll($stmt, $this->_rsm, $hints);
|
||||||
|
|
||||||
return $entities ? $entities[0] : null;
|
return $entities ? $entities[0] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -596,7 +612,7 @@ class BasicEntityPersister
|
|||||||
*/
|
*/
|
||||||
public function loadOneToOneEntity(array $assoc, $sourceEntity, array $identifier = array())
|
public function loadOneToOneEntity(array $assoc, $sourceEntity, array $identifier = array())
|
||||||
{
|
{
|
||||||
if ($foundEntity = $this->_em->getUnitOfWork()->tryGetById($identifier, $assoc['targetEntity'])) {
|
if (($foundEntity = $this->_em->getUnitOfWork()->tryGetById($identifier, $assoc['targetEntity'])) != false) {
|
||||||
return $foundEntity;
|
return $foundEntity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -608,14 +624,17 @@ class BasicEntityPersister
|
|||||||
// Mark inverse side as fetched in the hints, otherwise the UoW would
|
// Mark inverse side as fetched in the hints, otherwise the UoW would
|
||||||
// try to load it in a separate query (remember: to-one inverse sides can not be lazy).
|
// try to load it in a separate query (remember: to-one inverse sides can not be lazy).
|
||||||
$hints = array();
|
$hints = array();
|
||||||
|
|
||||||
if ($isInverseSingleValued) {
|
if ($isInverseSingleValued) {
|
||||||
$hints['fetched'][$targetClass->name][$assoc['inversedBy']] = true;
|
$hints['fetched'][$targetClass->name][$assoc['inversedBy']] = true;
|
||||||
|
|
||||||
if ($targetClass->subClasses) {
|
if ($targetClass->subClasses) {
|
||||||
foreach ($targetClass->subClasses as $targetSubclassName) {
|
foreach ($targetClass->subClasses as $targetSubclassName) {
|
||||||
$hints['fetched'][$targetSubclassName][$assoc['inversedBy']] = true;
|
$hints['fetched'][$targetSubclassName][$assoc['inversedBy']] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* cascade read-only status
|
/* cascade read-only status
|
||||||
if ($this->_em->getUnitOfWork()->isReadOnly($sourceEntity)) {
|
if ($this->_em->getUnitOfWork()->isReadOnly($sourceEntity)) {
|
||||||
$hints[Query::HINT_READ_ONLY] = true;
|
$hints[Query::HINT_READ_ONLY] = true;
|
||||||
@ -631,19 +650,21 @@ class BasicEntityPersister
|
|||||||
} else {
|
} else {
|
||||||
$sourceClass = $this->_em->getClassMetadata($assoc['sourceEntity']);
|
$sourceClass = $this->_em->getClassMetadata($assoc['sourceEntity']);
|
||||||
$owningAssoc = $targetClass->getAssociationMapping($assoc['mappedBy']);
|
$owningAssoc = $targetClass->getAssociationMapping($assoc['mappedBy']);
|
||||||
|
|
||||||
// TRICKY: since the association is specular source and target are flipped
|
// TRICKY: since the association is specular source and target are flipped
|
||||||
foreach ($owningAssoc['targetToSourceKeyColumns'] as $sourceKeyColumn => $targetKeyColumn) {
|
foreach ($owningAssoc['targetToSourceKeyColumns'] as $sourceKeyColumn => $targetKeyColumn) {
|
||||||
if (isset($sourceClass->fieldNames[$sourceKeyColumn])) {
|
if ( ! isset($sourceClass->fieldNames[$sourceKeyColumn])) {
|
||||||
// unset the old value and set the new sql aliased value here. By definition
|
|
||||||
// unset($identifier[$targetKeyColumn] works here with how UnitOfWork::createEntity() calls this method.
|
|
||||||
$identifier[$this->_getSQLTableAlias($targetClass->name) . "." . $targetKeyColumn] =
|
|
||||||
$sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
|
|
||||||
unset($identifier[$targetKeyColumn]);
|
|
||||||
} else {
|
|
||||||
throw MappingException::joinColumnMustPointToMappedField(
|
throw MappingException::joinColumnMustPointToMappedField(
|
||||||
$sourceClass->name, $sourceKeyColumn
|
$sourceClass->name, $sourceKeyColumn
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// unset the old value and set the new sql aliased value here. By definition
|
||||||
|
// unset($identifier[$targetKeyColumn] works here with how UnitOfWork::createEntity() calls this method.
|
||||||
|
$identifier[$this->_getSQLTableAlias($targetClass->name) . "." . $targetKeyColumn] =
|
||||||
|
$sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
|
||||||
|
|
||||||
|
unset($identifier[$targetKeyColumn]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$targetEntity = $this->load($identifier, null, $assoc);
|
$targetEntity = $this->load($identifier, null, $assoc);
|
||||||
@ -675,7 +696,9 @@ class BasicEntityPersister
|
|||||||
if (isset($this->_class->lifecycleCallbacks[Events::postLoad])) {
|
if (isset($this->_class->lifecycleCallbacks[Events::postLoad])) {
|
||||||
$this->_class->invokeLifecycleCallbacks(Events::postLoad, $entity);
|
$this->_class->invokeLifecycleCallbacks(Events::postLoad, $entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
$evm = $this->_em->getEventManager();
|
$evm = $this->_em->getEventManager();
|
||||||
|
|
||||||
if ($evm->hasListeners(Events::postLoad)) {
|
if ($evm->hasListeners(Events::postLoad)) {
|
||||||
$evm->dispatchEvent(Events::postLoad, new LifecycleEventArgs($entity, $this->_em));
|
$evm->dispatchEvent(Events::postLoad, new LifecycleEventArgs($entity, $this->_em));
|
||||||
}
|
}
|
||||||
@ -697,11 +720,8 @@ class BasicEntityPersister
|
|||||||
list($params, $types) = $this->expandParameters($criteria);
|
list($params, $types) = $this->expandParameters($criteria);
|
||||||
$stmt = $this->_conn->executeQuery($sql, $params, $types);
|
$stmt = $this->_conn->executeQuery($sql, $params, $types);
|
||||||
|
|
||||||
if ($this->_selectJoinSql) {
|
$hydrator = $this->_em->newHydrator(($this->_selectJoinSql) ? Query::HYDRATE_OBJECT : Query::HYDRATE_SIMPLEOBJECT);
|
||||||
$hydrator = $this->_em->newHydrator(Query::HYDRATE_OBJECT);
|
|
||||||
} else {
|
|
||||||
$hydrator = $this->_em->newHydrator(Query::HYDRATE_SIMPLEOBJECT);
|
|
||||||
}
|
|
||||||
return $hydrator->hydrateAll($stmt, $this->_rsm, array('deferEagerLoads' => true));
|
return $hydrator->hydrateAll($stmt, $this->_rsm, array('deferEagerLoads' => true));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -717,6 +737,7 @@ class BasicEntityPersister
|
|||||||
public function getManyToManyCollection(array $assoc, $sourceEntity, $offset = null, $limit = null)
|
public function getManyToManyCollection(array $assoc, $sourceEntity, $offset = null, $limit = null)
|
||||||
{
|
{
|
||||||
$stmt = $this->getManyToManyStatement($assoc, $sourceEntity, $offset, $limit);
|
$stmt = $this->getManyToManyStatement($assoc, $sourceEntity, $offset, $limit);
|
||||||
|
|
||||||
return $this->loadArrayFromStatement($assoc, $stmt);
|
return $this->loadArrayFromStatement($assoc, $stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -725,6 +746,7 @@ class BasicEntityPersister
|
|||||||
*
|
*
|
||||||
* @param array $assoc
|
* @param array $assoc
|
||||||
* @param Doctrine\DBAL\Statement $stmt
|
* @param Doctrine\DBAL\Statement $stmt
|
||||||
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
private function loadArrayFromStatement($assoc, $stmt)
|
private function loadArrayFromStatement($assoc, $stmt)
|
||||||
@ -739,6 +761,7 @@ class BasicEntityPersister
|
|||||||
}
|
}
|
||||||
|
|
||||||
$hydrator = $this->_em->newHydrator(Query::HYDRATE_OBJECT);
|
$hydrator = $this->_em->newHydrator(Query::HYDRATE_OBJECT);
|
||||||
|
|
||||||
return $hydrator->hydrateAll($stmt, $rsm, $hints);
|
return $hydrator->hydrateAll($stmt, $rsm, $hints);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -748,6 +771,8 @@ class BasicEntityPersister
|
|||||||
* @param array $assoc
|
* @param array $assoc
|
||||||
* @param Doctrine\DBAL\Statement $stmt
|
* @param Doctrine\DBAL\Statement $stmt
|
||||||
* @param PersistentCollection $coll
|
* @param PersistentCollection $coll
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
*/
|
*/
|
||||||
private function loadCollectionFromStatement($assoc, $stmt, $coll)
|
private function loadCollectionFromStatement($assoc, $stmt, $coll)
|
||||||
{
|
{
|
||||||
@ -761,7 +786,8 @@ class BasicEntityPersister
|
|||||||
}
|
}
|
||||||
|
|
||||||
$hydrator = $this->_em->newHydrator(Query::HYDRATE_OBJECT);
|
$hydrator = $this->_em->newHydrator(Query::HYDRATE_OBJECT);
|
||||||
$hydrator->hydrateAll($stmt, $rsm, $hints);
|
|
||||||
|
return $hydrator->hydrateAll($stmt, $rsm, $hints);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -777,6 +803,7 @@ class BasicEntityPersister
|
|||||||
public function loadManyToManyCollection(array $assoc, $sourceEntity, PersistentCollection $coll)
|
public function loadManyToManyCollection(array $assoc, $sourceEntity, PersistentCollection $coll)
|
||||||
{
|
{
|
||||||
$stmt = $this->getManyToManyStatement($assoc, $sourceEntity);
|
$stmt = $this->getManyToManyStatement($assoc, $sourceEntity);
|
||||||
|
|
||||||
return $this->loadCollectionFromStatement($assoc, $stmt, $coll);
|
return $this->loadCollectionFromStatement($assoc, $stmt, $coll);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -784,12 +811,15 @@ class BasicEntityPersister
|
|||||||
{
|
{
|
||||||
$criteria = array();
|
$criteria = array();
|
||||||
$sourceClass = $this->_em->getClassMetadata($assoc['sourceEntity']);
|
$sourceClass = $this->_em->getClassMetadata($assoc['sourceEntity']);
|
||||||
|
|
||||||
if ($assoc['isOwningSide']) {
|
if ($assoc['isOwningSide']) {
|
||||||
$quotedJoinTable = $sourceClass->getQuotedJoinTableName($assoc, $this->_platform);
|
$quotedJoinTable = $sourceClass->getQuotedJoinTableName($assoc, $this->_platform);
|
||||||
|
|
||||||
foreach ($assoc['relationToSourceKeyColumns'] as $relationKeyColumn => $sourceKeyColumn) {
|
foreach ($assoc['relationToSourceKeyColumns'] as $relationKeyColumn => $sourceKeyColumn) {
|
||||||
if ($sourceClass->containsForeignIdentifier) {
|
if ($sourceClass->containsForeignIdentifier) {
|
||||||
$field = $sourceClass->getFieldForColumn($sourceKeyColumn);
|
$field = $sourceClass->getFieldForColumn($sourceKeyColumn);
|
||||||
$value = $sourceClass->reflFields[$field]->getValue($sourceEntity);
|
$value = $sourceClass->reflFields[$field]->getValue($sourceEntity);
|
||||||
|
|
||||||
if (isset($sourceClass->associationMappings[$field])) {
|
if (isset($sourceClass->associationMappings[$field])) {
|
||||||
$value = $this->_em->getUnitOfWork()->getEntityIdentifier($value);
|
$value = $this->_em->getUnitOfWork()->getEntityIdentifier($value);
|
||||||
$value = $value[$this->_em->getClassMetadata($assoc['targetEntity'])->identifier[0]];
|
$value = $value[$this->_em->getClassMetadata($assoc['targetEntity'])->identifier[0]];
|
||||||
@ -807,15 +837,18 @@ class BasicEntityPersister
|
|||||||
} else {
|
} else {
|
||||||
$owningAssoc = $this->_em->getClassMetadata($assoc['targetEntity'])->associationMappings[$assoc['mappedBy']];
|
$owningAssoc = $this->_em->getClassMetadata($assoc['targetEntity'])->associationMappings[$assoc['mappedBy']];
|
||||||
$quotedJoinTable = $sourceClass->getQuotedJoinTableName($owningAssoc, $this->_platform);
|
$quotedJoinTable = $sourceClass->getQuotedJoinTableName($owningAssoc, $this->_platform);
|
||||||
|
|
||||||
// TRICKY: since the association is inverted source and target are flipped
|
// TRICKY: since the association is inverted source and target are flipped
|
||||||
foreach ($owningAssoc['relationToTargetKeyColumns'] as $relationKeyColumn => $sourceKeyColumn) {
|
foreach ($owningAssoc['relationToTargetKeyColumns'] as $relationKeyColumn => $sourceKeyColumn) {
|
||||||
if ($sourceClass->containsForeignIdentifier) {
|
if ($sourceClass->containsForeignIdentifier) {
|
||||||
$field = $sourceClass->getFieldForColumn($sourceKeyColumn);
|
$field = $sourceClass->getFieldForColumn($sourceKeyColumn);
|
||||||
$value = $sourceClass->reflFields[$field]->getValue($sourceEntity);
|
$value = $sourceClass->reflFields[$field]->getValue($sourceEntity);
|
||||||
|
|
||||||
if (isset($sourceClass->associationMappings[$field])) {
|
if (isset($sourceClass->associationMappings[$field])) {
|
||||||
$value = $this->_em->getUnitOfWork()->getEntityIdentifier($value);
|
$value = $this->_em->getUnitOfWork()->getEntityIdentifier($value);
|
||||||
$value = $value[$this->_em->getClassMetadata($assoc['targetEntity'])->identifier[0]];
|
$value = $value[$this->_em->getClassMetadata($assoc['targetEntity'])->identifier[0]];
|
||||||
}
|
}
|
||||||
|
|
||||||
$criteria[$quotedJoinTable . "." . $relationKeyColumn] = $value;
|
$criteria[$quotedJoinTable . "." . $relationKeyColumn] = $value;
|
||||||
} else if (isset($sourceClass->fieldNames[$sourceKeyColumn])) {
|
} else if (isset($sourceClass->fieldNames[$sourceKeyColumn])) {
|
||||||
$criteria[$quotedJoinTable . "." . $relationKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
|
$criteria[$quotedJoinTable . "." . $relationKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
|
||||||
@ -829,6 +862,7 @@ class BasicEntityPersister
|
|||||||
|
|
||||||
$sql = $this->_getSelectEntitiesSQL($criteria, $assoc, 0, $limit, $offset);
|
$sql = $this->_getSelectEntitiesSQL($criteria, $assoc, 0, $limit, $offset);
|
||||||
list($params, $types) = $this->expandParameters($criteria);
|
list($params, $types) = $this->expandParameters($criteria);
|
||||||
|
|
||||||
return $this->_conn->executeQuery($sql, $params, $types);
|
return $this->_conn->executeQuery($sql, $params, $types);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -847,15 +881,14 @@ class BasicEntityPersister
|
|||||||
*/
|
*/
|
||||||
protected function _getSelectEntitiesSQL(array $criteria, $assoc = null, $lockMode = 0, $limit = null, $offset = null, array $orderBy = null)
|
protected function _getSelectEntitiesSQL(array $criteria, $assoc = null, $lockMode = 0, $limit = null, $offset = null, array $orderBy = null)
|
||||||
{
|
{
|
||||||
$joinSql = $assoc != null && $assoc['type'] == ClassMetadata::MANY_TO_MANY ?
|
$joinSql = ($assoc != null && $assoc['type'] == ClassMetadata::MANY_TO_MANY) ? $this->_getSelectManyToManyJoinSQL($assoc) : '';
|
||||||
$this->_getSelectManyToManyJoinSQL($assoc) : '';
|
|
||||||
|
|
||||||
$conditionSql = $this->_getSelectConditionSQL($criteria, $assoc);
|
$conditionSql = $this->_getSelectConditionSQL($criteria, $assoc);
|
||||||
|
|
||||||
$orderBy = ($assoc !== null && isset($assoc['orderBy'])) ? $assoc['orderBy'] : $orderBy;
|
$orderBy = ($assoc !== null && isset($assoc['orderBy'])) ? $assoc['orderBy'] : $orderBy;
|
||||||
$orderBySql = $orderBy ? $this->_getOrderBySQL($orderBy, $this->_getSQLTableAlias($this->_class->name)) : '';
|
$orderBySql = $orderBy ? $this->_getOrderBySQL($orderBy, $this->_getSQLTableAlias($this->_class->name)) : '';
|
||||||
|
|
||||||
$lockSql = '';
|
$lockSql = '';
|
||||||
|
|
||||||
if ($lockMode == LockMode::PESSIMISTIC_READ) {
|
if ($lockMode == LockMode::PESSIMISTIC_READ) {
|
||||||
$lockSql = ' ' . $this->_platform->getReadLockSql();
|
$lockSql = ' ' . $this->_platform->getReadLockSql();
|
||||||
} else if ($lockMode == LockMode::PESSIMISTIC_WRITE) {
|
} else if ($lockMode == LockMode::PESSIMISTIC_WRITE) {
|
||||||
@ -890,6 +923,7 @@ class BasicEntityPersister
|
|||||||
protected final function _getOrderBySQL(array $orderBy, $baseTableAlias)
|
protected final function _getOrderBySQL(array $orderBy, $baseTableAlias)
|
||||||
{
|
{
|
||||||
$orderBySql = '';
|
$orderBySql = '';
|
||||||
|
|
||||||
foreach ($orderBy as $fieldName => $orientation) {
|
foreach ($orderBy as $fieldName => $orientation) {
|
||||||
if ( ! isset($this->_class->fieldMappings[$fieldName])) {
|
if ( ! isset($this->_class->fieldMappings[$fieldName])) {
|
||||||
throw ORMException::unrecognizedField($fieldName);
|
throw ORMException::unrecognizedField($fieldName);
|
||||||
@ -900,6 +934,7 @@ class BasicEntityPersister
|
|||||||
: $baseTableAlias;
|
: $baseTableAlias;
|
||||||
|
|
||||||
$columnName = $this->_class->getQuotedColumnName($fieldName, $this->_platform);
|
$columnName = $this->_class->getQuotedColumnName($fieldName, $this->_platform);
|
||||||
|
|
||||||
$orderBySql .= $orderBySql ? ', ' : ' ORDER BY ';
|
$orderBySql .= $orderBySql ? ', ' : ' ORDER BY ';
|
||||||
$orderBySql .= $tableAlias . '.' . $columnName . ' ' . $orientation;
|
$orderBySql .= $tableAlias . '.' . $columnName . ' ' . $orientation;
|
||||||
}
|
}
|
||||||
@ -932,20 +967,25 @@ class BasicEntityPersister
|
|||||||
// Add regular columns to select list
|
// Add regular columns to select list
|
||||||
foreach ($this->_class->fieldNames as $field) {
|
foreach ($this->_class->fieldNames as $field) {
|
||||||
if ($columnList) $columnList .= ', ';
|
if ($columnList) $columnList .= ', ';
|
||||||
|
|
||||||
$columnList .= $this->_getSelectColumnSQL($field, $this->_class);
|
$columnList .= $this->_getSelectColumnSQL($field, $this->_class);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->_selectJoinSql = '';
|
$this->_selectJoinSql = '';
|
||||||
$eagerAliasCounter = 0;
|
$eagerAliasCounter = 0;
|
||||||
|
|
||||||
foreach ($this->_class->associationMappings as $assocField => $assoc) {
|
foreach ($this->_class->associationMappings as $assocField => $assoc) {
|
||||||
$assocColumnSQL = $this->_getSelectColumnAssociationSQL($assocField, $assoc, $this->_class);
|
$assocColumnSQL = $this->_getSelectColumnAssociationSQL($assocField, $assoc, $this->_class);
|
||||||
|
|
||||||
if ($assocColumnSQL) {
|
if ($assocColumnSQL) {
|
||||||
if ($columnList) $columnList .= ', ';
|
if ($columnList) $columnList .= ', ';
|
||||||
|
|
||||||
$columnList .= $assocColumnSQL;
|
$columnList .= $assocColumnSQL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($assoc['type'] & ClassMetadata::TO_ONE && ($assoc['fetch'] == ClassMetadata::FETCH_EAGER || !$assoc['isOwningSide'])) {
|
if ($assoc['type'] & ClassMetadata::TO_ONE && ($assoc['fetch'] == ClassMetadata::FETCH_EAGER || !$assoc['isOwningSide'])) {
|
||||||
$eagerEntity = $this->_em->getClassMetadata($assoc['targetEntity']);
|
$eagerEntity = $this->_em->getClassMetadata($assoc['targetEntity']);
|
||||||
|
|
||||||
if ($eagerEntity->inheritanceType != ClassMetadata::INHERITANCE_TYPE_NONE) {
|
if ($eagerEntity->inheritanceType != ClassMetadata::INHERITANCE_TYPE_NONE) {
|
||||||
continue; // now this is why you shouldn't use inheritance
|
continue; // now this is why you shouldn't use inheritance
|
||||||
}
|
}
|
||||||
@ -955,41 +995,48 @@ class BasicEntityPersister
|
|||||||
|
|
||||||
foreach ($eagerEntity->fieldNames AS $field) {
|
foreach ($eagerEntity->fieldNames AS $field) {
|
||||||
if ($columnList) $columnList .= ', ';
|
if ($columnList) $columnList .= ', ';
|
||||||
|
|
||||||
$columnList .= $this->_getSelectColumnSQL($field, $eagerEntity, $assocAlias);
|
$columnList .= $this->_getSelectColumnSQL($field, $eagerEntity, $assocAlias);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($eagerEntity->associationMappings as $assoc2Field => $assoc2) {
|
foreach ($eagerEntity->associationMappings as $assoc2Field => $assoc2) {
|
||||||
$assoc2ColumnSQL = $this->_getSelectColumnAssociationSQL($assoc2Field, $assoc2, $eagerEntity, $assocAlias);
|
$assoc2ColumnSQL = $this->_getSelectColumnAssociationSQL($assoc2Field, $assoc2, $eagerEntity, $assocAlias);
|
||||||
|
|
||||||
if ($assoc2ColumnSQL) {
|
if ($assoc2ColumnSQL) {
|
||||||
if ($columnList) $columnList .= ', ';
|
if ($columnList) $columnList .= ', ';
|
||||||
$columnList .= $assoc2ColumnSQL;
|
$columnList .= $assoc2ColumnSQL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->_selectJoinSql .= ' LEFT JOIN'; // TODO: Inner join when all join columns are NOT nullable.
|
$this->_selectJoinSql .= ' LEFT JOIN'; // TODO: Inner join when all join columns are NOT nullable.
|
||||||
$first = true;
|
$first = true;
|
||||||
|
|
||||||
if ($assoc['isOwningSide']) {
|
if ($assoc['isOwningSide']) {
|
||||||
$this->_selectJoinSql .= ' ' . $eagerEntity->table['name'] . ' ' . $this->_getSQLTableAlias($eagerEntity->name, $assocAlias) .' ON ';
|
$this->_selectJoinSql .= ' ' . $eagerEntity->getQuotedTableName($this->_platform) . ' ' . $this->_getSQLTableAlias($eagerEntity->name, $assocAlias) .' ON ';
|
||||||
|
|
||||||
foreach ($assoc['sourceToTargetKeyColumns'] AS $sourceCol => $targetCol) {
|
foreach ($assoc['sourceToTargetKeyColumns'] AS $sourceCol => $targetCol) {
|
||||||
if (!$first) {
|
if ( ! $first) {
|
||||||
$this->_selectJoinSql .= ' AND ';
|
$this->_selectJoinSql .= ' AND ';
|
||||||
}
|
}
|
||||||
$this->_selectJoinSql .= $this->_getSQLTableAlias($assoc['sourceEntity']) . '.'.$sourceCol.' = ' .
|
|
||||||
$this->_getSQLTableAlias($assoc['targetEntity'], $assocAlias) . '.'.$targetCol.' ';
|
$this->_selectJoinSql .= $this->_getSQLTableAlias($assoc['sourceEntity']) . '.' . $sourceCol . ' = '
|
||||||
|
. $this->_getSQLTableAlias($assoc['targetEntity'], $assocAlias) . '.' . $targetCol . ' ';
|
||||||
$first = false;
|
$first = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$eagerEntity = $this->_em->getClassMetadata($assoc['targetEntity']);
|
$eagerEntity = $this->_em->getClassMetadata($assoc['targetEntity']);
|
||||||
$owningAssoc = $eagerEntity->getAssociationMapping($assoc['mappedBy']);
|
$owningAssoc = $eagerEntity->getAssociationMapping($assoc['mappedBy']);
|
||||||
|
|
||||||
$this->_selectJoinSql .= ' ' . $eagerEntity->table['name'] . ' ' . $this->_getSQLTableAlias($eagerEntity->name, $assocAlias) .' ON ';
|
$this->_selectJoinSql .= ' ' . $eagerEntity->getQuotedTableName($this->_platform) . ' '
|
||||||
|
. $this->_getSQLTableAlias($eagerEntity->name, $assocAlias) . ' ON ';
|
||||||
|
|
||||||
foreach ($owningAssoc['sourceToTargetKeyColumns'] AS $sourceCol => $targetCol) {
|
foreach ($owningAssoc['sourceToTargetKeyColumns'] AS $sourceCol => $targetCol) {
|
||||||
if (!$first) {
|
if ( ! $first) {
|
||||||
$this->_selectJoinSql .= ' AND ';
|
$this->_selectJoinSql .= ' AND ';
|
||||||
}
|
}
|
||||||
$this->_selectJoinSql .= $this->_getSQLTableAlias($owningAssoc['sourceEntity'], $assocAlias) . '.'.$sourceCol.' = ' .
|
|
||||||
$this->_getSQLTableAlias($owningAssoc['targetEntity']) . '.' . $targetCol . ' ';
|
$this->_selectJoinSql .= $this->_getSQLTableAlias($owningAssoc['sourceEntity'], $assocAlias) . '.' . $sourceCol . ' = '
|
||||||
|
. $this->_getSQLTableAlias($owningAssoc['targetEntity']) . '.' . $targetCol . ' ';
|
||||||
$first = false;
|
$first = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1001,19 +1048,32 @@ class BasicEntityPersister
|
|||||||
return $this->_selectColumnListSql;
|
return $this->_selectColumnListSql;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the SQL join fragment used when selecting entities from an association.
|
||||||
|
*
|
||||||
|
* @param string $field
|
||||||
|
* @param array $assoc
|
||||||
|
* @param ClassMetadata $class
|
||||||
|
* @param string $alias
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
protected function _getSelectColumnAssociationSQL($field, $assoc, ClassMetadata $class, $alias = 'r')
|
protected function _getSelectColumnAssociationSQL($field, $assoc, ClassMetadata $class, $alias = 'r')
|
||||||
{
|
{
|
||||||
$columnList = '';
|
$columnList = '';
|
||||||
|
|
||||||
if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) {
|
if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) {
|
||||||
foreach ($assoc['targetToSourceKeyColumns'] as $srcColumn) {
|
foreach ($assoc['targetToSourceKeyColumns'] as $srcColumn) {
|
||||||
if ($columnList) $columnList .= ', ';
|
if ($columnList) $columnList .= ', ';
|
||||||
|
|
||||||
$columnAlias = $srcColumn . $this->_sqlAliasCounter++;
|
$columnAlias = $srcColumn . $this->_sqlAliasCounter++;
|
||||||
$columnList .= $this->_getSQLTableAlias($class->name, ($alias == 'r' ? '' : $alias) ) . ".$srcColumn AS $columnAlias";
|
$columnList .= $this->_getSQLTableAlias($class->name, ($alias == 'r' ? '' : $alias) )
|
||||||
|
. '.' . $srcColumn . ' AS ' . $columnAlias;
|
||||||
$resultColumnName = $this->_platform->getSQLResultCasing($columnAlias);
|
$resultColumnName = $this->_platform->getSQLResultCasing($columnAlias);
|
||||||
$this->_rsm->addMetaResult($alias, $this->_platform->getSQLResultCasing($columnAlias), $srcColumn, isset($assoc['id']) && $assoc['id'] === true);
|
$this->_rsm->addMetaResult($alias, $this->_platform->getSQLResultCasing($columnAlias), $srcColumn, isset($assoc['id']) && $assoc['id'] === true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $columnList;
|
return $columnList;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1035,23 +1095,22 @@ class BasicEntityPersister
|
|||||||
}
|
}
|
||||||
|
|
||||||
$joinTableName = $this->_class->getQuotedJoinTableName($owningAssoc, $this->_platform);
|
$joinTableName = $this->_class->getQuotedJoinTableName($owningAssoc, $this->_platform);
|
||||||
|
|
||||||
$joinSql = '';
|
$joinSql = '';
|
||||||
|
|
||||||
foreach ($joinClauses as $joinTableColumn => $sourceColumn) {
|
foreach ($joinClauses as $joinTableColumn => $sourceColumn) {
|
||||||
if ($joinSql != '') $joinSql .= ' AND ';
|
if ($joinSql != '') $joinSql .= ' AND ';
|
||||||
|
|
||||||
if ($this->_class->containsForeignIdentifier && !isset($this->_class->fieldNames[$sourceColumn])) {
|
if ($this->_class->containsForeignIdentifier && ! isset($this->_class->fieldNames[$sourceColumn])) {
|
||||||
$quotedColumn = $sourceColumn; // join columns cannot be quoted
|
$quotedColumn = $sourceColumn; // join columns cannot be quoted
|
||||||
} else {
|
} else {
|
||||||
$quotedColumn = $this->_class->getQuotedColumnName($this->_class->fieldNames[$sourceColumn], $this->_platform);
|
$quotedColumn = $this->_class->getQuotedColumnName($this->_class->fieldNames[$sourceColumn], $this->_platform);
|
||||||
}
|
}
|
||||||
|
|
||||||
$joinSql .= $this->_getSQLTableAlias($this->_class->name) .
|
$joinSql .= $this->_getSQLTableAlias($this->_class->name) . '.' . $quotedColumn . ' = '
|
||||||
'.' . $quotedColumn . ' = '
|
. $joinTableName . '.' . $joinTableColumn;
|
||||||
. $joinTableName . '.' . $joinTableColumn;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return " INNER JOIN $joinTableName ON $joinSql";
|
return ' INNER JOIN ' . $joinTableName . ' ON ' . $joinSql;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1064,21 +1123,23 @@ class BasicEntityPersister
|
|||||||
if ($this->_insertSql === null) {
|
if ($this->_insertSql === null) {
|
||||||
$insertSql = '';
|
$insertSql = '';
|
||||||
$columns = $this->_getInsertColumnList();
|
$columns = $this->_getInsertColumnList();
|
||||||
|
|
||||||
if (empty($columns)) {
|
if (empty($columns)) {
|
||||||
$insertSql = $this->_platform->getEmptyIdentityInsertSQL(
|
$insertSql = $this->_platform->getEmptyIdentityInsertSQL(
|
||||||
$this->_class->getQuotedTableName($this->_platform),
|
$this->_class->getQuotedTableName($this->_platform),
|
||||||
$this->_class->getQuotedColumnName($this->_class->identifier[0], $this->_platform)
|
$this->_class->getQuotedColumnName($this->_class->identifier[0], $this->_platform)
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
$columns = array_unique($columns);
|
$columns = array_unique($columns);
|
||||||
$values = array_fill(0, count($columns), '?');
|
$values = array_fill(0, count($columns), '?');
|
||||||
|
|
||||||
$insertSql = 'INSERT INTO ' . $this->_class->getQuotedTableName($this->_platform)
|
$insertSql = 'INSERT INTO ' . $this->_class->getQuotedTableName($this->_platform)
|
||||||
. ' (' . implode(', ', $columns) . ') '
|
. ' (' . implode(', ', $columns) . ') VALUES (' . implode(', ', $values) . ')';
|
||||||
. 'VALUES (' . implode(', ', $values) . ')';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->_insertSql = $insertSql;
|
$this->_insertSql = $insertSql;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->_insertSql;
|
return $this->_insertSql;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1093,19 +1154,21 @@ class BasicEntityPersister
|
|||||||
protected function _getInsertColumnList()
|
protected function _getInsertColumnList()
|
||||||
{
|
{
|
||||||
$columns = array();
|
$columns = array();
|
||||||
|
|
||||||
foreach ($this->_class->reflFields as $name => $field) {
|
foreach ($this->_class->reflFields as $name => $field) {
|
||||||
if ($this->_class->isVersioned && $this->_class->versionField == $name) {
|
if ($this->_class->isVersioned && $this->_class->versionField == $name) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($this->_class->associationMappings[$name])) {
|
if (isset($this->_class->associationMappings[$name])) {
|
||||||
$assoc = $this->_class->associationMappings[$name];
|
$assoc = $this->_class->associationMappings[$name];
|
||||||
|
|
||||||
if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) {
|
if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) {
|
||||||
foreach ($assoc['targetToSourceKeyColumns'] as $sourceCol) {
|
foreach ($assoc['targetToSourceKeyColumns'] as $sourceCol) {
|
||||||
$columns[] = $sourceCol;
|
$columns[] = $sourceCol;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if ($this->_class->generatorType != ClassMetadata::GENERATOR_TYPE_IDENTITY ||
|
} else if ($this->_class->generatorType != ClassMetadata::GENERATOR_TYPE_IDENTITY || $this->_class->identifier[0] != $name) {
|
||||||
$this->_class->identifier[0] != $name) {
|
|
||||||
$columns[] = $this->_class->getQuotedColumnName($name, $this->_platform);
|
$columns[] = $this->_class->getQuotedColumnName($name, $this->_platform);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1124,11 +1187,13 @@ class BasicEntityPersister
|
|||||||
protected function _getSelectColumnSQL($field, ClassMetadata $class, $alias = 'r')
|
protected function _getSelectColumnSQL($field, ClassMetadata $class, $alias = 'r')
|
||||||
{
|
{
|
||||||
$columnName = $class->columnNames[$field];
|
$columnName = $class->columnNames[$field];
|
||||||
$sql = $this->_getSQLTableAlias($class->name, $alias == 'r' ? '' : $alias) . '.' . $class->getQuotedColumnName($field, $this->_platform);
|
$sql = $this->_getSQLTableAlias($class->name, $alias == 'r' ? '' : $alias)
|
||||||
|
. '.' . $class->getQuotedColumnName($field, $this->_platform);
|
||||||
$columnAlias = $this->_platform->getSQLResultCasing($columnName . $this->_sqlAliasCounter++);
|
$columnAlias = $this->_platform->getSQLResultCasing($columnName . $this->_sqlAliasCounter++);
|
||||||
|
|
||||||
$this->_rsm->addFieldResult($alias, $columnAlias, $field);
|
$this->_rsm->addFieldResult($alias, $columnAlias, $field);
|
||||||
|
|
||||||
return "$sql AS $columnAlias";
|
return $sql . ' AS ' . $columnAlias;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1141,15 +1206,17 @@ class BasicEntityPersister
|
|||||||
protected function _getSQLTableAlias($className, $assocName = '')
|
protected function _getSQLTableAlias($className, $assocName = '')
|
||||||
{
|
{
|
||||||
if ($assocName) {
|
if ($assocName) {
|
||||||
$className .= '#'.$assocName;
|
$className .= '#' . $assocName;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($this->_sqlTableAliases[$className])) {
|
if (isset($this->_sqlTableAliases[$className])) {
|
||||||
return $this->_sqlTableAliases[$className];
|
return $this->_sqlTableAliases[$className];
|
||||||
}
|
}
|
||||||
|
|
||||||
$tableAlias = 't' . $this->_sqlAliasCounter++;
|
$tableAlias = 't' . $this->_sqlAliasCounter++;
|
||||||
|
|
||||||
$this->_sqlTableAliases[$className] = $tableAlias;
|
$this->_sqlTableAliases[$className] = $tableAlias;
|
||||||
|
|
||||||
return $tableAlias;
|
return $tableAlias;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1173,7 +1240,9 @@ class BasicEntityPersister
|
|||||||
$sql = 'SELECT 1 '
|
$sql = 'SELECT 1 '
|
||||||
. $this->_platform->appendLockHint($this->getLockTablesSql(), $lockMode)
|
. $this->_platform->appendLockHint($this->getLockTablesSql(), $lockMode)
|
||||||
. ($conditionSql ? ' WHERE ' . $conditionSql : '') . ' ' . $lockSql;
|
. ($conditionSql ? ' WHERE ' . $conditionSql : '') . ' ' . $lockSql;
|
||||||
|
|
||||||
list($params, $types) = $this->expandParameters($criteria);
|
list($params, $types) = $this->expandParameters($criteria);
|
||||||
|
|
||||||
$stmt = $this->_conn->executeQuery($sql, $params, $types);
|
$stmt = $this->_conn->executeQuery($sql, $params, $types);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1185,7 +1254,7 @@ class BasicEntityPersister
|
|||||||
protected function getLockTablesSql()
|
protected function getLockTablesSql()
|
||||||
{
|
{
|
||||||
return 'FROM ' . $this->_class->getQuotedTableName($this->_platform) . ' '
|
return 'FROM ' . $this->_class->getQuotedTableName($this->_platform) . ' '
|
||||||
. $this->_getSQLTableAlias($this->_class->name);
|
. $this->_getSQLTableAlias($this->_class->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1202,28 +1271,26 @@ class BasicEntityPersister
|
|||||||
protected function _getSelectConditionSQL(array $criteria, $assoc = null)
|
protected function _getSelectConditionSQL(array $criteria, $assoc = null)
|
||||||
{
|
{
|
||||||
$conditionSql = '';
|
$conditionSql = '';
|
||||||
|
|
||||||
foreach ($criteria as $field => $value) {
|
foreach ($criteria as $field => $value) {
|
||||||
$conditionSql .= $conditionSql ? ' AND ' : '';
|
$conditionSql .= $conditionSql ? ' AND ' : '';
|
||||||
|
|
||||||
if (isset($this->_class->columnNames[$field])) {
|
if (isset($this->_class->columnNames[$field])) {
|
||||||
if (isset($this->_class->fieldMappings[$field]['inherited'])) {
|
$className = (isset($this->_class->fieldMappings[$field]['inherited']))
|
||||||
$conditionSql .= $this->_getSQLTableAlias($this->_class->fieldMappings[$field]['inherited']) . '.';
|
? $this->_class->fieldMappings[$field]['inherited']
|
||||||
} else {
|
: $this->_class->name;
|
||||||
$conditionSql .= $this->_getSQLTableAlias($this->_class->name) . '.';
|
|
||||||
}
|
$conditionSql .= $this->_getSQLTableAlias($className) . '.' . $this->_class->getQuotedColumnName($field, $this->_platform);
|
||||||
$conditionSql .= $this->_class->getQuotedColumnName($field, $this->_platform);
|
|
||||||
} else if (isset($this->_class->associationMappings[$field])) {
|
} else if (isset($this->_class->associationMappings[$field])) {
|
||||||
if (!$this->_class->associationMappings[$field]['isOwningSide']) {
|
if ( ! $this->_class->associationMappings[$field]['isOwningSide']) {
|
||||||
throw ORMException::invalidFindByInverseAssociation($this->_class->name, $field);
|
throw ORMException::invalidFindByInverseAssociation($this->_class->name, $field);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($this->_class->associationMappings[$field]['inherited'])) {
|
|
||||||
$conditionSql .= $this->_getSQLTableAlias($this->_class->associationMappings[$field]['inherited']) . '.';
|
|
||||||
} else {
|
|
||||||
$conditionSql .= $this->_getSQLTableAlias($this->_class->name) . '.';
|
|
||||||
}
|
|
||||||
|
|
||||||
$conditionSql .= $this->_class->associationMappings[$field]['joinColumns'][0]['name'];
|
$className = (isset($this->_class->associationMappings[$field]['inherited']))
|
||||||
|
? $this->_class->associationMappings[$field]['inherited']
|
||||||
|
: $this->_class->name;
|
||||||
|
|
||||||
|
$conditionSql .= $this->_getSQLTableAlias($className) . '.' . $this->_class->associationMappings[$field]['joinColumns'][0]['name'];
|
||||||
} else if ($assoc !== null && strpos($field, " ") === false && strpos($field, "(") === false) {
|
} else if ($assoc !== null && strpos($field, " ") === false && strpos($field, "(") === false) {
|
||||||
// very careless developers could potentially open up this normally hidden api for userland attacks,
|
// very careless developers could potentially open up this normally hidden api for userland attacks,
|
||||||
// therefore checking for spaces and function calls which are not allowed.
|
// therefore checking for spaces and function calls which are not allowed.
|
||||||
@ -1251,6 +1318,7 @@ class BasicEntityPersister
|
|||||||
public function getOneToManyCollection(array $assoc, $sourceEntity, $offset = null, $limit = null)
|
public function getOneToManyCollection(array $assoc, $sourceEntity, $offset = null, $limit = null)
|
||||||
{
|
{
|
||||||
$stmt = $this->getOneToManyStatement($assoc, $sourceEntity, $offset, $limit);
|
$stmt = $this->getOneToManyStatement($assoc, $sourceEntity, $offset, $limit);
|
||||||
|
|
||||||
return $this->loadArrayFromStatement($assoc, $stmt);
|
return $this->loadArrayFromStatement($assoc, $stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1266,7 +1334,8 @@ class BasicEntityPersister
|
|||||||
public function loadOneToManyCollection(array $assoc, $sourceEntity, PersistentCollection $coll)
|
public function loadOneToManyCollection(array $assoc, $sourceEntity, PersistentCollection $coll)
|
||||||
{
|
{
|
||||||
$stmt = $this->getOneToManyStatement($assoc, $sourceEntity);
|
$stmt = $this->getOneToManyStatement($assoc, $sourceEntity);
|
||||||
$this->loadCollectionFromStatement($assoc, $stmt, $coll);
|
|
||||||
|
return $this->loadCollectionFromStatement($assoc, $stmt, $coll);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1284,18 +1353,18 @@ class BasicEntityPersister
|
|||||||
$owningAssoc = $this->_class->associationMappings[$assoc['mappedBy']];
|
$owningAssoc = $this->_class->associationMappings[$assoc['mappedBy']];
|
||||||
$sourceClass = $this->_em->getClassMetadata($assoc['sourceEntity']);
|
$sourceClass = $this->_em->getClassMetadata($assoc['sourceEntity']);
|
||||||
|
|
||||||
$tableAlias = isset($owningAssoc['inherited']) ?
|
$tableAlias = $this->_getSQLTableAlias(isset($owningAssoc['inherited']) ? $owningAssoc['inherited'] : $this->_class->name);
|
||||||
$this->_getSQLTableAlias($owningAssoc['inherited'])
|
|
||||||
: $this->_getSQLTableAlias($this->_class->name);
|
|
||||||
|
|
||||||
foreach ($owningAssoc['targetToSourceKeyColumns'] as $sourceKeyColumn => $targetKeyColumn) {
|
foreach ($owningAssoc['targetToSourceKeyColumns'] as $sourceKeyColumn => $targetKeyColumn) {
|
||||||
if ($sourceClass->containsForeignIdentifier) {
|
if ($sourceClass->containsForeignIdentifier) {
|
||||||
$field = $sourceClass->getFieldForColumn($sourceKeyColumn);
|
$field = $sourceClass->getFieldForColumn($sourceKeyColumn);
|
||||||
$value = $sourceClass->reflFields[$field]->getValue($sourceEntity);
|
$value = $sourceClass->reflFields[$field]->getValue($sourceEntity);
|
||||||
|
|
||||||
if (isset($sourceClass->associationMappings[$field])) {
|
if (isset($sourceClass->associationMappings[$field])) {
|
||||||
$value = $this->_em->getUnitOfWork()->getEntityIdentifier($value);
|
$value = $this->_em->getUnitOfWork()->getEntityIdentifier($value);
|
||||||
$value = $value[$this->_em->getClassMetadata($assoc['targetEntity'])->identifier[0]];
|
$value = $value[$this->_em->getClassMetadata($assoc['targetEntity'])->identifier[0]];
|
||||||
}
|
}
|
||||||
|
|
||||||
$criteria[$tableAlias . "." . $targetKeyColumn] = $value;
|
$criteria[$tableAlias . "." . $targetKeyColumn] = $value;
|
||||||
} else {
|
} else {
|
||||||
$criteria[$tableAlias . "." . $targetKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
|
$criteria[$tableAlias . "." . $targetKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
|
||||||
@ -1424,23 +1493,25 @@ class BasicEntityPersister
|
|||||||
public function exists($entity, array $extraConditions = array())
|
public function exists($entity, array $extraConditions = array())
|
||||||
{
|
{
|
||||||
$criteria = $this->_class->getIdentifierValues($entity);
|
$criteria = $this->_class->getIdentifierValues($entity);
|
||||||
|
|
||||||
if ($extraConditions) {
|
if ($extraConditions) {
|
||||||
$criteria = array_merge($criteria, $extraConditions);
|
$criteria = array_merge($criteria, $extraConditions);
|
||||||
}
|
}
|
||||||
|
|
||||||
$alias = $this->_getSQLTableAlias($this->_class->name);
|
$alias = $this->_getSQLTableAlias($this->_class->name);
|
||||||
|
|
||||||
|
$sql = 'SELECT 1'
|
||||||
$sql = 'SELECT 1 FROM ' . $this->_class->getQuotedTableName($this->_platform)
|
. ' FROM ' . $this->_class->getQuotedTableName($this->_platform) . ' ' . $alias
|
||||||
. ' ' . $alias
|
. ' WHERE ' . $this->_getSelectConditionSQL($criteria);
|
||||||
. ' WHERE ' . $this->_getSelectConditionSQL($criteria);
|
|
||||||
|
|
||||||
$filterSql = $this->generateFilterConditionSQL($this->_class, $alias);
|
$filterSql = $this->generateFilterConditionSQL($this->_class, $alias);
|
||||||
if('' !== $filterSql) {
|
if('' !== $filterSql) {
|
||||||
$sql .= ' AND ' . $filterSql;
|
$sql .= ' AND ' . $filterSql;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (bool) $this->_conn->fetchColumn($sql, array_values($criteria));
|
list($params, $types) = $this->expandParameters($criteria);
|
||||||
|
|
||||||
|
return (bool) $this->_conn->fetchColumn($sql, $params);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function generateFilterConditionSQL(ClassMetadata $targetEntity, $targetTableAlias)
|
private function generateFilterConditionSQL(ClassMetadata $targetEntity, $targetTableAlias)
|
||||||
|
@ -22,6 +22,7 @@ namespace Doctrine\ORM\Persisters;
|
|||||||
use Doctrine\ORM\ORMException,
|
use Doctrine\ORM\ORMException,
|
||||||
Doctrine\ORM\Mapping\ClassMetadata,
|
Doctrine\ORM\Mapping\ClassMetadata,
|
||||||
Doctrine\DBAL\LockMode,
|
Doctrine\DBAL\LockMode,
|
||||||
|
Doctrine\DBAL\Types\Type,
|
||||||
Doctrine\ORM\Query\ResultSetMapping;
|
Doctrine\ORM\Query\ResultSetMapping;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -55,11 +56,11 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
|||||||
*/
|
*/
|
||||||
protected function _getDiscriminatorColumnTableName()
|
protected function _getDiscriminatorColumnTableName()
|
||||||
{
|
{
|
||||||
if ($this->_class->name == $this->_class->rootEntityName) {
|
$class = ($this->_class->name !== $this->_class->rootEntityName)
|
||||||
return $this->_class->table['name'];
|
? $this->_em->getClassMetadata($this->_class->rootEntityName)
|
||||||
} else {
|
: $this->_class;
|
||||||
return $this->_em->getClassMetadata($this->_class->rootEntityName)->table['name'];
|
|
||||||
}
|
return $class->getTableName();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -72,8 +73,10 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
|||||||
{
|
{
|
||||||
if (isset($this->_class->fieldMappings[$this->_class->versionField]['inherited'])) {
|
if (isset($this->_class->fieldMappings[$this->_class->versionField]['inherited'])) {
|
||||||
$definingClassName = $this->_class->fieldMappings[$this->_class->versionField]['inherited'];
|
$definingClassName = $this->_class->fieldMappings[$this->_class->versionField]['inherited'];
|
||||||
|
|
||||||
return $this->_em->getClassMetadata($definingClassName);
|
return $this->_em->getClassMetadata($definingClassName);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->_class;
|
return $this->_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,19 +89,24 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
|||||||
*/
|
*/
|
||||||
public function getOwningTable($fieldName)
|
public function getOwningTable($fieldName)
|
||||||
{
|
{
|
||||||
if (!isset($this->_owningTableMap[$fieldName])) {
|
if (isset($this->_owningTableMap[$fieldName])) {
|
||||||
if (isset($this->_class->associationMappings[$fieldName]['inherited'])) {
|
return $this->_owningTableMap[$fieldName];
|
||||||
$cm = $this->_em->getClassMetadata($this->_class->associationMappings[$fieldName]['inherited']);
|
}
|
||||||
} else if (isset($this->_class->fieldMappings[$fieldName]['inherited'])) {
|
|
||||||
$cm = $this->_em->getClassMetadata($this->_class->fieldMappings[$fieldName]['inherited']);
|
if (isset($this->_class->associationMappings[$fieldName]['inherited'])) {
|
||||||
} else {
|
$cm = $this->_em->getClassMetadata($this->_class->associationMappings[$fieldName]['inherited']);
|
||||||
$cm = $this->_class;
|
} else if (isset($this->_class->fieldMappings[$fieldName]['inherited'])) {
|
||||||
}
|
$cm = $this->_em->getClassMetadata($this->_class->fieldMappings[$fieldName]['inherited']);
|
||||||
$this->_owningTableMap[$fieldName] = $cm->table['name'];
|
} else {
|
||||||
$this->_quotedTableMap[$cm->table['name']] = $cm->getQuotedTableName($this->_platform);
|
$cm = $this->_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->_owningTableMap[$fieldName];
|
$tableName = $cm->getTableName();
|
||||||
|
|
||||||
|
$this->_owningTableMap[$fieldName] = $tableName;
|
||||||
|
$this->_quotedTableMap[$tableName] = $cm->getQuotedTableName($this->_platform);
|
||||||
|
|
||||||
|
return $tableName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -115,20 +123,22 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
|||||||
$isPostInsertId = $idGen->isPostInsertGenerator();
|
$isPostInsertId = $idGen->isPostInsertGenerator();
|
||||||
|
|
||||||
// Prepare statement for the root table
|
// Prepare statement for the root table
|
||||||
$rootClass = $this->_class->name == $this->_class->rootEntityName ?
|
$rootClass = ($this->_class->name !== $this->_class->rootEntityName) ? $this->_em->getClassMetadata($this->_class->rootEntityName) : $this->_class;
|
||||||
$this->_class : $this->_em->getClassMetadata($this->_class->rootEntityName);
|
|
||||||
$rootPersister = $this->_em->getUnitOfWork()->getEntityPersister($rootClass->name);
|
$rootPersister = $this->_em->getUnitOfWork()->getEntityPersister($rootClass->name);
|
||||||
$rootTableName = $rootClass->table['name'];
|
$rootTableName = $rootClass->getTableName();
|
||||||
$rootTableStmt = $this->_conn->prepare($rootPersister->_getInsertSQL());
|
$rootTableStmt = $this->_conn->prepare($rootPersister->_getInsertSQL());
|
||||||
|
|
||||||
// Prepare statements for sub tables.
|
// Prepare statements for sub tables.
|
||||||
$subTableStmts = array();
|
$subTableStmts = array();
|
||||||
|
|
||||||
if ($rootClass !== $this->_class) {
|
if ($rootClass !== $this->_class) {
|
||||||
$subTableStmts[$this->_class->table['name']] = $this->_conn->prepare($this->_getInsertSQL());
|
$subTableStmts[$this->_class->getTableName()] = $this->_conn->prepare($this->_getInsertSQL());
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($this->_class->parentClasses as $parentClassName) {
|
foreach ($this->_class->parentClasses as $parentClassName) {
|
||||||
$parentClass = $this->_em->getClassMetadata($parentClassName);
|
$parentClass = $this->_em->getClassMetadata($parentClassName);
|
||||||
$parentTableName = $parentClass->table['name'];
|
$parentTableName = $parentClass->getTableName();
|
||||||
|
|
||||||
if ($parentClass !== $rootClass) {
|
if ($parentClass !== $rootClass) {
|
||||||
$parentPersister = $this->_em->getUnitOfWork()->getEntityPersister($parentClassName);
|
$parentPersister = $this->_em->getUnitOfWork()->getEntityPersister($parentClassName);
|
||||||
$subTableStmts[$parentTableName] = $this->_conn->prepare($parentPersister->_getInsertSQL());
|
$subTableStmts[$parentTableName] = $this->_conn->prepare($parentPersister->_getInsertSQL());
|
||||||
@ -143,9 +153,11 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
|||||||
|
|
||||||
// Execute insert on root table
|
// Execute insert on root table
|
||||||
$paramIndex = 1;
|
$paramIndex = 1;
|
||||||
|
|
||||||
foreach ($insertData[$rootTableName] as $columnName => $value) {
|
foreach ($insertData[$rootTableName] as $columnName => $value) {
|
||||||
$rootTableStmt->bindValue($paramIndex++, $value, $this->_columnTypes[$columnName]);
|
$rootTableStmt->bindValue($paramIndex++, $value, $this->_columnTypes[$columnName]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$rootTableStmt->execute();
|
$rootTableStmt->execute();
|
||||||
|
|
||||||
if ($isPostInsertId) {
|
if ($isPostInsertId) {
|
||||||
@ -160,17 +172,23 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
|||||||
foreach ($subTableStmts as $tableName => $stmt) {
|
foreach ($subTableStmts as $tableName => $stmt) {
|
||||||
$data = isset($insertData[$tableName]) ? $insertData[$tableName] : array();
|
$data = isset($insertData[$tableName]) ? $insertData[$tableName] : array();
|
||||||
$paramIndex = 1;
|
$paramIndex = 1;
|
||||||
foreach ((array) $id as $idVal) {
|
|
||||||
$stmt->bindValue($paramIndex++, $idVal);
|
foreach ((array) $id as $idName => $idVal) {
|
||||||
|
$type = isset($this->_columnTypes[$idName]) ? $this->_columnTypes[$idName] : Type::STRING;
|
||||||
|
|
||||||
|
$stmt->bindValue($paramIndex++, $idVal, $type);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($data as $columnName => $value) {
|
foreach ($data as $columnName => $value) {
|
||||||
$stmt->bindValue($paramIndex++, $value, $this->_columnTypes[$columnName]);
|
$stmt->bindValue($paramIndex++, $value, $this->_columnTypes[$columnName]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$rootTableStmt->closeCursor();
|
$rootTableStmt->closeCursor();
|
||||||
|
|
||||||
foreach ($subTableStmts as $stmt) {
|
foreach ($subTableStmts as $stmt) {
|
||||||
$stmt->closeCursor();
|
$stmt->closeCursor();
|
||||||
}
|
}
|
||||||
@ -191,15 +209,18 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
|||||||
{
|
{
|
||||||
$updateData = $this->_prepareUpdateData($entity);
|
$updateData = $this->_prepareUpdateData($entity);
|
||||||
|
|
||||||
if ($isVersioned = $this->_class->isVersioned) {
|
if (($isVersioned = $this->_class->isVersioned) != false) {
|
||||||
$versionedClass = $this->_getVersionedClassMetadata();
|
$versionedClass = $this->_getVersionedClassMetadata();
|
||||||
$versionedTable = $versionedClass->table['name'];
|
$versionedTable = $versionedClass->getTableName();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($updateData) {
|
if ($updateData) {
|
||||||
foreach ($updateData as $tableName => $data) {
|
foreach ($updateData as $tableName => $data) {
|
||||||
$this->_updateTable($entity, $this->_quotedTableMap[$tableName], $data, $isVersioned && $versionedTable == $tableName);
|
$this->_updateTable(
|
||||||
|
$entity, $this->_quotedTableMap[$tableName], $data, $isVersioned && $versionedTable == $tableName
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the table with the version column is updated even if no columns on that
|
// Make sure the table with the version column is updated even if no columns on that
|
||||||
// table were affected.
|
// table were affected.
|
||||||
if ($isVersioned && ! isset($updateData[$versionedTable])) {
|
if ($isVersioned && ! isset($updateData[$versionedTable])) {
|
||||||
@ -224,13 +245,17 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
|||||||
// If the database platform supports FKs, just
|
// If the database platform supports FKs, just
|
||||||
// delete the row from the root table. Cascades do the rest.
|
// delete the row from the root table. Cascades do the rest.
|
||||||
if ($this->_platform->supportsForeignKeyConstraints()) {
|
if ($this->_platform->supportsForeignKeyConstraints()) {
|
||||||
$this->_conn->delete($this->_em->getClassMetadata($this->_class->rootEntityName)
|
$this->_conn->delete(
|
||||||
->getQuotedTableName($this->_platform), $id);
|
$this->_em->getClassMetadata($this->_class->rootEntityName)->getQuotedTableName($this->_platform), $id
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
// Delete from all tables individually, starting from this class' table up to the root table.
|
// Delete from all tables individually, starting from this class' table up to the root table.
|
||||||
$this->_conn->delete($this->_class->getQuotedTableName($this->_platform), $id);
|
$this->_conn->delete($this->_class->getQuotedTableName($this->_platform), $id);
|
||||||
|
|
||||||
foreach ($this->_class->parentClasses as $parentClass) {
|
foreach ($this->_class->parentClasses as $parentClass) {
|
||||||
$this->_conn->delete($this->_em->getClassMetadata($parentClass)->getQuotedTableName($this->_platform), $id);
|
$this->_conn->delete(
|
||||||
|
$this->_em->getClassMetadata($parentClass)->getQuotedTableName($this->_platform), $id
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -251,23 +276,27 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
|||||||
|
|
||||||
// Add regular columns
|
// Add regular columns
|
||||||
$columnList = '';
|
$columnList = '';
|
||||||
|
|
||||||
foreach ($this->_class->fieldMappings as $fieldName => $mapping) {
|
foreach ($this->_class->fieldMappings as $fieldName => $mapping) {
|
||||||
if ($columnList != '') $columnList .= ', ';
|
if ($columnList != '') $columnList .= ', ';
|
||||||
$columnList .= $this->_getSelectColumnSQL($fieldName,
|
|
||||||
isset($mapping['inherited']) ?
|
$columnList .= $this->_getSelectColumnSQL(
|
||||||
$this->_em->getClassMetadata($mapping['inherited']) :
|
$fieldName,
|
||||||
$this->_class);
|
isset($mapping['inherited']) ? $this->_em->getClassMetadata($mapping['inherited']) : $this->_class
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add foreign key columns
|
// Add foreign key columns
|
||||||
foreach ($this->_class->associationMappings as $assoc2) {
|
foreach ($this->_class->associationMappings as $assoc2) {
|
||||||
if ($assoc2['isOwningSide'] && $assoc2['type'] & ClassMetadata::TO_ONE) {
|
if ($assoc2['isOwningSide'] && $assoc2['type'] & ClassMetadata::TO_ONE) {
|
||||||
$tableAlias = isset($assoc2['inherited']) ?
|
$tableAlias = isset($assoc2['inherited']) ? $this->_getSQLTableAlias($assoc2['inherited']) : $baseTableAlias;
|
||||||
$this->_getSQLTableAlias($assoc2['inherited'])
|
|
||||||
: $baseTableAlias;
|
|
||||||
foreach ($assoc2['targetToSourceKeyColumns'] as $srcColumn) {
|
foreach ($assoc2['targetToSourceKeyColumns'] as $srcColumn) {
|
||||||
if ($columnList != '') $columnList .= ', ';
|
if ($columnList != '') $columnList .= ', ';
|
||||||
$columnList .= $this->getSelectJoinColumnSQL($tableAlias, $srcColumn,
|
|
||||||
|
$columnList .= $this->getSelectJoinColumnSQL(
|
||||||
|
$tableAlias,
|
||||||
|
$srcColumn,
|
||||||
isset($assoc2['inherited']) ? $assoc2['inherited'] : $this->_class->name
|
isset($assoc2['inherited']) ? $assoc2['inherited'] : $this->_class->name
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -276,27 +305,27 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
|||||||
|
|
||||||
// Add discriminator column (DO NOT ALIAS, see AbstractEntityInheritancePersister#_processSQLResult).
|
// Add discriminator column (DO NOT ALIAS, see AbstractEntityInheritancePersister#_processSQLResult).
|
||||||
$discrColumn = $this->_class->discriminatorColumn['name'];
|
$discrColumn = $this->_class->discriminatorColumn['name'];
|
||||||
if ($this->_class->rootEntityName == $this->_class->name) {
|
$tableAlias = ($this->_class->rootEntityName == $this->_class->name) ? $baseTableAlias : $this->_getSQLTableAlias($this->_class->rootEntityName);
|
||||||
$columnList .= ", $baseTableAlias.$discrColumn";
|
$columnList .= ', ' . $tableAlias . '.' . $discrColumn;
|
||||||
} else {
|
|
||||||
$columnList .= ', ' . $this->_getSQLTableAlias($this->_class->rootEntityName)
|
|
||||||
. ".$discrColumn";
|
|
||||||
}
|
|
||||||
|
|
||||||
$resultColumnName = $this->_platform->getSQLResultCasing($discrColumn);
|
$resultColumnName = $this->_platform->getSQLResultCasing($discrColumn);
|
||||||
|
|
||||||
$this->_rsm->setDiscriminatorColumn('r', $resultColumnName);
|
$this->_rsm->setDiscriminatorColumn('r', $resultColumnName);
|
||||||
$this->_rsm->addMetaResult('r', $resultColumnName, $discrColumn);
|
$this->_rsm->addMetaResult('r', $resultColumnName, $discrColumn);
|
||||||
}
|
}
|
||||||
|
|
||||||
// INNER JOIN parent tables
|
// INNER JOIN parent tables
|
||||||
$joinSql = '';
|
$joinSql = '';
|
||||||
|
|
||||||
foreach ($this->_class->parentClasses as $parentClassName) {
|
foreach ($this->_class->parentClasses as $parentClassName) {
|
||||||
$parentClass = $this->_em->getClassMetadata($parentClassName);
|
$parentClass = $this->_em->getClassMetadata($parentClassName);
|
||||||
$tableAlias = $this->_getSQLTableAlias($parentClassName);
|
$tableAlias = $this->_getSQLTableAlias($parentClassName);
|
||||||
$joinSql .= ' INNER JOIN ' . $parentClass->getQuotedTableName($this->_platform) . ' ' . $tableAlias . ' ON ';
|
$joinSql .= ' INNER JOIN ' . $parentClass->getQuotedTableName($this->_platform) . ' ' . $tableAlias . ' ON ';
|
||||||
$first = true;
|
$first = true;
|
||||||
|
|
||||||
foreach ($idColumns as $idColumn) {
|
foreach ($idColumns as $idColumn) {
|
||||||
if ($first) $first = false; else $joinSql .= ' AND ';
|
if ($first) $first = false; else $joinSql .= ' AND ';
|
||||||
|
|
||||||
$joinSql .= $baseTableAlias . '.' . $idColumn . ' = ' . $tableAlias . '.' . $idColumn;
|
$joinSql .= $baseTableAlias . '.' . $idColumn . ' = ' . $tableAlias . '.' . $idColumn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -309,19 +338,20 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
|||||||
if ($this->_selectColumnListSql === null) {
|
if ($this->_selectColumnListSql === null) {
|
||||||
// Add subclass columns
|
// Add subclass columns
|
||||||
foreach ($subClass->fieldMappings as $fieldName => $mapping) {
|
foreach ($subClass->fieldMappings as $fieldName => $mapping) {
|
||||||
if (isset($mapping['inherited'])) {
|
if (isset($mapping['inherited'])) continue;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$columnList .= ', ' . $this->_getSelectColumnSQL($fieldName, $subClass);
|
$columnList .= ', ' . $this->_getSelectColumnSQL($fieldName, $subClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add join columns (foreign keys)
|
// Add join columns (foreign keys)
|
||||||
foreach ($subClass->associationMappings as $assoc2) {
|
foreach ($subClass->associationMappings as $assoc2) {
|
||||||
if ($assoc2['isOwningSide'] && $assoc2['type'] & ClassMetadata::TO_ONE
|
if ($assoc2['isOwningSide'] && $assoc2['type'] & ClassMetadata::TO_ONE && ! isset($assoc2['inherited'])) {
|
||||||
&& ! isset($assoc2['inherited'])) {
|
|
||||||
foreach ($assoc2['targetToSourceKeyColumns'] as $srcColumn) {
|
foreach ($assoc2['targetToSourceKeyColumns'] as $srcColumn) {
|
||||||
if ($columnList != '') $columnList .= ', ';
|
if ($columnList != '') $columnList .= ', ';
|
||||||
$columnList .= $this->getSelectJoinColumnSQL($tableAlias, $srcColumn,
|
|
||||||
|
$columnList .= $this->getSelectJoinColumnSQL(
|
||||||
|
$tableAlias,
|
||||||
|
$srcColumn,
|
||||||
isset($assoc2['inherited']) ? $assoc2['inherited'] : $subClass->name
|
isset($assoc2['inherited']) ? $assoc2['inherited'] : $subClass->name
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -332,14 +362,15 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
|||||||
// Add LEFT JOIN
|
// Add LEFT JOIN
|
||||||
$joinSql .= ' LEFT JOIN ' . $subClass->getQuotedTableName($this->_platform) . ' ' . $tableAlias . ' ON ';
|
$joinSql .= ' LEFT JOIN ' . $subClass->getQuotedTableName($this->_platform) . ' ' . $tableAlias . ' ON ';
|
||||||
$first = true;
|
$first = true;
|
||||||
|
|
||||||
foreach ($idColumns as $idColumn) {
|
foreach ($idColumns as $idColumn) {
|
||||||
if ($first) $first = false; else $joinSql .= ' AND ';
|
if ($first) $first = false; else $joinSql .= ' AND ';
|
||||||
|
|
||||||
$joinSql .= $baseTableAlias . '.' . $idColumn . ' = ' . $tableAlias . '.' . $idColumn;
|
$joinSql .= $baseTableAlias . '.' . $idColumn . ' = ' . $tableAlias . '.' . $idColumn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$joinSql .= $assoc != null && $assoc['type'] == ClassMetadata::MANY_TO_MANY ?
|
$joinSql .= ($assoc != null && $assoc['type'] == ClassMetadata::MANY_TO_MANY) ? $this->_getSelectManyToManyJoinSQL($assoc) : '';
|
||||||
$this->_getSelectManyToManyJoinSQL($assoc) : '';
|
|
||||||
|
|
||||||
$conditionSql = $this->_getSelectConditionSQL($criteria, $assoc);
|
$conditionSql = $this->_getSelectConditionSQL($criteria, $assoc);
|
||||||
|
|
||||||
@ -351,6 +382,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
|||||||
}
|
}
|
||||||
|
|
||||||
$lockSql = '';
|
$lockSql = '';
|
||||||
|
|
||||||
if ($lockMode == LockMode::PESSIMISTIC_READ) {
|
if ($lockMode == LockMode::PESSIMISTIC_READ) {
|
||||||
$lockSql = ' ' . $this->_platform->getReadLockSql();
|
$lockSql = ' ' . $this->_platform->getReadLockSql();
|
||||||
} else if ($lockMode == LockMode::PESSIMISTIC_WRITE) {
|
} else if ($lockMode == LockMode::PESSIMISTIC_WRITE) {
|
||||||
@ -376,13 +408,16 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
|||||||
|
|
||||||
// INNER JOIN parent tables
|
// INNER JOIN parent tables
|
||||||
$joinSql = '';
|
$joinSql = '';
|
||||||
|
|
||||||
foreach ($this->_class->parentClasses as $parentClassName) {
|
foreach ($this->_class->parentClasses as $parentClassName) {
|
||||||
$parentClass = $this->_em->getClassMetadata($parentClassName);
|
$parentClass = $this->_em->getClassMetadata($parentClassName);
|
||||||
$tableAlias = $this->_getSQLTableAlias($parentClassName);
|
$tableAlias = $this->_getSQLTableAlias($parentClassName);
|
||||||
$joinSql .= ' INNER JOIN ' . $parentClass->getQuotedTableName($this->_platform) . ' ' . $tableAlias . ' ON ';
|
$joinSql .= ' INNER JOIN ' . $parentClass->getQuotedTableName($this->_platform) . ' ' . $tableAlias . ' ON ';
|
||||||
$first = true;
|
$first = true;
|
||||||
|
|
||||||
foreach ($idColumns as $idColumn) {
|
foreach ($idColumns as $idColumn) {
|
||||||
if ($first) $first = false; else $joinSql .= ' AND ';
|
if ($first) $first = false; else $joinSql .= ' AND ';
|
||||||
|
|
||||||
$joinSql .= $baseTableAlias . '.' . $idColumn . ' = ' . $tableAlias . '.' . $idColumn;
|
$joinSql .= $baseTableAlias . '.' . $idColumn . ' = ' . $tableAlias . '.' . $idColumn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,9 +40,10 @@ class ManyToManyPersister extends AbstractCollectionPersister
|
|||||||
protected function _getDeleteRowSQL(PersistentCollection $coll)
|
protected function _getDeleteRowSQL(PersistentCollection $coll)
|
||||||
{
|
{
|
||||||
$mapping = $coll->getMapping();
|
$mapping = $coll->getMapping();
|
||||||
$joinTable = $mapping['joinTable'];
|
$class = $this->_em->getClassMetadata(get_class($coll->getOwner()));
|
||||||
$columns = $mapping['joinTableColumns'];
|
|
||||||
return 'DELETE FROM ' . $joinTable['name'] . ' WHERE ' . implode(' = ? AND ', $columns) . ' = ?';
|
return 'DELETE FROM ' . $class->getQuotedJoinTableName($mapping, $this->_conn->getDatabasePlatform())
|
||||||
|
. ' WHERE ' . implode(' = ? AND ', $mapping['joinTableColumns']) . ' = ?';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -75,10 +76,11 @@ class ManyToManyPersister extends AbstractCollectionPersister
|
|||||||
protected function _getInsertRowSQL(PersistentCollection $coll)
|
protected function _getInsertRowSQL(PersistentCollection $coll)
|
||||||
{
|
{
|
||||||
$mapping = $coll->getMapping();
|
$mapping = $coll->getMapping();
|
||||||
$joinTable = $mapping['joinTable'];
|
|
||||||
$columns = $mapping['joinTableColumns'];
|
$columns = $mapping['joinTableColumns'];
|
||||||
return 'INSERT INTO ' . $joinTable['name'] . ' (' . implode(', ', $columns) . ')'
|
$class = $this->_em->getClassMetadata(get_class($coll->getOwner()));
|
||||||
. ' VALUES (' . implode(', ', array_fill(0, count($columns), '?')) . ')';
|
|
||||||
|
return 'INSERT INTO ' . $class->getQuotedJoinTableName($mapping, $this->_conn->getDatabasePlatform())
|
||||||
|
. ' (' . implode(', ', $columns) . ') VALUES (' . implode(', ', array_fill(0, count($columns), '?')) . ')';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -103,8 +105,8 @@ class ManyToManyPersister extends AbstractCollectionPersister
|
|||||||
*/
|
*/
|
||||||
private function _collectJoinTableColumnParameters(PersistentCollection $coll, $element)
|
private function _collectJoinTableColumnParameters(PersistentCollection $coll, $element)
|
||||||
{
|
{
|
||||||
$params = array();
|
$params = array();
|
||||||
$mapping = $coll->getMapping();
|
$mapping = $coll->getMapping();
|
||||||
$isComposite = count($mapping['joinTableColumns']) > 2;
|
$isComposite = count($mapping['joinTableColumns']) > 2;
|
||||||
|
|
||||||
$identifier1 = $this->_uow->getEntityIdentifier($coll->getOwner());
|
$identifier1 = $this->_uow->getEntityIdentifier($coll->getOwner());
|
||||||
@ -149,14 +151,19 @@ class ManyToManyPersister extends AbstractCollectionPersister
|
|||||||
*/
|
*/
|
||||||
protected function _getDeleteSQL(PersistentCollection $coll)
|
protected function _getDeleteSQL(PersistentCollection $coll)
|
||||||
{
|
{
|
||||||
$mapping = $coll->getMapping();
|
$mapping = $coll->getMapping();
|
||||||
|
$class = $this->_em->getClassMetadata(get_class($coll->getOwner()));
|
||||||
$joinTable = $mapping['joinTable'];
|
$joinTable = $mapping['joinTable'];
|
||||||
$whereClause = '';
|
$whereClause = '';
|
||||||
|
|
||||||
foreach ($mapping['relationToSourceKeyColumns'] as $relationColumn => $srcColumn) {
|
foreach ($mapping['relationToSourceKeyColumns'] as $relationColumn => $srcColumn) {
|
||||||
if ($whereClause !== '') $whereClause .= ' AND ';
|
if ($whereClause !== '') $whereClause .= ' AND ';
|
||||||
$whereClause .= "$relationColumn = ?";
|
|
||||||
|
$whereClause .= $relationColumn . ' = ?';
|
||||||
}
|
}
|
||||||
return 'DELETE FROM ' . $joinTable['name'] . ' WHERE ' . $whereClause;
|
|
||||||
|
return 'DELETE FROM ' . $class->getQuotedJoinTableName($mapping, $this->_conn->getDatabasePlatform())
|
||||||
|
. ' WHERE ' . $whereClause;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -171,8 +178,10 @@ class ManyToManyPersister extends AbstractCollectionPersister
|
|||||||
$params = array();
|
$params = array();
|
||||||
$mapping = $coll->getMapping();
|
$mapping = $coll->getMapping();
|
||||||
$identifier = $this->_uow->getEntityIdentifier($coll->getOwner());
|
$identifier = $this->_uow->getEntityIdentifier($coll->getOwner());
|
||||||
|
|
||||||
if (count($mapping['relationToSourceKeyColumns']) > 1) {
|
if (count($mapping['relationToSourceKeyColumns']) > 1) {
|
||||||
$sourceClass = $this->_em->getClassMetadata(get_class($mapping->getOwner()));
|
$sourceClass = $this->_em->getClassMetadata(get_class($mapping->getOwner()));
|
||||||
|
|
||||||
foreach ($mapping['relationToSourceKeyColumns'] as $relColumn => $srcColumn) {
|
foreach ($mapping['relationToSourceKeyColumns'] as $relColumn => $srcColumn) {
|
||||||
$params[] = $identifier[$sourceClass->fieldNames[$srcColumn]];
|
$params[] = $identifier[$sourceClass->fieldNames[$srcColumn]];
|
||||||
}
|
}
|
||||||
@ -188,21 +197,20 @@ class ManyToManyPersister extends AbstractCollectionPersister
|
|||||||
*/
|
*/
|
||||||
public function count(PersistentCollection $coll)
|
public function count(PersistentCollection $coll)
|
||||||
{
|
{
|
||||||
$params = array();
|
$params = array();
|
||||||
$mapping = $coll->getMapping();
|
$mapping = $coll->getMapping();
|
||||||
$class = $this->_em->getClassMetadata($mapping['sourceEntity']);
|
$class = $this->_em->getClassMetadata($mapping['sourceEntity']);
|
||||||
$id = $this->_em->getUnitOfWork()->getEntityIdentifier($coll->getOwner());
|
$id = $this->_em->getUnitOfWork()->getEntityIdentifier($coll->getOwner());
|
||||||
|
|
||||||
if ($mapping['isOwningSide']) {
|
if ($mapping['isOwningSide']) {
|
||||||
$joinTable = $mapping['joinTable'];
|
|
||||||
$joinColumns = $mapping['relationToSourceKeyColumns'];
|
$joinColumns = $mapping['relationToSourceKeyColumns'];
|
||||||
} else {
|
} else {
|
||||||
$mapping = $this->_em->getClassMetadata($mapping['targetEntity'])->associationMappings[$mapping['mappedBy']];
|
$mapping = $this->_em->getClassMetadata($mapping['targetEntity'])->associationMappings[$mapping['mappedBy']];
|
||||||
$joinTable = $mapping['joinTable'];
|
|
||||||
$joinColumns = $mapping['relationToTargetKeyColumns'];
|
$joinColumns = $mapping['relationToTargetKeyColumns'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$whereClause = '';
|
$whereClause = '';
|
||||||
|
|
||||||
foreach ($mapping['joinTableColumns'] as $joinTableColumn) {
|
foreach ($mapping['joinTableColumns'] as $joinTableColumn) {
|
||||||
if (isset($joinColumns[$joinTableColumn])) {
|
if (isset($joinColumns[$joinTableColumn])) {
|
||||||
if ($whereClause !== '') {
|
if ($whereClause !== '') {
|
||||||
@ -210,18 +218,16 @@ class ManyToManyPersister extends AbstractCollectionPersister
|
|||||||
}
|
}
|
||||||
$whereClause .= "t.$joinTableColumn = ?";
|
$whereClause .= "t.$joinTableColumn = ?";
|
||||||
|
|
||||||
if ($class->containsForeignIdentifier) {
|
$params[] = ($class->containsForeignIdentifier)
|
||||||
$params[] = $id[$class->getFieldForColumn($joinColumns[$joinTableColumn])];
|
? $id[$class->getFieldForColumn($joinColumns[$joinTableColumn])]
|
||||||
} else {
|
: $id[$class->fieldNames[$joinColumns[$joinTableColumn]]];
|
||||||
$params[] = $id[$class->fieldNames[$joinColumns[$joinTableColumn]]];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
list($joinTargetEntitySQL, $filterSql) = $this->getFilterSql($mapping);
|
list($joinTargetEntitySQL, $filterSql) = $this->getFilterSql($mapping);
|
||||||
|
|
||||||
$sql = 'SELECT count(*)'
|
$sql = 'SELECT COUNT(*)'
|
||||||
. ' FROM ' . $joinTable['name'] . ' t'
|
. ' FROM ' . $class->getQuotedJoinTableName($mapping, $this->_conn->getDatabasePlatform()) . ' t'
|
||||||
. $joinTargetEntitySQL
|
. $joinTargetEntitySQL
|
||||||
. ' WHERE ' . $whereClause
|
. ' WHERE ' . $whereClause
|
||||||
. $filterSql;
|
. $filterSql;
|
||||||
@ -238,9 +244,8 @@ class ManyToManyPersister extends AbstractCollectionPersister
|
|||||||
public function slice(PersistentCollection $coll, $offset, $length = null)
|
public function slice(PersistentCollection $coll, $offset, $length = null)
|
||||||
{
|
{
|
||||||
$mapping = $coll->getMapping();
|
$mapping = $coll->getMapping();
|
||||||
return $this->_em->getUnitOfWork()
|
|
||||||
->getEntityPersister($mapping['targetEntity'])
|
return $this->_em->getUnitOfWork()->getEntityPersister($mapping['targetEntity'])->getManyToManyCollection($mapping, $coll->getOwner(), $offset, $length);
|
||||||
->getManyToManyCollection($mapping, $coll->getOwner(), $offset, $length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -259,7 +264,7 @@ class ManyToManyPersister extends AbstractCollectionPersister
|
|||||||
$params = array();
|
$params = array();
|
||||||
$mapping = $coll->getMapping();
|
$mapping = $coll->getMapping();
|
||||||
|
|
||||||
if (!$mapping['isOwningSide']) {
|
if ( ! $mapping['isOwningSide']) {
|
||||||
$sourceClass = $this->_em->getClassMetadata($mapping['targetEntity']);
|
$sourceClass = $this->_em->getClassMetadata($mapping['targetEntity']);
|
||||||
$targetClass = $this->_em->getClassMetadata($mapping['sourceEntity']);
|
$targetClass = $this->_em->getClassMetadata($mapping['sourceEntity']);
|
||||||
$sourceId = $uow->getEntityIdentifier($element);
|
$sourceId = $uow->getEntityIdentifier($element);
|
||||||
@ -272,44 +277,42 @@ class ManyToManyPersister extends AbstractCollectionPersister
|
|||||||
$sourceId = $uow->getEntityIdentifier($coll->getOwner());
|
$sourceId = $uow->getEntityIdentifier($coll->getOwner());
|
||||||
$targetId = $uow->getEntityIdentifier($element);
|
$targetId = $uow->getEntityIdentifier($element);
|
||||||
}
|
}
|
||||||
$joinTable = $mapping['joinTable'];
|
|
||||||
|
|
||||||
$whereClause = '';
|
$whereClause = '';
|
||||||
|
|
||||||
foreach ($mapping['joinTableColumns'] as $joinTableColumn) {
|
foreach ($mapping['joinTableColumns'] as $joinTableColumn) {
|
||||||
if (isset($mapping['relationToTargetKeyColumns'][$joinTableColumn])) {
|
if (isset($mapping['relationToTargetKeyColumns'][$joinTableColumn])) {
|
||||||
if ($whereClause !== '') {
|
if ($whereClause !== '') {
|
||||||
$whereClause .= ' AND ';
|
$whereClause .= ' AND ';
|
||||||
}
|
}
|
||||||
$whereClause .= "$joinTableColumn = ?";
|
|
||||||
|
$whereClause .= $joinTableColumn . ' = ?';
|
||||||
|
|
||||||
if ($targetClass->containsForeignIdentifier) {
|
$params[] = ($targetClass->containsForeignIdentifier)
|
||||||
$params[] = $targetId[$targetClass->getFieldForColumn($mapping['relationToTargetKeyColumns'][$joinTableColumn])];
|
? $targetId[$targetClass->getFieldForColumn($mapping['relationToTargetKeyColumns'][$joinTableColumn])]
|
||||||
} else {
|
: $targetId[$targetClass->fieldNames[$mapping['relationToTargetKeyColumns'][$joinTableColumn]]];
|
||||||
$params[] = $targetId[$targetClass->fieldNames[$mapping['relationToTargetKeyColumns'][$joinTableColumn]]];
|
|
||||||
}
|
|
||||||
} else if (isset($mapping['relationToSourceKeyColumns'][$joinTableColumn])) {
|
} else if (isset($mapping['relationToSourceKeyColumns'][$joinTableColumn])) {
|
||||||
if ($whereClause !== '') {
|
if ($whereClause !== '') {
|
||||||
$whereClause .= ' AND ';
|
$whereClause .= ' AND ';
|
||||||
}
|
}
|
||||||
$whereClause .= "$joinTableColumn = ?";
|
|
||||||
|
$whereClause .= $joinTableColumn . ' = ?';
|
||||||
|
|
||||||
if ($sourceClass->containsForeignIdentifier) {
|
$params[] = ($sourceClass->containsForeignIdentifier)
|
||||||
$params[] = $sourceId[$sourceClass->getFieldForColumn($mapping['relationToSourceKeyColumns'][$joinTableColumn])];
|
? $sourceId[$sourceClass->getFieldForColumn($mapping['relationToSourceKeyColumns'][$joinTableColumn])]
|
||||||
} else {
|
: $sourceId[$sourceClass->fieldNames[$mapping['relationToSourceKeyColumns'][$joinTableColumn]]];
|
||||||
$params[] = $sourceId[$sourceClass->fieldNames[$mapping['relationToSourceKeyColumns'][$joinTableColumn]]];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
list($joinTargetEntitySQL, $filterSql) = $this->getFilterSql($mapping);
|
list($joinTargetEntitySQL, $filterSql) = $this->getFilterSql($mapping);
|
||||||
|
|
||||||
$sql = 'SELECT 1'
|
$sql = 'SELECT 1'
|
||||||
. ' FROM ' . $joinTable['name'] . ' t'
|
. ' FROM ' . $sourceClass->getQuotedJoinTableName($mapping, $this->_conn->getDatabasePlatform()) . ' t'
|
||||||
. $joinTargetEntitySQL
|
. $joinTargetEntitySQL
|
||||||
. ' WHERE ' . $whereClause
|
. ' WHERE ' . $whereClause
|
||||||
. $filterSql;
|
. $filterSql;
|
||||||
|
|
||||||
return (bool)$this->_conn->fetchColumn($sql, $params);
|
return (bool) $this->_conn->fetchColumn($sql, $params);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFilterSql($mapping)
|
public function getFilterSql($mapping)
|
||||||
|
@ -35,38 +35,49 @@ class SingleTablePersister extends AbstractEntityInheritancePersister
|
|||||||
/** {@inheritdoc} */
|
/** {@inheritdoc} */
|
||||||
protected function _getDiscriminatorColumnTableName()
|
protected function _getDiscriminatorColumnTableName()
|
||||||
{
|
{
|
||||||
return $this->_class->table['name'];
|
return $this->_class->getTableName();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritdoc} */
|
/** {@inheritdoc} */
|
||||||
protected function _getSelectColumnListSQL()
|
protected function _getSelectColumnListSQL()
|
||||||
{
|
{
|
||||||
|
if ($this->_selectColumnListSql !== null) {
|
||||||
|
return $this->_selectColumnListSql;
|
||||||
|
}
|
||||||
|
|
||||||
$columnList = parent::_getSelectColumnListSQL();
|
$columnList = parent::_getSelectColumnListSQL();
|
||||||
|
|
||||||
// Append discriminator column
|
// Append discriminator column
|
||||||
$discrColumn = $this->_class->discriminatorColumn['name'];
|
$discrColumn = $this->_class->discriminatorColumn['name'];
|
||||||
$columnList .= ", $discrColumn";
|
$columnList .= ', ' . $discrColumn;
|
||||||
$rootClass = $this->_em->getClassMetadata($this->_class->rootEntityName);
|
|
||||||
|
$rootClass = $this->_em->getClassMetadata($this->_class->rootEntityName);
|
||||||
$tableAlias = $this->_getSQLTableAlias($rootClass->name);
|
$tableAlias = $this->_getSQLTableAlias($rootClass->name);
|
||||||
$resultColumnName = $this->_platform->getSQLResultCasing($discrColumn);
|
$resultColumnName = $this->_platform->getSQLResultCasing($discrColumn);
|
||||||
|
|
||||||
$this->_rsm->setDiscriminatorColumn('r', $resultColumnName);
|
$this->_rsm->setDiscriminatorColumn('r', $resultColumnName);
|
||||||
$this->_rsm->addMetaResult('r', $resultColumnName, $discrColumn);
|
$this->_rsm->addMetaResult('r', $resultColumnName, $discrColumn);
|
||||||
|
|
||||||
// Append subclass columns
|
// Append subclass columns
|
||||||
foreach ($this->_class->subClasses as $subClassName) {
|
foreach ($this->_class->subClasses as $subClassName) {
|
||||||
$subClass = $this->_em->getClassMetadata($subClassName);
|
$subClass = $this->_em->getClassMetadata($subClassName);
|
||||||
|
|
||||||
// Regular columns
|
// Regular columns
|
||||||
foreach ($subClass->fieldMappings as $fieldName => $mapping) {
|
foreach ($subClass->fieldMappings as $fieldName => $mapping) {
|
||||||
if ( ! isset($mapping['inherited'])) {
|
if ( ! isset($mapping['inherited'])) {
|
||||||
$columnList .= ', ' . $this->_getSelectColumnSQL($fieldName, $subClass);
|
$columnList .= ', ' . $this->_getSelectColumnSQL($fieldName, $subClass);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Foreign key columns
|
// Foreign key columns
|
||||||
foreach ($subClass->associationMappings as $assoc) {
|
foreach ($subClass->associationMappings as $assoc) {
|
||||||
if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE && ! isset($assoc['inherited'])) {
|
if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE && ! isset($assoc['inherited'])) {
|
||||||
foreach ($assoc['targetToSourceKeyColumns'] as $srcColumn) {
|
foreach ($assoc['targetToSourceKeyColumns'] as $srcColumn) {
|
||||||
if ($columnList != '') $columnList .= ', ';
|
if ($columnList != '') $columnList .= ', ';
|
||||||
$columnList .= $this->getSelectJoinColumnSQL($tableAlias, $srcColumn,
|
|
||||||
|
$columnList .= $this->getSelectJoinColumnSQL(
|
||||||
|
$tableAlias,
|
||||||
|
$srcColumn,
|
||||||
isset($assoc['inherited']) ? $assoc['inherited'] : $this->_class->name
|
isset($assoc['inherited']) ? $assoc['inherited'] : $this->_class->name
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -74,13 +85,15 @@ class SingleTablePersister extends AbstractEntityInheritancePersister
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $columnList;
|
$this->_selectColumnListSql = $columnList;
|
||||||
|
return $this->_selectColumnListSql;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritdoc} */
|
/** {@inheritdoc} */
|
||||||
protected function _getInsertColumnList()
|
protected function _getInsertColumnList()
|
||||||
{
|
{
|
||||||
$columns = parent::_getInsertColumnList();
|
$columns = parent::_getInsertColumnList();
|
||||||
|
|
||||||
// Add discriminator column to the INSERT SQL
|
// Add discriminator column to the INSERT SQL
|
||||||
$columns[] = $this->_class->discriminatorColumn['name'];
|
$columns[] = $this->_class->discriminatorColumn['name'];
|
||||||
|
|
||||||
@ -100,18 +113,21 @@ class SingleTablePersister extends AbstractEntityInheritancePersister
|
|||||||
|
|
||||||
// Append discriminator condition
|
// Append discriminator condition
|
||||||
if ($conditionSql) $conditionSql .= ' AND ';
|
if ($conditionSql) $conditionSql .= ' AND ';
|
||||||
|
|
||||||
$values = array();
|
$values = array();
|
||||||
|
|
||||||
if ($this->_class->discriminatorValue !== null) { // discriminators can be 0
|
if ($this->_class->discriminatorValue !== null) { // discriminators can be 0
|
||||||
$values[] = $this->_conn->quote($this->_class->discriminatorValue);
|
$values[] = $this->_conn->quote($this->_class->discriminatorValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
$discrValues = array_flip($this->_class->discriminatorMap);
|
$discrValues = array_flip($this->_class->discriminatorMap);
|
||||||
|
|
||||||
foreach ($this->_class->subClasses as $subclassName) {
|
foreach ($this->_class->subClasses as $subclassName) {
|
||||||
$values[] = $this->_conn->quote($discrValues[$subclassName]);
|
$values[] = $this->_conn->quote($discrValues[$subclassName]);
|
||||||
}
|
}
|
||||||
$conditionSql .= $this->_getSQLTableAlias($this->_class->name) . '.'
|
|
||||||
. $this->_class->discriminatorColumn['name']
|
$conditionSql .= $this->_getSQLTableAlias($this->_class->name) . '.' . $this->_class->discriminatorColumn['name']
|
||||||
. ' IN (' . implode(', ', $values) . ')';
|
. ' IN (' . implode(', ', $values) . ')';
|
||||||
|
|
||||||
return $conditionSql;
|
return $conditionSql;
|
||||||
}
|
}
|
||||||
|
@ -207,8 +207,9 @@ final class Query extends AbstractQuery
|
|||||||
|
|
||||||
// Check query cache.
|
// Check query cache.
|
||||||
if ($this->_useQueryCache && ($queryCache = $this->getQueryCacheDriver())) {
|
if ($this->_useQueryCache && ($queryCache = $this->getQueryCacheDriver())) {
|
||||||
$hash = $this->_getQueryCacheId();
|
$hash = $this->_getQueryCacheId();
|
||||||
$cached = $this->_expireQueryCache ? false : $queryCache->fetch($hash);
|
$cached = $this->_expireQueryCache ? false : $queryCache->fetch($hash);
|
||||||
|
|
||||||
if ($cached === false) {
|
if ($cached === false) {
|
||||||
// Cache miss.
|
// Cache miss.
|
||||||
$parser = new Parser($this);
|
$parser = new Parser($this);
|
||||||
@ -222,6 +223,7 @@ final class Query extends AbstractQuery
|
|||||||
$parser = new Parser($this);
|
$parser = new Parser($this);
|
||||||
$this->_parserResult = $parser->parse();
|
$this->_parserResult = $parser->parse();
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->_state = self::STATE_CLEAN;
|
$this->_state = self::STATE_CLEAN;
|
||||||
|
|
||||||
return $this->_parserResult;
|
return $this->_parserResult;
|
||||||
@ -241,50 +243,85 @@ final class Query extends AbstractQuery
|
|||||||
throw QueryException::invalidParameterNumber();
|
throw QueryException::invalidParameterNumber();
|
||||||
}
|
}
|
||||||
|
|
||||||
$sqlParams = $types = array();
|
list($sqlParams, $types) = $this->processParameterMappings($paramMappings);
|
||||||
|
|
||||||
foreach ($this->_params as $key => $value) {
|
|
||||||
if ( ! isset($paramMappings[$key])) {
|
|
||||||
throw QueryException::unknownParameter($key);
|
|
||||||
}
|
|
||||||
if (isset($this->_paramTypes[$key])) {
|
|
||||||
foreach ($paramMappings[$key] as $position) {
|
|
||||||
$types[$position] = $this->_paramTypes[$key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_object($value) && $this->_em->getMetadataFactory()->hasMetadataFor(get_class($value))) {
|
|
||||||
if ($this->_em->getUnitOfWork()->getEntityState($value) == UnitOfWork::STATE_MANAGED) {
|
|
||||||
$idValues = $this->_em->getUnitOfWork()->getEntityIdentifier($value);
|
|
||||||
} else {
|
|
||||||
$class = $this->_em->getClassMetadata(get_class($value));
|
|
||||||
$idValues = $class->getIdentifierValues($value);
|
|
||||||
}
|
|
||||||
$sqlPositions = $paramMappings[$key];
|
|
||||||
$cSqlPos = count($sqlPositions);
|
|
||||||
$cIdValues = count($idValues);
|
|
||||||
$idValues = array_values($idValues);
|
|
||||||
for ($i = 0; $i < $cSqlPos; $i++) {
|
|
||||||
$sqlParams[$sqlPositions[$i]] = $idValues[ ($i % $cIdValues) ];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
foreach ($paramMappings[$key] as $position) {
|
|
||||||
$sqlParams[$position] = $value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($sqlParams) {
|
|
||||||
ksort($sqlParams);
|
|
||||||
$sqlParams = array_values($sqlParams);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->_resultSetMapping === null) {
|
if ($this->_resultSetMapping === null) {
|
||||||
$this->_resultSetMapping = $this->_parserResult->getResultSetMapping();
|
$this->_resultSetMapping = $this->_parserResult->getResultSetMapping();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $executor->execute($this->_em->getConnection(), $sqlParams, $types);
|
return $executor->execute($this->_em->getConnection(), $sqlParams, $types);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes query parameter mappings
|
||||||
|
*
|
||||||
|
* @param array $paramMappings
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function processParameterMappings($paramMappings)
|
||||||
|
{
|
||||||
|
$sqlParams = $types = array();
|
||||||
|
|
||||||
|
foreach ($this->_params as $key => $value) {
|
||||||
|
if ( ! isset($paramMappings[$key])) {
|
||||||
|
throw QueryException::unknownParameter($key);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($this->_paramTypes[$key])) {
|
||||||
|
foreach ($paramMappings[$key] as $position) {
|
||||||
|
$types[$position] = $this->_paramTypes[$key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$sqlPositions = $paramMappings[$key];
|
||||||
|
$value = array_values($this->processParameterValue($value));
|
||||||
|
$countValue = count($value);
|
||||||
|
|
||||||
|
for ($i = 0, $l = count($sqlPositions); $i < $l; $i++) {
|
||||||
|
$sqlParams[$sqlPositions[$i]] = $value[($i % $countValue)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($sqlParams) {
|
||||||
|
ksort($sqlParams);
|
||||||
|
$sqlParams = array_values($sqlParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
return array($sqlParams, $types);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process an individual parameter value
|
||||||
|
*
|
||||||
|
* @param mixed $value
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function processParameterValue($value)
|
||||||
|
{
|
||||||
|
switch (true) {
|
||||||
|
case is_array($value):
|
||||||
|
for ($i = 0, $l = count($value); $i < $l; $i++) {
|
||||||
|
$paramValue = $this->processParameterValue($value[$i]);
|
||||||
|
|
||||||
|
// TODO: What about Entities that have composite primary key?
|
||||||
|
$value[$i] = is_array($paramValue) ? $paramValue[key($paramValue)] : $paramValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return array($value);
|
||||||
|
|
||||||
|
case is_object($value) && $this->_em->getMetadataFactory()->hasMetadataFor(get_class($value)):
|
||||||
|
if ($this->_em->getUnitOfWork()->getEntityState($value) === UnitOfWork::STATE_MANAGED) {
|
||||||
|
return array_values($this->_em->getUnitOfWork()->getEntityIdentifier($value));
|
||||||
|
}
|
||||||
|
|
||||||
|
$class = $this->_em->getClassMetadata(get_class($value));
|
||||||
|
|
||||||
|
return array_values($class->getIdentifierValues($value));
|
||||||
|
|
||||||
|
default:
|
||||||
|
return array($value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a cache driver to be used for caching queries.
|
* Defines a cache driver to be used for caching queries.
|
||||||
|
68
lib/Doctrine/ORM/Query/AST/Functions/IdentityFunction.php
Normal file
68
lib/Doctrine/ORM/Query/AST/Functions/IdentityFunction.php
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* 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.doctrine-project.org>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Doctrine\ORM\Query\AST\Functions;
|
||||||
|
|
||||||
|
use Doctrine\ORM\Query\Lexer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* "IDENTITY" "(" SingleValuedAssociationPathExpression ")"
|
||||||
|
*
|
||||||
|
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||||
|
* @link www.doctrine-project.org
|
||||||
|
* @since 2.2
|
||||||
|
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||||
|
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||||
|
*/
|
||||||
|
class IdentityFunction extends FunctionNode
|
||||||
|
{
|
||||||
|
public $pathExpression;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
|
||||||
|
{
|
||||||
|
$platform = $sqlWalker->getConnection()->getDatabasePlatform();
|
||||||
|
$dqlAlias = $this->pathExpression->identificationVariable;
|
||||||
|
$assocField = $this->pathExpression->field;
|
||||||
|
|
||||||
|
$qComp = $sqlWalker->getQueryComponent($dqlAlias);
|
||||||
|
$class = $qComp['metadata'];
|
||||||
|
$assoc = $class->associationMappings[$assocField];
|
||||||
|
|
||||||
|
$tableAlias = $sqlWalker->getSQLTableAlias($class->getTableName(), $dqlAlias);
|
||||||
|
|
||||||
|
return $tableAlias . '.' . reset($assoc['targetToSourceKeyColumns']);;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
public function parse(\Doctrine\ORM\Query\Parser $parser)
|
||||||
|
{
|
||||||
|
$parser->match(Lexer::T_IDENTIFIER);
|
||||||
|
$parser->match(Lexer::T_OPEN_PARENTHESIS);
|
||||||
|
|
||||||
|
$this->pathExpression = $parser->SingleValuedAssociationPathExpression();
|
||||||
|
|
||||||
|
$parser->match(Lexer::T_CLOSE_PARENTHESIS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -53,8 +53,8 @@ class SizeFunction extends FunctionNode
|
|||||||
|
|
||||||
if ($assoc['type'] == \Doctrine\ORM\Mapping\ClassMetadata::ONE_TO_MANY) {
|
if ($assoc['type'] == \Doctrine\ORM\Mapping\ClassMetadata::ONE_TO_MANY) {
|
||||||
$targetClass = $sqlWalker->getEntityManager()->getClassMetadata($assoc['targetEntity']);
|
$targetClass = $sqlWalker->getEntityManager()->getClassMetadata($assoc['targetEntity']);
|
||||||
$targetTableAlias = $sqlWalker->getSQLTableAlias($targetClass->table['name']);
|
$targetTableAlias = $sqlWalker->getSQLTableAlias($targetClass->getTableName());
|
||||||
$sourceTableAlias = $sqlWalker->getSQLTableAlias($class->table['name'], $dqlAlias);
|
$sourceTableAlias = $sqlWalker->getSQLTableAlias($class->getTableName(), $dqlAlias);
|
||||||
|
|
||||||
$sql .= $targetClass->getQuotedTableName($platform) . ' ' . $targetTableAlias . ' WHERE ';
|
$sql .= $targetClass->getQuotedTableName($platform) . ' ' . $targetTableAlias . ' WHERE ';
|
||||||
|
|
||||||
@ -77,7 +77,7 @@ class SizeFunction extends FunctionNode
|
|||||||
|
|
||||||
// SQL table aliases
|
// SQL table aliases
|
||||||
$joinTableAlias = $sqlWalker->getSQLTableAlias($joinTable['name']);
|
$joinTableAlias = $sqlWalker->getSQLTableAlias($joinTable['name']);
|
||||||
$sourceTableAlias = $sqlWalker->getSQLTableAlias($class->table['name'], $dqlAlias);
|
$sourceTableAlias = $sqlWalker->getSQLTableAlias($class->getTableName(), $dqlAlias);
|
||||||
|
|
||||||
// join to target table
|
// join to target table
|
||||||
$sql .= $targetClass->getQuotedJoinTableName($owningAssoc, $platform) . ' ' . $joinTableAlias . ' WHERE ';
|
$sql .= $targetClass->getQuotedJoinTableName($owningAssoc, $platform) . ' ' . $joinTableAlias . ' WHERE ';
|
||||||
|
@ -23,7 +23,7 @@ namespace Doctrine\ORM\Query\AST;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* SelectExpression ::= IdentificationVariable ["." "*"] | StateFieldPathExpression |
|
* SelectExpression ::= IdentificationVariable ["." "*"] | StateFieldPathExpression |
|
||||||
* (AggregateExpression | "(" Subselect ")") [["AS"] FieldAliasIdentificationVariable]
|
* (AggregateExpression | "(" Subselect ")") [["AS"] ["HIDDEN"] FieldAliasIdentificationVariable]
|
||||||
*
|
*
|
||||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||||
* @link www.doctrine-project.org
|
* @link www.doctrine-project.org
|
||||||
@ -37,11 +37,13 @@ class SelectExpression extends Node
|
|||||||
{
|
{
|
||||||
public $expression;
|
public $expression;
|
||||||
public $fieldIdentificationVariable;
|
public $fieldIdentificationVariable;
|
||||||
|
public $hiddenAliasResultVariable;
|
||||||
|
|
||||||
public function __construct($expression, $fieldIdentificationVariable)
|
public function __construct($expression, $fieldIdentificationVariable, $hiddenAliasResultVariable = false)
|
||||||
{
|
{
|
||||||
$this->expression = $expression;
|
$this->expression = $expression;
|
||||||
$this->fieldIdentificationVariable = $fieldIdentificationVariable;
|
$this->fieldIdentificationVariable = $fieldIdentificationVariable;
|
||||||
|
$this->hiddenAliasResultVariable = $hiddenAliasResultVariable;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function dispatch($sqlWalker)
|
public function dispatch($sqlWalker)
|
||||||
|
@ -63,7 +63,7 @@ class MultiTableDeleteExecutor extends AbstractSqlExecutor
|
|||||||
$idColumnList = implode(', ', $idColumnNames);
|
$idColumnList = implode(', ', $idColumnNames);
|
||||||
|
|
||||||
// 1. Create an INSERT INTO temptable ... SELECT identifiers WHERE $AST->getWhereClause()
|
// 1. Create an INSERT INTO temptable ... SELECT identifiers WHERE $AST->getWhereClause()
|
||||||
$sqlWalker->setSQLTableAlias($primaryClass->table['name'], 't0', $primaryDqlAlias);
|
$sqlWalker->setSQLTableAlias($primaryClass->getTableName(), 't0', $primaryDqlAlias);
|
||||||
|
|
||||||
$this->_insertSql = 'INSERT INTO ' . $tempTable . ' (' . $idColumnList . ')'
|
$this->_insertSql = 'INSERT INTO ' . $tempTable . ' (' . $idColumnList . ')'
|
||||||
. ' SELECT t0.' . implode(', t0.', $idColumnNames);
|
. ' SELECT t0.' . implode(', t0.', $idColumnNames);
|
||||||
@ -98,7 +98,7 @@ class MultiTableDeleteExecutor extends AbstractSqlExecutor
|
|||||||
}
|
}
|
||||||
$this->_createTempTableSql = $platform->getCreateTemporaryTableSnippetSQL() . ' ' . $tempTable . ' ('
|
$this->_createTempTableSql = $platform->getCreateTemporaryTableSnippetSQL() . ' ' . $tempTable . ' ('
|
||||||
. $platform->getColumnDeclarationListSQL($columnDefinitions) . ')';
|
. $platform->getColumnDeclarationListSQL($columnDefinitions) . ')';
|
||||||
$this->_dropTempTableSql = 'DROP TABLE ' . $tempTable;
|
$this->_dropTempTableSql = $platform->getDropTemporaryTableSQL($tempTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -64,7 +64,7 @@ class MultiTableUpdateExecutor extends AbstractSqlExecutor
|
|||||||
$idColumnList = implode(', ', $idColumnNames);
|
$idColumnList = implode(', ', $idColumnNames);
|
||||||
|
|
||||||
// 1. Create an INSERT INTO temptable ... SELECT identifiers WHERE $AST->getWhereClause()
|
// 1. Create an INSERT INTO temptable ... SELECT identifiers WHERE $AST->getWhereClause()
|
||||||
$sqlWalker->setSQLTableAlias($primaryClass->table['name'], 't0', $updateClause->aliasIdentificationVariable);
|
$sqlWalker->setSQLTableAlias($primaryClass->getTableName(), 't0', $updateClause->aliasIdentificationVariable);
|
||||||
|
|
||||||
$this->_insertSql = 'INSERT INTO ' . $tempTable . ' (' . $idColumnList . ')'
|
$this->_insertSql = 'INSERT INTO ' . $tempTable . ' (' . $idColumnList . ')'
|
||||||
. ' SELECT t0.' . implode(', t0.', $idColumnNames);
|
. ' SELECT t0.' . implode(', t0.', $idColumnNames);
|
||||||
@ -106,7 +106,8 @@ class MultiTableUpdateExecutor extends AbstractSqlExecutor
|
|||||||
//FIXME (URGENT): With query cache the parameter is out of date. Move to execute() stage.
|
//FIXME (URGENT): With query cache the parameter is out of date. Move to execute() stage.
|
||||||
if ($newValue instanceof AST\InputParameter) {
|
if ($newValue instanceof AST\InputParameter) {
|
||||||
$paramKey = $newValue->name;
|
$paramKey = $newValue->name;
|
||||||
$this->_sqlParameters[$i][] = $sqlWalker->getQuery()->getParameter($paramKey);
|
$this->_sqlParameters[$i]['parameters'][] = $sqlWalker->getQuery()->getParameter($paramKey);
|
||||||
|
$this->_sqlParameters[$i]['types'][] = $sqlWalker->getQuery()->getParameterType($paramKey);
|
||||||
|
|
||||||
++$this->_numParametersInUpdateClause;
|
++$this->_numParametersInUpdateClause;
|
||||||
}
|
}
|
||||||
@ -136,7 +137,7 @@ class MultiTableUpdateExecutor extends AbstractSqlExecutor
|
|||||||
$this->_createTempTableSql = $platform->getCreateTemporaryTableSnippetSQL() . ' ' . $tempTable . ' ('
|
$this->_createTempTableSql = $platform->getCreateTemporaryTableSnippetSQL() . ' ' . $tempTable . ' ('
|
||||||
. $platform->getColumnDeclarationListSQL($columnDefinitions) . ')';
|
. $platform->getColumnDeclarationListSQL($columnDefinitions) . ')';
|
||||||
|
|
||||||
$this->_dropTempTableSql = 'DROP TABLE ' . $tempTable;
|
$this->_dropTempTableSql = $platform->getDropTemporaryTableSQL($tempTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -154,11 +155,23 @@ class MultiTableUpdateExecutor extends AbstractSqlExecutor
|
|||||||
$conn->executeUpdate($this->_createTempTableSql);
|
$conn->executeUpdate($this->_createTempTableSql);
|
||||||
|
|
||||||
// Insert identifiers. Parameters from the update clause are cut off.
|
// Insert identifiers. Parameters from the update clause are cut off.
|
||||||
$numUpdated = $conn->executeUpdate($this->_insertSql, array_slice($params, $this->_numParametersInUpdateClause), $types);
|
$numUpdated = $conn->executeUpdate(
|
||||||
|
$this->_insertSql,
|
||||||
|
array_slice($params, $this->_numParametersInUpdateClause),
|
||||||
|
array_slice($types, $this->_numParametersInUpdateClause)
|
||||||
|
);
|
||||||
|
|
||||||
// Execute UPDATE statements
|
// Execute UPDATE statements
|
||||||
for ($i=0, $count=count($this->_sqlStatements); $i<$count; ++$i) {
|
for ($i=0, $count=count($this->_sqlStatements); $i<$count; ++$i) {
|
||||||
$conn->executeUpdate($this->_sqlStatements[$i], isset($this->_sqlParameters[$i]) ? $this->_sqlParameters[$i] : array());
|
$parameters = array();
|
||||||
|
$types = array();
|
||||||
|
|
||||||
|
if (isset($this->_sqlParameters[$i])) {
|
||||||
|
$parameters = isset($this->_sqlParameters[$i]['parameters']) ? $this->_sqlParameters[$i]['parameters'] : array();
|
||||||
|
$types = isset($this->_sqlParameters[$i]['types']) ? $this->_sqlParameters[$i]['types'] : array();
|
||||||
|
}
|
||||||
|
|
||||||
|
$conn->executeUpdate($this->_sqlStatements[$i], $parameters, $types);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Drop temporary table
|
// Drop temporary table
|
||||||
|
@ -34,27 +34,55 @@ namespace Doctrine\ORM\Query\Expr;
|
|||||||
*/
|
*/
|
||||||
class From
|
class From
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
private $_from;
|
private $_from;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
private $_alias;
|
private $_alias;
|
||||||
|
|
||||||
public function __construct($from, $alias)
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_indexBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $from The class name.
|
||||||
|
* @param string $alias The alias of the class.
|
||||||
|
* @param string $indexBy The index for the from.
|
||||||
|
*/
|
||||||
|
public function __construct($from, $alias, $indexBy = null)
|
||||||
{
|
{
|
||||||
$this->_from = $from;
|
$this->_from = $from;
|
||||||
$this->_alias = $alias;
|
$this->_alias = $alias;
|
||||||
|
$this->_indexBy = $indexBy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function getFrom()
|
public function getFrom()
|
||||||
{
|
{
|
||||||
return $this->_from;
|
return $this->_from;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function getAlias()
|
public function getAlias()
|
||||||
{
|
{
|
||||||
return $this->_alias;
|
return $this->_alias;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function __toString()
|
public function __toString()
|
||||||
{
|
{
|
||||||
return $this->_from . ' ' . $this->_alias;
|
return $this->_from . ' ' . $this->_alias .
|
||||||
|
($this->_indexBy ? ' INDEX BY ' . $this->_indexBy : '');
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -76,39 +76,40 @@ class Lexer extends \Doctrine\Common\Lexer
|
|||||||
const T_FROM = 122;
|
const T_FROM = 122;
|
||||||
const T_GROUP = 123;
|
const T_GROUP = 123;
|
||||||
const T_HAVING = 124;
|
const T_HAVING = 124;
|
||||||
const T_IN = 125;
|
const T_HIDDEN = 125;
|
||||||
const T_INDEX = 126;
|
const T_IN = 126;
|
||||||
const T_INNER = 127;
|
const T_INDEX = 127;
|
||||||
const T_INSTANCE = 128;
|
const T_INNER = 128;
|
||||||
const T_IS = 129;
|
const T_INSTANCE = 129;
|
||||||
const T_JOIN = 130;
|
const T_IS = 130;
|
||||||
const T_LEADING = 131;
|
const T_JOIN = 131;
|
||||||
const T_LEFT = 132;
|
const T_LEADING = 132;
|
||||||
const T_LIKE = 133;
|
const T_LEFT = 133;
|
||||||
const T_MAX = 134;
|
const T_LIKE = 134;
|
||||||
const T_MEMBER = 135;
|
const T_MAX = 135;
|
||||||
const T_MIN = 136;
|
const T_MEMBER = 136;
|
||||||
const T_NOT = 137;
|
const T_MIN = 137;
|
||||||
const T_NULL = 138;
|
const T_NOT = 138;
|
||||||
const T_NULLIF = 139;
|
const T_NULL = 139;
|
||||||
const T_OF = 140;
|
const T_NULLIF = 140;
|
||||||
const T_OR = 141;
|
const T_OF = 141;
|
||||||
const T_ORDER = 142;
|
const T_OR = 142;
|
||||||
const T_OUTER = 143;
|
const T_ORDER = 143;
|
||||||
const T_SELECT = 144;
|
const T_OUTER = 144;
|
||||||
const T_SET = 145;
|
const T_SELECT = 145;
|
||||||
const T_SIZE = 146;
|
const T_SET = 146;
|
||||||
const T_SOME = 147;
|
const T_SIZE = 147;
|
||||||
const T_SUM = 148;
|
const T_SOME = 148;
|
||||||
const T_THEN = 149;
|
const T_SUM = 149;
|
||||||
const T_TRAILING = 150;
|
const T_THEN = 150;
|
||||||
const T_TRUE = 151;
|
const T_TRAILING = 151;
|
||||||
const T_UPDATE = 152;
|
const T_TRUE = 152;
|
||||||
const T_WHEN = 153;
|
const T_UPDATE = 153;
|
||||||
const T_WHERE = 154;
|
const T_WHEN = 154;
|
||||||
const T_WITH = 155;
|
const T_WHERE = 155;
|
||||||
const T_PARTIAL = 156;
|
const T_WITH = 156;
|
||||||
const T_MOD = 157;
|
const T_PARTIAL = 157;
|
||||||
|
const T_MOD = 158;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new query scanner object.
|
* Creates a new query scanner object.
|
||||||
|
@ -40,7 +40,8 @@ class Parser
|
|||||||
'substring' => 'Doctrine\ORM\Query\AST\Functions\SubstringFunction',
|
'substring' => 'Doctrine\ORM\Query\AST\Functions\SubstringFunction',
|
||||||
'trim' => 'Doctrine\ORM\Query\AST\Functions\TrimFunction',
|
'trim' => 'Doctrine\ORM\Query\AST\Functions\TrimFunction',
|
||||||
'lower' => 'Doctrine\ORM\Query\AST\Functions\LowerFunction',
|
'lower' => 'Doctrine\ORM\Query\AST\Functions\LowerFunction',
|
||||||
'upper' => 'Doctrine\ORM\Query\AST\Functions\UpperFunction'
|
'upper' => 'Doctrine\ORM\Query\AST\Functions\UpperFunction',
|
||||||
|
'identity' => 'Doctrine\ORM\Query\AST\Functions\IdentityFunction',
|
||||||
);
|
);
|
||||||
|
|
||||||
/** READ-ONLY: Maps BUILT-IN numeric function names to AST class names. */
|
/** READ-ONLY: Maps BUILT-IN numeric function names to AST class names. */
|
||||||
@ -1695,6 +1696,7 @@ class Parser
|
|||||||
return $this->CoalesceExpression();
|
return $this->CoalesceExpression();
|
||||||
|
|
||||||
case Lexer::T_CASE:
|
case Lexer::T_CASE:
|
||||||
|
$this->_lexer->resetPeek();
|
||||||
$peek = $this->_lexer->peek();
|
$peek = $this->_lexer->peek();
|
||||||
|
|
||||||
return ($peek['type'] === Lexer::T_WHEN)
|
return ($peek['type'] === Lexer::T_WHEN)
|
||||||
@ -1829,7 +1831,7 @@ class Parser
|
|||||||
/**
|
/**
|
||||||
* SelectExpression ::=
|
* SelectExpression ::=
|
||||||
* IdentificationVariable | StateFieldPathExpression |
|
* IdentificationVariable | StateFieldPathExpression |
|
||||||
* (AggregateExpression | "(" Subselect ")" | ScalarExpression) [["AS"] AliasResultVariable]
|
* (AggregateExpression | "(" Subselect ")" | ScalarExpression) [["AS"] ["HIDDEN"] AliasResultVariable]
|
||||||
*
|
*
|
||||||
* @return Doctrine\ORM\Query\AST\SelectExpression
|
* @return Doctrine\ORM\Query\AST\SelectExpression
|
||||||
*/
|
*/
|
||||||
@ -1837,6 +1839,7 @@ class Parser
|
|||||||
{
|
{
|
||||||
$expression = null;
|
$expression = null;
|
||||||
$identVariable = null;
|
$identVariable = null;
|
||||||
|
$hiddenAliasResultVariable = false;
|
||||||
$fieldAliasIdentificationVariable = null;
|
$fieldAliasIdentificationVariable = null;
|
||||||
$peek = $this->_lexer->glimpse();
|
$peek = $this->_lexer->glimpse();
|
||||||
|
|
||||||
@ -1898,6 +1901,12 @@ class Parser
|
|||||||
if ($this->_lexer->isNextToken(Lexer::T_AS)) {
|
if ($this->_lexer->isNextToken(Lexer::T_AS)) {
|
||||||
$this->match(Lexer::T_AS);
|
$this->match(Lexer::T_AS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->_lexer->isNextToken(Lexer::T_HIDDEN)) {
|
||||||
|
$this->match(Lexer::T_HIDDEN);
|
||||||
|
|
||||||
|
$hiddenAliasResultVariable = true;
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->_lexer->isNextToken(Lexer::T_IDENTIFIER)) {
|
if ($this->_lexer->isNextToken(Lexer::T_IDENTIFIER)) {
|
||||||
$token = $this->_lexer->lookahead;
|
$token = $this->_lexer->lookahead;
|
||||||
@ -1912,10 +1921,12 @@ class Parser
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$expr = new AST\SelectExpression($expression, $fieldAliasIdentificationVariable);
|
$expr = new AST\SelectExpression($expression, $fieldAliasIdentificationVariable, $hiddenAliasResultVariable);
|
||||||
if (!$supportsAlias) {
|
|
||||||
|
if ( ! $supportsAlias) {
|
||||||
$this->_identVariableExpressions[$identVariable] = $expr;
|
$this->_identVariableExpressions[$identVariable] = $expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $expr;
|
return $expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2381,7 +2392,7 @@ class Parser
|
|||||||
/**
|
/**
|
||||||
* ArithmeticPrimary ::= SingleValuedPathExpression | Literal | "(" SimpleArithmeticExpression ")"
|
* ArithmeticPrimary ::= SingleValuedPathExpression | Literal | "(" SimpleArithmeticExpression ")"
|
||||||
* | FunctionsReturningNumerics | AggregateExpression | FunctionsReturningStrings
|
* | FunctionsReturningNumerics | AggregateExpression | FunctionsReturningStrings
|
||||||
* | FunctionsReturningDatetime | IdentificationVariable | CaseExpression
|
* | FunctionsReturningDatetime | IdentificationVariable | ResultVariable | CaseExpression
|
||||||
*/
|
*/
|
||||||
public function ArithmeticPrimary()
|
public function ArithmeticPrimary()
|
||||||
{
|
{
|
||||||
@ -2410,7 +2421,11 @@ class Parser
|
|||||||
if ($peek['value'] == '.') {
|
if ($peek['value'] == '.') {
|
||||||
return $this->SingleValuedPathExpression();
|
return $this->SingleValuedPathExpression();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isset($this->_queryComponents[$this->_lexer->lookahead['value']]['resultVariable'])) {
|
||||||
|
return $this->ResultVariable();
|
||||||
|
}
|
||||||
|
|
||||||
return $this->StateFieldPathExpression();
|
return $this->StateFieldPathExpression();
|
||||||
|
|
||||||
case Lexer::T_INPUT_PARAMETER:
|
case Lexer::T_INPUT_PARAMETER:
|
||||||
|
@ -244,24 +244,23 @@ class SqlWalker implements TreeWalker
|
|||||||
{
|
{
|
||||||
$sql = '';
|
$sql = '';
|
||||||
|
|
||||||
$baseTableAlias = $this->getSQLTableAlias($class->table['name'], $dqlAlias);
|
$baseTableAlias = $this->getSQLTableAlias($class->getTableName(), $dqlAlias);
|
||||||
|
|
||||||
// INNER JOIN parent class tables
|
// INNER JOIN parent class tables
|
||||||
foreach ($class->parentClasses as $parentClassName) {
|
foreach ($class->parentClasses as $parentClassName) {
|
||||||
$parentClass = $this->_em->getClassMetadata($parentClassName);
|
$parentClass = $this->_em->getClassMetadata($parentClassName);
|
||||||
$tableAlias = $this->getSQLTableAlias($parentClass->table['name'], $dqlAlias);
|
$tableAlias = $this->getSQLTableAlias($parentClass->getTableName(), $dqlAlias);
|
||||||
|
|
||||||
// If this is a joined association we must use left joins to preserve the correct result.
|
// If this is a joined association we must use left joins to preserve the correct result.
|
||||||
$sql .= isset($this->_queryComponents[$dqlAlias]['relation']) ? ' LEFT ' : ' INNER ';
|
$sql .= isset($this->_queryComponents[$dqlAlias]['relation']) ? ' LEFT ' : ' INNER ';
|
||||||
$sql .= 'JOIN ' . $parentClass->getQuotedTableName($this->_platform)
|
$sql .= 'JOIN ' . $parentClass->getQuotedTableName($this->_platform) . ' ' . $tableAlias . ' ON ';
|
||||||
. ' ' . $tableAlias . ' ON ';
|
|
||||||
$first = true;
|
$first = true;
|
||||||
|
|
||||||
foreach ($class->identifier as $idField) {
|
foreach ($class->identifier as $idField) {
|
||||||
if ($first) $first = false; else $sql .= ' AND ';
|
if ($first) $first = false; else $sql .= ' AND ';
|
||||||
|
|
||||||
$columnName = $class->getQuotedColumnName($idField, $this->_platform);
|
$columnName = $class->getQuotedColumnName($idField, $this->_platform);
|
||||||
$sql .= $baseTableAlias . '.' . $columnName
|
$sql .= $baseTableAlias . '.' . $columnName . ' = ' . $tableAlias . '.' . $columnName;
|
||||||
. ' = '
|
|
||||||
. $tableAlias . '.' . $columnName;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -269,17 +268,15 @@ class SqlWalker implements TreeWalker
|
|||||||
if ( ! $this->_query->getHint(Query::HINT_FORCE_PARTIAL_LOAD)) {
|
if ( ! $this->_query->getHint(Query::HINT_FORCE_PARTIAL_LOAD)) {
|
||||||
foreach ($class->subClasses as $subClassName) {
|
foreach ($class->subClasses as $subClassName) {
|
||||||
$subClass = $this->_em->getClassMetadata($subClassName);
|
$subClass = $this->_em->getClassMetadata($subClassName);
|
||||||
$tableAlias = $this->getSQLTableAlias($subClass->table['name'], $dqlAlias);
|
$tableAlias = $this->getSQLTableAlias($subClass->getTableName(), $dqlAlias);
|
||||||
$sql .= ' LEFT JOIN ' . $subClass->getQuotedTableName($this->_platform)
|
$sql .= ' LEFT JOIN ' . $subClass->getQuotedTableName($this->_platform) . ' ' . $tableAlias . ' ON ';
|
||||||
. ' ' . $tableAlias . ' ON ';
|
|
||||||
$first = true;
|
$first = true;
|
||||||
|
|
||||||
foreach ($class->identifier as $idField) {
|
foreach ($class->identifier as $idField) {
|
||||||
if ($first) $first = false; else $sql .= ' AND ';
|
if ($first) $first = false; else $sql .= ' AND ';
|
||||||
|
|
||||||
$columnName = $class->getQuotedColumnName($idField, $this->_platform);
|
$columnName = $class->getQuotedColumnName($idField, $this->_platform);
|
||||||
$sql .= $baseTableAlias . '.' . $columnName
|
$sql .= $baseTableAlias . '.' . $columnName . ' = ' . $tableAlias . '.' . $columnName;
|
||||||
. ' = '
|
|
||||||
. $tableAlias . '.' . $columnName;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -290,24 +287,26 @@ class SqlWalker implements TreeWalker
|
|||||||
private function _generateOrderedCollectionOrderByItems()
|
private function _generateOrderedCollectionOrderByItems()
|
||||||
{
|
{
|
||||||
$sql = '';
|
$sql = '';
|
||||||
|
|
||||||
foreach ($this->_selectedClasses AS $dqlAlias => $class) {
|
foreach ($this->_selectedClasses AS $dqlAlias => $class) {
|
||||||
$qComp = $this->_queryComponents[$dqlAlias];
|
$qComp = $this->_queryComponents[$dqlAlias];
|
||||||
|
|
||||||
if (isset($qComp['relation']['orderBy'])) {
|
if (isset($qComp['relation']['orderBy'])) {
|
||||||
foreach ($qComp['relation']['orderBy'] AS $fieldName => $orientation) {
|
foreach ($qComp['relation']['orderBy'] AS $fieldName => $orientation) {
|
||||||
if ($qComp['metadata']->isInheritanceTypeJoined()) {
|
$tableName = ($qComp['metadata']->isInheritanceTypeJoined())
|
||||||
$tableName = $this->_em->getUnitOfWork()->getEntityPersister($class->name)->getOwningTable($fieldName);
|
? $this->_em->getUnitOfWork()->getEntityPersister($class->name)->getOwningTable($fieldName)
|
||||||
} else {
|
: $qComp['metadata']->getTableName();
|
||||||
$tableName = $qComp['metadata']->table['name'];
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($sql != '') {
|
if ($sql != '') {
|
||||||
$sql .= ', ';
|
$sql .= ', ';
|
||||||
}
|
}
|
||||||
$sql .= $this->getSQLTableAlias($tableName, $dqlAlias) . '.' .
|
|
||||||
$qComp['metadata']->getQuotedColumnName($fieldName, $this->_platform) . " $orientation";
|
$sql .= $this->getSQLTableAlias($tableName, $dqlAlias) . '.'
|
||||||
|
. $qComp['metadata']->getQuotedColumnName($fieldName, $this->_platform) . ' ' . $orientation;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $sql;
|
return $sql;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -328,6 +327,7 @@ class SqlWalker implements TreeWalker
|
|||||||
if ($class->isInheritanceTypeSingleTable()) {
|
if ($class->isInheritanceTypeSingleTable()) {
|
||||||
$conn = $this->_em->getConnection();
|
$conn = $this->_em->getConnection();
|
||||||
$values = array();
|
$values = array();
|
||||||
|
|
||||||
if ($class->discriminatorValue !== null) { // discrimnators can be 0
|
if ($class->discriminatorValue !== null) { // discrimnators can be 0
|
||||||
$values[] = $conn->quote($class->discriminatorValue);
|
$values[] = $conn->quote($class->discriminatorValue);
|
||||||
}
|
}
|
||||||
@ -342,7 +342,7 @@ class SqlWalker implements TreeWalker
|
|||||||
}
|
}
|
||||||
|
|
||||||
$sql .= ($sql != '' ? ' AND ' : '')
|
$sql .= ($sql != '' ? ' AND ' : '')
|
||||||
. (($this->_useSqlTableAliases) ? $this->getSQLTableAlias($class->table['name'], $dqlAlias) . '.' : '')
|
. (($this->_useSqlTableAliases) ? $this->getSQLTableAlias($class->getTableName(), $dqlAlias) . '.' : '')
|
||||||
. $class->discriminatorColumn['name'] . ' IN (' . implode(', ', $values) . ')';
|
. $class->discriminatorColumn['name'] . ' IN (' . implode(', ', $values) . ')';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -373,7 +373,7 @@ class SqlWalker implements TreeWalker
|
|||||||
*/
|
*/
|
||||||
public function walkSelectStatement(AST\SelectStatement $AST)
|
public function walkSelectStatement(AST\SelectStatement $AST)
|
||||||
{
|
{
|
||||||
$sql = $this->walkSelectClause($AST->selectClause);
|
$sql = $this->walkSelectClause($AST->selectClause);
|
||||||
$sql .= $this->walkFromClause($AST->fromClause);
|
$sql .= $this->walkFromClause($AST->fromClause);
|
||||||
$sql .= $this->walkWhereClause($AST->whereClause);
|
$sql .= $this->walkWhereClause($AST->whereClause);
|
||||||
$sql .= $AST->groupByClause ? $this->walkGroupByClause($AST->groupByClause) : '';
|
$sql .= $AST->groupByClause ? $this->walkGroupByClause($AST->groupByClause) : '';
|
||||||
@ -382,19 +382,18 @@ class SqlWalker implements TreeWalker
|
|||||||
if (($orderByClause = $AST->orderByClause) !== null) {
|
if (($orderByClause = $AST->orderByClause) !== null) {
|
||||||
$sql .= $AST->orderByClause ? $this->walkOrderByClause($AST->orderByClause) : '';
|
$sql .= $AST->orderByClause ? $this->walkOrderByClause($AST->orderByClause) : '';
|
||||||
} else if (($orderBySql = $this->_generateOrderedCollectionOrderByItems()) !== '') {
|
} else if (($orderBySql = $this->_generateOrderedCollectionOrderByItems()) !== '') {
|
||||||
$sql .= ' ORDER BY '.$orderBySql;
|
$sql .= ' ORDER BY ' . $orderBySql;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$sql = $this->_platform->modifyLimitQuery(
|
$sql = $this->_platform->modifyLimitQuery(
|
||||||
$sql, $this->_query->getMaxResults(), $this->_query->getFirstResult()
|
$sql, $this->_query->getMaxResults(), $this->_query->getFirstResult()
|
||||||
);
|
);
|
||||||
|
|
||||||
if (($lockMode = $this->_query->getHint(Query::HINT_LOCK_MODE)) !== false) {
|
if (($lockMode = $this->_query->getHint(Query::HINT_LOCK_MODE)) !== false) {
|
||||||
if ($lockMode == LockMode::PESSIMISTIC_READ) {
|
if ($lockMode == LockMode::PESSIMISTIC_READ) {
|
||||||
$sql .= " " . $this->_platform->getReadLockSQL();
|
$sql .= ' ' . $this->_platform->getReadLockSQL();
|
||||||
} else if ($lockMode == LockMode::PESSIMISTIC_WRITE) {
|
} else if ($lockMode == LockMode::PESSIMISTIC_WRITE) {
|
||||||
$sql .= " " . $this->_platform->getWriteLockSQL();
|
$sql .= ' ' . $this->_platform->getWriteLockSQL();
|
||||||
} else if ($lockMode == LockMode::OPTIMISTIC) {
|
} else if ($lockMode == LockMode::OPTIMISTIC) {
|
||||||
foreach ($this->_selectedClasses AS $class) {
|
foreach ($this->_selectedClasses AS $class) {
|
||||||
if ( ! $class->isVersioned) {
|
if ( ! $class->isVersioned) {
|
||||||
@ -416,10 +415,8 @@ class SqlWalker implements TreeWalker
|
|||||||
public function walkUpdateStatement(AST\UpdateStatement $AST)
|
public function walkUpdateStatement(AST\UpdateStatement $AST)
|
||||||
{
|
{
|
||||||
$this->_useSqlTableAliases = false;
|
$this->_useSqlTableAliases = false;
|
||||||
$sql = $this->walkUpdateClause($AST->updateClause);
|
|
||||||
$sql .= $this->walkWhereClause($AST->whereClause);
|
return $this->walkUpdateClause($AST->updateClause) . $this->walkWhereClause($AST->whereClause);
|
||||||
|
|
||||||
return $sql;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -431,10 +428,8 @@ class SqlWalker implements TreeWalker
|
|||||||
public function walkDeleteStatement(AST\DeleteStatement $AST)
|
public function walkDeleteStatement(AST\DeleteStatement $AST)
|
||||||
{
|
{
|
||||||
$this->_useSqlTableAliases = false;
|
$this->_useSqlTableAliases = false;
|
||||||
$sql = $this->walkDeleteClause($AST->deleteClause);
|
|
||||||
$sql .= $this->walkWhereClause($AST->whereClause);
|
return $this->walkDeleteClause($AST->deleteClause) . $this->walkWhereClause($AST->whereClause);
|
||||||
|
|
||||||
return $sql;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -456,7 +451,7 @@ class SqlWalker implements TreeWalker
|
|||||||
$class = $this->_em->getClassMetadata($class->fieldMappings[$fieldName]['inherited']);
|
$class = $this->_em->getClassMetadata($class->fieldMappings[$fieldName]['inherited']);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->getSQLTableAlias($class->table['name'], $identificationVariable);
|
return $this->getSQLTableAlias($class->getTableName(), $identificationVariable);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -505,7 +500,7 @@ class SqlWalker implements TreeWalker
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($this->_useSqlTableAliases) {
|
if ($this->_useSqlTableAliases) {
|
||||||
$sql .= $this->getSQLTableAlias($class->table['name'], $dqlAlias) . '.';
|
$sql .= $this->getSQLTableAlias($class->getTableName(), $dqlAlias) . '.';
|
||||||
}
|
}
|
||||||
|
|
||||||
$sql .= reset($assoc['targetToSourceKeyColumns']);
|
$sql .= reset($assoc['targetToSourceKeyColumns']);
|
||||||
@ -550,7 +545,7 @@ class SqlWalker implements TreeWalker
|
|||||||
if ($class->isInheritanceTypeSingleTable() || $class->isInheritanceTypeJoined()) {
|
if ($class->isInheritanceTypeSingleTable() || $class->isInheritanceTypeJoined()) {
|
||||||
// Add discriminator columns to SQL
|
// Add discriminator columns to SQL
|
||||||
$rootClass = $this->_em->getClassMetadata($class->rootEntityName);
|
$rootClass = $this->_em->getClassMetadata($class->rootEntityName);
|
||||||
$tblAlias = $this->getSQLTableAlias($rootClass->table['name'], $dqlAlias);
|
$tblAlias = $this->getSQLTableAlias($rootClass->getTableName(), $dqlAlias);
|
||||||
$discrColumn = $rootClass->discriminatorColumn;
|
$discrColumn = $rootClass->discriminatorColumn;
|
||||||
$columnAlias = $this->getSQLColumnAlias($discrColumn['name']);
|
$columnAlias = $this->getSQLColumnAlias($discrColumn['name']);
|
||||||
|
|
||||||
@ -567,9 +562,9 @@ class SqlWalker implements TreeWalker
|
|||||||
if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) {
|
if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) {
|
||||||
if (isset($assoc['inherited'])) {
|
if (isset($assoc['inherited'])) {
|
||||||
$owningClass = $this->_em->getClassMetadata($assoc['inherited']);
|
$owningClass = $this->_em->getClassMetadata($assoc['inherited']);
|
||||||
$sqlTableAlias = $this->getSQLTableAlias($owningClass->table['name'], $dqlAlias);
|
$sqlTableAlias = $this->getSQLTableAlias($owningClass->getTableName(), $dqlAlias);
|
||||||
} else {
|
} else {
|
||||||
$sqlTableAlias = $this->getSQLTableAlias($class->table['name'], $dqlAlias);
|
$sqlTableAlias = $this->getSQLTableAlias($class->getTableName(), $dqlAlias);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($assoc['targetToSourceKeyColumns'] as $srcColumn) {
|
foreach ($assoc['targetToSourceKeyColumns'] as $srcColumn) {
|
||||||
@ -586,7 +581,8 @@ class SqlWalker implements TreeWalker
|
|||||||
} else {
|
} else {
|
||||||
// Add foreign key columns to SQL, if necessary
|
// Add foreign key columns to SQL, if necessary
|
||||||
if ($addMetaColumns) {
|
if ($addMetaColumns) {
|
||||||
$sqlTableAlias = $this->getSQLTableAlias($class->table['name'], $dqlAlias);
|
$sqlTableAlias = $this->getSQLTableAlias($class->getTableName(), $dqlAlias);
|
||||||
|
|
||||||
foreach ($class->associationMappings as $assoc) {
|
foreach ($class->associationMappings as $assoc) {
|
||||||
if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) {
|
if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) {
|
||||||
foreach ($assoc['targetToSourceKeyColumns'] as $srcColumn) {
|
foreach ($assoc['targetToSourceKeyColumns'] as $srcColumn) {
|
||||||
@ -628,7 +624,7 @@ class SqlWalker implements TreeWalker
|
|||||||
|
|
||||||
$class = $this->_em->getClassMetadata($rangeDecl->abstractSchemaName);
|
$class = $this->_em->getClassMetadata($rangeDecl->abstractSchemaName);
|
||||||
$sql .= $class->getQuotedTableName($this->_platform) . ' '
|
$sql .= $class->getQuotedTableName($this->_platform) . ' '
|
||||||
. $this->getSQLTableAlias($class->table['name'], $dqlAlias);
|
. $this->getSQLTableAlias($class->getTableName(), $dqlAlias);
|
||||||
|
|
||||||
if ($class->isInheritanceTypeJoined()) {
|
if ($class->isInheritanceTypeJoined()) {
|
||||||
$sql .= $this->_generateClassTableInheritanceJoins($class, $dqlAlias);
|
$sql .= $this->_generateClassTableInheritanceJoins($class, $dqlAlias);
|
||||||
@ -739,13 +735,15 @@ class SqlWalker implements TreeWalker
|
|||||||
}
|
}
|
||||||
|
|
||||||
$joinAssocPathExpr = $join->joinAssociationPathExpression;
|
$joinAssocPathExpr = $join->joinAssociationPathExpression;
|
||||||
$joinedDqlAlias = $join->aliasIdentificationVariable;
|
$joinedDqlAlias = $join->aliasIdentificationVariable;
|
||||||
$relation = $this->_queryComponents[$joinedDqlAlias]['relation'];
|
|
||||||
$targetClass = $this->_em->getClassMetadata($relation['targetEntity']);
|
$relation = $this->_queryComponents[$joinedDqlAlias]['relation'];
|
||||||
$sourceClass = $this->_em->getClassMetadata($relation['sourceEntity']);
|
$targetClass = $this->_em->getClassMetadata($relation['targetEntity']);
|
||||||
|
$sourceClass = $this->_em->getClassMetadata($relation['sourceEntity']);
|
||||||
$targetTableName = $targetClass->getQuotedTableName($this->_platform);
|
$targetTableName = $targetClass->getQuotedTableName($this->_platform);
|
||||||
$targetTableAlias = $this->getSQLTableAlias($targetClass->table['name'], $joinedDqlAlias);
|
|
||||||
$sourceTableAlias = $this->getSQLTableAlias($sourceClass->table['name'], $joinAssocPathExpr->identificationVariable);
|
$targetTableAlias = $this->getSQLTableAlias($targetClass->getTableName(), $joinedDqlAlias);
|
||||||
|
$sourceTableAlias = $this->getSQLTableAlias($sourceClass->getTableName(), $joinAssocPathExpr->identificationVariable);
|
||||||
|
|
||||||
// Ensure we got the owning side, since it has all mapping info
|
// Ensure we got the owning side, since it has all mapping info
|
||||||
$assoc = ( ! $relation['isOwningSide']) ? $targetClass->associationMappings[$relation['mappedBy']] : $relation;
|
$assoc = ( ! $relation['isOwningSide']) ? $targetClass->associationMappings[$relation['mappedBy']] : $relation;
|
||||||
@ -833,8 +831,7 @@ class SqlWalker implements TreeWalker
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Join target table
|
// Join target table
|
||||||
$sql .= ($joinType == AST\Join::JOIN_TYPE_LEFT || $joinType == AST\Join::JOIN_TYPE_LEFTOUTER)
|
$sql .= ($joinType == AST\Join::JOIN_TYPE_LEFT || $joinType == AST\Join::JOIN_TYPE_LEFTOUTER) ? ' LEFT JOIN ' : ' INNER JOIN ';
|
||||||
? ' LEFT JOIN ' : ' INNER JOIN ';
|
|
||||||
$sql .= $targetTableName . ' ' . $targetTableAlias . ' ON ';
|
$sql .= $targetTableName . ' ' . $targetTableAlias . ' ON ';
|
||||||
|
|
||||||
$first = true;
|
$first = true;
|
||||||
@ -1006,8 +1003,9 @@ class SqlWalker implements TreeWalker
|
|||||||
*/
|
*/
|
||||||
public function walkSelectExpression($selectExpression)
|
public function walkSelectExpression($selectExpression)
|
||||||
{
|
{
|
||||||
$sql = '';
|
$sql = '';
|
||||||
$expr = $selectExpression->expression;
|
$expr = $selectExpression->expression;
|
||||||
|
$hidden = $selectExpression->hiddenAliasResultVariable;
|
||||||
|
|
||||||
if ($expr instanceof AST\PathExpression) {
|
if ($expr instanceof AST\PathExpression) {
|
||||||
if ($expr->type !== AST\PathExpression::TYPE_STATE_FIELD) {
|
if ($expr->type !== AST\PathExpression::TYPE_STATE_FIELD) {
|
||||||
@ -1037,7 +1035,10 @@ class SqlWalker implements TreeWalker
|
|||||||
$columnAlias = $this->getSQLColumnAlias($columnName);
|
$columnAlias = $this->getSQLColumnAlias($columnName);
|
||||||
$sql .= $sqlTableAlias . '.' . $columnName . ' AS ' . $columnAlias;
|
$sql .= $sqlTableAlias . '.' . $columnName . ' AS ' . $columnAlias;
|
||||||
$columnAlias = $this->_platform->getSQLResultCasing($columnAlias);
|
$columnAlias = $this->_platform->getSQLResultCasing($columnAlias);
|
||||||
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
|
|
||||||
|
if ( ! $hidden) {
|
||||||
|
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
|
||||||
|
}
|
||||||
} else if ($expr instanceof AST\AggregateExpression) {
|
} else if ($expr instanceof AST\AggregateExpression) {
|
||||||
if ( ! $selectExpression->fieldIdentificationVariable) {
|
if ( ! $selectExpression->fieldIdentificationVariable) {
|
||||||
$resultAlias = $this->_scalarResultCounter++;
|
$resultAlias = $this->_scalarResultCounter++;
|
||||||
@ -1050,7 +1051,10 @@ class SqlWalker implements TreeWalker
|
|||||||
$this->_scalarResultAliasMap[$resultAlias] = $columnAlias;
|
$this->_scalarResultAliasMap[$resultAlias] = $columnAlias;
|
||||||
|
|
||||||
$columnAlias = $this->_platform->getSQLResultCasing($columnAlias);
|
$columnAlias = $this->_platform->getSQLResultCasing($columnAlias);
|
||||||
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
|
|
||||||
|
if ( ! $hidden) {
|
||||||
|
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
|
||||||
|
}
|
||||||
} else if ($expr instanceof AST\Subselect) {
|
} else if ($expr instanceof AST\Subselect) {
|
||||||
if ( ! $selectExpression->fieldIdentificationVariable) {
|
if ( ! $selectExpression->fieldIdentificationVariable) {
|
||||||
$resultAlias = $this->_scalarResultCounter++;
|
$resultAlias = $this->_scalarResultCounter++;
|
||||||
@ -1063,7 +1067,10 @@ class SqlWalker implements TreeWalker
|
|||||||
$this->_scalarResultAliasMap[$resultAlias] = $columnAlias;
|
$this->_scalarResultAliasMap[$resultAlias] = $columnAlias;
|
||||||
|
|
||||||
$columnAlias = $this->_platform->getSQLResultCasing($columnAlias);
|
$columnAlias = $this->_platform->getSQLResultCasing($columnAlias);
|
||||||
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
|
|
||||||
|
if ( ! $hidden) {
|
||||||
|
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
|
||||||
|
}
|
||||||
} else if ($expr instanceof AST\Functions\FunctionNode) {
|
} else if ($expr instanceof AST\Functions\FunctionNode) {
|
||||||
if ( ! $selectExpression->fieldIdentificationVariable) {
|
if ( ! $selectExpression->fieldIdentificationVariable) {
|
||||||
$resultAlias = $this->_scalarResultCounter++;
|
$resultAlias = $this->_scalarResultCounter++;
|
||||||
@ -1076,7 +1083,10 @@ class SqlWalker implements TreeWalker
|
|||||||
$this->_scalarResultAliasMap[$resultAlias] = $columnAlias;
|
$this->_scalarResultAliasMap[$resultAlias] = $columnAlias;
|
||||||
|
|
||||||
$columnAlias = $this->_platform->getSQLResultCasing($columnAlias);
|
$columnAlias = $this->_platform->getSQLResultCasing($columnAlias);
|
||||||
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
|
|
||||||
|
if ( ! $hidden) {
|
||||||
|
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
|
||||||
|
}
|
||||||
} else if (
|
} else if (
|
||||||
$expr instanceof AST\SimpleArithmeticExpression ||
|
$expr instanceof AST\SimpleArithmeticExpression ||
|
||||||
$expr instanceof AST\ArithmeticTerm ||
|
$expr instanceof AST\ArithmeticTerm ||
|
||||||
@ -1101,7 +1111,10 @@ class SqlWalker implements TreeWalker
|
|||||||
$this->_scalarResultAliasMap[$resultAlias] = $columnAlias;
|
$this->_scalarResultAliasMap[$resultAlias] = $columnAlias;
|
||||||
|
|
||||||
$columnAlias = $this->_platform->getSQLResultCasing($columnAlias);
|
$columnAlias = $this->_platform->getSQLResultCasing($columnAlias);
|
||||||
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
|
|
||||||
|
if ( ! $hidden) {
|
||||||
|
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
|
||||||
|
}
|
||||||
} else if (
|
} else if (
|
||||||
$expr instanceof AST\NullIfExpression ||
|
$expr instanceof AST\NullIfExpression ||
|
||||||
$expr instanceof AST\CoalesceExpression ||
|
$expr instanceof AST\CoalesceExpression ||
|
||||||
@ -1121,7 +1134,10 @@ class SqlWalker implements TreeWalker
|
|||||||
$this->_scalarResultAliasMap[$resultAlias] = $columnAlias;
|
$this->_scalarResultAliasMap[$resultAlias] = $columnAlias;
|
||||||
|
|
||||||
$columnAlias = $this->_platform->getSQLResultCasing($columnAlias);
|
$columnAlias = $this->_platform->getSQLResultCasing($columnAlias);
|
||||||
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
|
|
||||||
|
if ( ! $hidden) {
|
||||||
|
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// IdentificationVariable or PartialObjectExpression
|
// IdentificationVariable or PartialObjectExpression
|
||||||
if ($expr instanceof AST\PartialObjectExpression) {
|
if ($expr instanceof AST\PartialObjectExpression) {
|
||||||
@ -1146,11 +1162,9 @@ class SqlWalker implements TreeWalker
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($mapping['inherited'])) {
|
$tableName = (isset($mapping['inherited']))
|
||||||
$tableName = $this->_em->getClassMetadata($mapping['inherited'])->table['name'];
|
? $this->_em->getClassMetadata($mapping['inherited'])->getTableName()
|
||||||
} else {
|
: $class->getTableName();
|
||||||
$tableName = $class->table['name'];
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($beginning) $beginning = false; else $sql .= ', ';
|
if ($beginning) $beginning = false; else $sql .= ', ';
|
||||||
|
|
||||||
@ -1170,7 +1184,7 @@ class SqlWalker implements TreeWalker
|
|||||||
if ($class->isInheritanceTypeSingleTable() || ! $this->_query->getHint(Query::HINT_FORCE_PARTIAL_LOAD)) {
|
if ($class->isInheritanceTypeSingleTable() || ! $this->_query->getHint(Query::HINT_FORCE_PARTIAL_LOAD)) {
|
||||||
foreach ($class->subClasses as $subClassName) {
|
foreach ($class->subClasses as $subClassName) {
|
||||||
$subClass = $this->_em->getClassMetadata($subClassName);
|
$subClass = $this->_em->getClassMetadata($subClassName);
|
||||||
$sqlTableAlias = $this->getSQLTableAlias($subClass->table['name'], $dqlAlias);
|
$sqlTableAlias = $this->getSQLTableAlias($subClass->getTableName(), $dqlAlias);
|
||||||
foreach ($subClass->fieldMappings as $fieldName => $mapping) {
|
foreach ($subClass->fieldMappings as $fieldName => $mapping) {
|
||||||
if (isset($mapping['inherited']) || $partialFieldSet && !in_array($fieldName, $partialFieldSet)) {
|
if (isset($mapping['inherited']) || $partialFieldSet && !in_array($fieldName, $partialFieldSet)) {
|
||||||
continue;
|
continue;
|
||||||
@ -1263,7 +1277,7 @@ class SqlWalker implements TreeWalker
|
|||||||
|
|
||||||
$class = $this->_em->getClassMetadata($rangeDecl->abstractSchemaName);
|
$class = $this->_em->getClassMetadata($rangeDecl->abstractSchemaName);
|
||||||
$sql .= $class->getQuotedTableName($this->_platform) . ' '
|
$sql .= $class->getQuotedTableName($this->_platform) . ' '
|
||||||
. $this->getSQLTableAlias($class->table['name'], $dqlAlias);
|
. $this->getSQLTableAlias($class->getTableName(), $dqlAlias);
|
||||||
|
|
||||||
$this->_rootAliases[] = $dqlAlias;
|
$this->_rootAliases[] = $dqlAlias;
|
||||||
|
|
||||||
@ -1348,6 +1362,22 @@ class SqlWalker implements TreeWalker
|
|||||||
|
|
||||||
$columnAlias = 'sclr' . $this->_aliasCounter++;
|
$columnAlias = 'sclr' . $this->_aliasCounter++;
|
||||||
$sql .= $this->walkSimpleArithmeticExpression($expr) . ' AS ' . $columnAlias;
|
$sql .= $this->walkSimpleArithmeticExpression($expr) . ' AS ' . $columnAlias;
|
||||||
|
$this->_scalarResultAliasMap[$alias] = $columnAlias;
|
||||||
|
} else if (
|
||||||
|
$expr instanceof AST\NullIfExpression ||
|
||||||
|
$expr instanceof AST\CoalesceExpression ||
|
||||||
|
$expr instanceof AST\GeneralCaseExpression ||
|
||||||
|
$expr instanceof AST\SimpleCaseExpression
|
||||||
|
) {
|
||||||
|
if ( ! $simpleSelectExpression->fieldIdentificationVariable) {
|
||||||
|
$alias = $this->_scalarResultCounter++;
|
||||||
|
} else {
|
||||||
|
$alias = $simpleSelectExpression->fieldIdentificationVariable;
|
||||||
|
}
|
||||||
|
|
||||||
|
$columnAlias = 'sclr' . $this->_aliasCounter++;
|
||||||
|
$sql .= $this->walkCaseExpression($expr) . ' AS ' . $columnAlias;
|
||||||
|
|
||||||
$this->_scalarResultAliasMap[$alias] = $columnAlias;
|
$this->_scalarResultAliasMap[$alias] = $columnAlias;
|
||||||
} else {
|
} else {
|
||||||
// IdentificationVariable
|
// IdentificationVariable
|
||||||
@ -1637,15 +1667,13 @@ class SqlWalker implements TreeWalker
|
|||||||
$assoc = $class->associationMappings[$fieldName];
|
$assoc = $class->associationMappings[$fieldName];
|
||||||
|
|
||||||
if ($assoc['type'] == ClassMetadata::ONE_TO_MANY) {
|
if ($assoc['type'] == ClassMetadata::ONE_TO_MANY) {
|
||||||
$targetClass = $this->_em->getClassMetadata($assoc['targetEntity']);
|
$targetClass = $this->_em->getClassMetadata($assoc['targetEntity']);
|
||||||
$targetTableAlias = $this->getSQLTableAlias($targetClass->table['name']);
|
$targetTableAlias = $this->getSQLTableAlias($targetClass->getTableName());
|
||||||
$sourceTableAlias = $this->getSQLTableAlias($class->table['name'], $dqlAlias);
|
$sourceTableAlias = $this->getSQLTableAlias($class->getTableName(), $dqlAlias);
|
||||||
|
|
||||||
$sql .= $targetClass->getQuotedTableName($this->_platform)
|
$sql .= $targetClass->getQuotedTableName($this->_platform) . ' ' . $targetTableAlias . ' WHERE ';
|
||||||
. ' ' . $targetTableAlias . ' WHERE ';
|
|
||||||
|
|
||||||
$owningAssoc = $targetClass->associationMappings[$assoc['mappedBy']];
|
$owningAssoc = $targetClass->associationMappings[$assoc['mappedBy']];
|
||||||
|
|
||||||
$first = true;
|
$first = true;
|
||||||
|
|
||||||
foreach ($owningAssoc['targetToSourceKeyColumns'] as $targetColumn => $sourceColumn) {
|
foreach ($owningAssoc['targetToSourceKeyColumns'] as $targetColumn => $sourceColumn) {
|
||||||
@ -1673,15 +1701,13 @@ class SqlWalker implements TreeWalker
|
|||||||
$joinTable = $owningAssoc['joinTable'];
|
$joinTable = $owningAssoc['joinTable'];
|
||||||
|
|
||||||
// SQL table aliases
|
// SQL table aliases
|
||||||
$joinTableAlias = $this->getSQLTableAlias($joinTable['name']);
|
$joinTableAlias = $this->getSQLTableAlias($joinTable['name']);
|
||||||
$targetTableAlias = $this->getSQLTableAlias($targetClass->table['name']);
|
$targetTableAlias = $this->getSQLTableAlias($targetClass->getTableName());
|
||||||
$sourceTableAlias = $this->getSQLTableAlias($class->table['name'], $dqlAlias);
|
$sourceTableAlias = $this->getSQLTableAlias($class->getTableName(), $dqlAlias);
|
||||||
|
|
||||||
// join to target table
|
// join to target table
|
||||||
$sql .= $targetClass->getQuotedJoinTableName($owningAssoc, $this->_platform)
|
$sql .= $targetClass->getQuotedJoinTableName($owningAssoc, $this->_platform) . ' ' . $joinTableAlias
|
||||||
. ' ' . $joinTableAlias . ' INNER JOIN '
|
. ' INNER JOIN ' . $targetClass->getQuotedTableName($this->_platform) . ' ' . $targetTableAlias . ' ON ';
|
||||||
. $targetClass->getQuotedTableName($this->_platform)
|
|
||||||
. ' ' . $targetTableAlias . ' ON ';
|
|
||||||
|
|
||||||
// join conditions
|
// join conditions
|
||||||
$joinColumns = $assoc['isOwningSide']
|
$joinColumns = $assoc['isOwningSide']
|
||||||
@ -1693,25 +1719,19 @@ class SqlWalker implements TreeWalker
|
|||||||
if ($first) $first = false; else $sql .= ' AND ';
|
if ($first) $first = false; else $sql .= ' AND ';
|
||||||
|
|
||||||
$sql .= $joinTableAlias . '.' . $joinColumn['name'] . ' = '
|
$sql .= $joinTableAlias . '.' . $joinColumn['name'] . ' = '
|
||||||
. $targetTableAlias . '.' . $targetClass->getQuotedColumnName(
|
. $targetTableAlias . '.' . $targetClass->getQuotedColumnName($targetClass->fieldNames[$joinColumn['referencedColumnName']], $this->_platform);
|
||||||
$targetClass->fieldNames[$joinColumn['referencedColumnName']],
|
|
||||||
$this->_platform);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$sql .= ' WHERE ';
|
$sql .= ' WHERE ';
|
||||||
|
|
||||||
$joinColumns = $assoc['isOwningSide']
|
$joinColumns = $assoc['isOwningSide'] ? $joinTable['joinColumns'] : $joinTable['inverseJoinColumns'];
|
||||||
? $joinTable['joinColumns']
|
|
||||||
: $joinTable['inverseJoinColumns'];
|
|
||||||
|
|
||||||
$first = true;
|
$first = true;
|
||||||
|
|
||||||
foreach ($joinColumns as $joinColumn) {
|
foreach ($joinColumns as $joinColumn) {
|
||||||
if ($first) $first = false; else $sql .= ' AND ';
|
if ($first) $first = false; else $sql .= ' AND ';
|
||||||
|
|
||||||
$sql .= $joinTableAlias . '.' . $joinColumn['name'] . ' = '
|
$sql .= $joinTableAlias . '.' . $joinColumn['name'] . ' = '
|
||||||
. $sourceTableAlias . '.' . $class->getQuotedColumnName(
|
. $sourceTableAlias . '.' . $class->getQuotedColumnName($class->fieldNames[$joinColumn['referencedColumnName']], $this->_platform);
|
||||||
$class->fieldNames[$joinColumn['referencedColumnName']],
|
|
||||||
$this->_platform);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$sql .= ' AND ';
|
$sql .= ' AND ';
|
||||||
@ -1808,7 +1828,7 @@ class SqlWalker implements TreeWalker
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($this->_useSqlTableAliases) {
|
if ($this->_useSqlTableAliases) {
|
||||||
$sql .= $this->getSQLTableAlias($discrClass->table['name'], $dqlAlias) . '.';
|
$sql .= $this->getSQLTableAlias($discrClass->getTableName(), $dqlAlias) . '.';
|
||||||
}
|
}
|
||||||
|
|
||||||
$sql .= $class->discriminatorColumn['name'] . ($instanceOfExpr->not ? ' NOT IN ' : ' IN ');
|
$sql .= $class->discriminatorColumn['name'] . ($instanceOfExpr->not ? ' NOT IN ' : ' IN ');
|
||||||
@ -2019,6 +2039,12 @@ class SqlWalker implements TreeWalker
|
|||||||
public function walkArithmeticTerm($term)
|
public function walkArithmeticTerm($term)
|
||||||
{
|
{
|
||||||
if (is_string($term)) {
|
if (is_string($term)) {
|
||||||
|
if (isset($this->_queryComponents[$term])) {
|
||||||
|
$columnName = $this->_queryComponents[$term]['token']['value'];
|
||||||
|
|
||||||
|
return $this->_scalarResultAliasMap[$columnName];
|
||||||
|
}
|
||||||
|
|
||||||
return $term;
|
return $term;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -595,11 +595,12 @@ class QueryBuilder
|
|||||||
*
|
*
|
||||||
* @param string $from The class name.
|
* @param string $from The class name.
|
||||||
* @param string $alias The alias of the class.
|
* @param string $alias The alias of the class.
|
||||||
|
* @param string $indexBy The index for the from.
|
||||||
* @return QueryBuilder This QueryBuilder instance.
|
* @return QueryBuilder This QueryBuilder instance.
|
||||||
*/
|
*/
|
||||||
public function from($from, $alias)
|
public function from($from, $alias, $indexBy = null)
|
||||||
{
|
{
|
||||||
return $this->add('from', new Expr\From($from, $alias), true);
|
return $this->add('from', new Expr\From($from, $alias, $indexBy), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
/*
|
/*
|
||||||
* $Id$
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
@ -23,7 +21,8 @@ namespace Doctrine\ORM\Tools\Console\Command\ClearCache;
|
|||||||
|
|
||||||
use Symfony\Component\Console\Input\InputArgument,
|
use Symfony\Component\Console\Input\InputArgument,
|
||||||
Symfony\Component\Console\Input\InputOption,
|
Symfony\Component\Console\Input\InputOption,
|
||||||
Symfony\Component\Console;
|
Symfony\Component\Console,
|
||||||
|
Doctrine\Common\Cache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Command to clear the metadata cache of the various cache drivers.
|
* Command to clear the metadata cache of the various cache drivers.
|
||||||
@ -31,7 +30,6 @@ use Symfony\Component\Console\Input\InputArgument,
|
|||||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||||
* @link www.doctrine-project.org
|
* @link www.doctrine-project.org
|
||||||
* @since 2.0
|
* @since 2.0
|
||||||
* @version $Revision$
|
|
||||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||||
* @author Jonathan Wage <jonwage@gmail.com>
|
* @author Jonathan Wage <jonwage@gmail.com>
|
||||||
@ -47,9 +45,30 @@ class MetadataCommand extends Console\Command\Command
|
|||||||
$this
|
$this
|
||||||
->setName('orm:clear-cache:metadata')
|
->setName('orm:clear-cache:metadata')
|
||||||
->setDescription('Clear all metadata cache of the various cache drivers.')
|
->setDescription('Clear all metadata cache of the various cache drivers.')
|
||||||
->setDefinition(array())
|
->setDefinition(array(
|
||||||
->setHelp(<<<EOT
|
new InputOption(
|
||||||
Clear all metadata cache of the various cache drivers.
|
'flush', null, InputOption::VALUE_NONE,
|
||||||
|
'If defined, cache entries will be flushed instead of deleted/invalidated.'
|
||||||
|
)
|
||||||
|
));
|
||||||
|
|
||||||
|
$fullName = $this->getName();
|
||||||
|
$this->setHelp(<<<EOT
|
||||||
|
The <info>$fullName</info> command is meant to clear the metadata cache of associated Entity Manager.
|
||||||
|
It is possible to invalidate all cache entries at once - called delete -, or flushes the cache provider
|
||||||
|
instance completely.
|
||||||
|
|
||||||
|
The execution type differ on how you execute the command.
|
||||||
|
If you want to invalidate the entries (and not delete from cache instance), this command would do the work:
|
||||||
|
|
||||||
|
<info>$fullName</info>
|
||||||
|
|
||||||
|
Alternatively, if you want to flush the cache provider using this command:
|
||||||
|
|
||||||
|
<info>$fullName --flush</info>
|
||||||
|
|
||||||
|
Finally, be aware that if <info>--flush</info> option is passed, not all cache providers are able to flush entries,
|
||||||
|
because of a limitation of its execution nature.
|
||||||
EOT
|
EOT
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -65,21 +84,21 @@ EOT
|
|||||||
if ( ! $cacheDriver) {
|
if ( ! $cacheDriver) {
|
||||||
throw new \InvalidArgumentException('No Metadata cache driver is configured on given EntityManager.');
|
throw new \InvalidArgumentException('No Metadata cache driver is configured on given EntityManager.');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($cacheDriver instanceof \Doctrine\Common\Cache\ApcCache) {
|
if ($cacheDriver instanceof Cache\ApcCache) {
|
||||||
throw new \LogicException("Cannot clear APC Cache from Console, its shared in the Webserver memory and not accessible from the CLI.");
|
throw new \LogicException("Cannot clear APC Cache from Console, its shared in the Webserver memory and not accessible from the CLI.");
|
||||||
}
|
}
|
||||||
|
|
||||||
$output->write('Clearing ALL Metadata cache entries' . PHP_EOL);
|
$output->write('Clearing ALL Metadata cache entries' . PHP_EOL);
|
||||||
|
|
||||||
$cacheIds = $cacheDriver->deleteAll();
|
$result = $cacheDriver->deleteAll();
|
||||||
|
$message = ($result) ? 'Successfully deleted cache entries.' : 'No cache entries were deleted.';
|
||||||
if ($cacheIds) {
|
|
||||||
foreach ($cacheIds as $cacheId) {
|
if (true === $input->getOption('flush')) {
|
||||||
$output->write(' - ' . $cacheId . PHP_EOL);
|
$result = $cacheDriver->flushAll();
|
||||||
}
|
$message = ($result) ? 'Successfully flushed cache entries.' : $message;
|
||||||
} else {
|
|
||||||
$output->write('No entries to be deleted.' . PHP_EOL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$output->write($message . PHP_EOL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
/*
|
/*
|
||||||
* $Id$
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
@ -23,7 +21,8 @@ namespace Doctrine\ORM\Tools\Console\Command\ClearCache;
|
|||||||
|
|
||||||
use Symfony\Component\Console\Input\InputArgument,
|
use Symfony\Component\Console\Input\InputArgument,
|
||||||
Symfony\Component\Console\Input\InputOption,
|
Symfony\Component\Console\Input\InputOption,
|
||||||
Symfony\Component\Console;
|
Symfony\Component\Console,
|
||||||
|
Doctrine\Common\Cache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Command to clear the query cache of the various cache drivers.
|
* Command to clear the query cache of the various cache drivers.
|
||||||
@ -31,7 +30,6 @@ use Symfony\Component\Console\Input\InputArgument,
|
|||||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||||
* @link www.doctrine-project.org
|
* @link www.doctrine-project.org
|
||||||
* @since 2.0
|
* @since 2.0
|
||||||
* @version $Revision$
|
|
||||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||||
* @author Jonathan Wage <jonwage@gmail.com>
|
* @author Jonathan Wage <jonwage@gmail.com>
|
||||||
@ -47,9 +45,30 @@ class QueryCommand extends Console\Command\Command
|
|||||||
$this
|
$this
|
||||||
->setName('orm:clear-cache:query')
|
->setName('orm:clear-cache:query')
|
||||||
->setDescription('Clear all query cache of the various cache drivers.')
|
->setDescription('Clear all query cache of the various cache drivers.')
|
||||||
->setDefinition(array())
|
->setDefinition(array(
|
||||||
->setHelp(<<<EOT
|
new InputOption(
|
||||||
Clear all query cache of the various cache drivers.
|
'flush', null, InputOption::VALUE_NONE,
|
||||||
|
'If defined, cache entries will be flushed instead of deleted/invalidated.'
|
||||||
|
)
|
||||||
|
));
|
||||||
|
|
||||||
|
$fullName = $this->getName();
|
||||||
|
$this->setHelp(<<<EOT
|
||||||
|
The <info>$fullName</info> command is meant to clear the query cache of associated Entity Manager.
|
||||||
|
It is possible to invalidate all cache entries at once - called delete -, or flushes the cache provider
|
||||||
|
instance completely.
|
||||||
|
|
||||||
|
The execution type differ on how you execute the command.
|
||||||
|
If you want to invalidate the entries (and not delete from cache instance), this command would do the work:
|
||||||
|
|
||||||
|
<info>$fullName</info>
|
||||||
|
|
||||||
|
Alternatively, if you want to flush the cache provider using this command:
|
||||||
|
|
||||||
|
<info>$fullName --flush</info>
|
||||||
|
|
||||||
|
Finally, be aware that if <info>--flush</info> option is passed, not all cache providers are able to flush entries,
|
||||||
|
because of a limitation of its execution nature.
|
||||||
EOT
|
EOT
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -65,21 +84,21 @@ EOT
|
|||||||
if ( ! $cacheDriver) {
|
if ( ! $cacheDriver) {
|
||||||
throw new \InvalidArgumentException('No Query cache driver is configured on given EntityManager.');
|
throw new \InvalidArgumentException('No Query cache driver is configured on given EntityManager.');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($cacheDriver instanceof \Doctrine\Common\Cache\ApcCache) {
|
if ($cacheDriver instanceof Cache\ApcCache) {
|
||||||
throw new \LogicException("Cannot clear APC Cache from Console, its shared in the Webserver memory and not accessible from the CLI.");
|
throw new \LogicException("Cannot clear APC Cache from Console, its shared in the Webserver memory and not accessible from the CLI.");
|
||||||
}
|
}
|
||||||
|
|
||||||
$output->write('Clearing ALL Query cache entries' . PHP_EOL);
|
$output->write('Clearing ALL Query cache entries' . PHP_EOL);
|
||||||
|
|
||||||
$cacheIds = $cacheDriver->deleteAll();
|
$result = $cacheDriver->deleteAll();
|
||||||
|
$message = ($result) ? 'Successfully deleted cache entries.' : 'No cache entries were deleted.';
|
||||||
if ($cacheIds) {
|
|
||||||
foreach ($cacheIds as $cacheId) {
|
if (true === $input->getOption('flush')) {
|
||||||
$output->write(' - ' . $cacheId . PHP_EOL);
|
$result = $cacheDriver->flushAll();
|
||||||
}
|
$message = ($result) ? 'Successfully flushed cache entries.' : $message;
|
||||||
} else {
|
|
||||||
$output->write('No entries to be deleted.' . PHP_EOL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$output->write($message . PHP_EOL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
/*
|
/*
|
||||||
* $Id$
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
@ -23,7 +21,8 @@ namespace Doctrine\ORM\Tools\Console\Command\ClearCache;
|
|||||||
|
|
||||||
use Symfony\Component\Console\Input\InputArgument,
|
use Symfony\Component\Console\Input\InputArgument,
|
||||||
Symfony\Component\Console\Input\InputOption,
|
Symfony\Component\Console\Input\InputOption,
|
||||||
Symfony\Component\Console;
|
Symfony\Component\Console,
|
||||||
|
Doctrine\Common\Cache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Command to clear the result cache of the various cache drivers.
|
* Command to clear the result cache of the various cache drivers.
|
||||||
@ -31,7 +30,6 @@ use Symfony\Component\Console\Input\InputArgument,
|
|||||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||||
* @link www.doctrine-project.org
|
* @link www.doctrine-project.org
|
||||||
* @since 2.0
|
* @since 2.0
|
||||||
* @version $Revision$
|
|
||||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||||
* @author Jonathan Wage <jonwage@gmail.com>
|
* @author Jonathan Wage <jonwage@gmail.com>
|
||||||
@ -46,28 +44,31 @@ class ResultCommand extends Console\Command\Command
|
|||||||
{
|
{
|
||||||
$this
|
$this
|
||||||
->setName('orm:clear-cache:result')
|
->setName('orm:clear-cache:result')
|
||||||
->setDescription('Clear result cache of the various cache drivers.')
|
->setDescription('Clear all result cache of the various cache drivers.')
|
||||||
->setDefinition(array(
|
->setDefinition(array(
|
||||||
new InputOption(
|
new InputOption(
|
||||||
'id', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
|
'flush', null, InputOption::VALUE_NONE,
|
||||||
'ID(s) of the cache entry to delete (accepts * wildcards).', array()
|
'If defined, cache entries will be flushed instead of deleted/invalidated.'
|
||||||
),
|
)
|
||||||
new InputOption(
|
));
|
||||||
'regex', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
|
|
||||||
'Delete cache entries that match the given regular expression(s).', array()
|
$fullName = $this->getName();
|
||||||
),
|
$this->setHelp(<<<EOT
|
||||||
new InputOption(
|
The <info>$fullName</info> command is meant to clear the result cache of associated Entity Manager.
|
||||||
'prefix', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
|
It is possible to invalidate all cache entries at once - called delete -, or flushes the cache provider
|
||||||
'Delete cache entries that have the given prefix(es).', array()
|
instance completely.
|
||||||
),
|
|
||||||
new InputOption(
|
The execution type differ on how you execute the command.
|
||||||
'suffix', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
|
If you want to invalidate the entries (and not delete from cache instance), this command would do the work:
|
||||||
'Delete cache entries that have the given suffix(es).', array()
|
|
||||||
),
|
<info>$fullName</info>
|
||||||
))
|
|
||||||
->setHelp(<<<EOT
|
Alternatively, if you want to flush the cache provider using this command:
|
||||||
Clear result cache of the various cache drivers.
|
|
||||||
If none of the options are defined, all cache entries will be removed.
|
<info>$fullName --flush</info>
|
||||||
|
|
||||||
|
Finally, be aware that if <info>--flush</info> option is passed, not all cache providers are able to flush entries,
|
||||||
|
because of a limitation of its execution nature.
|
||||||
EOT
|
EOT
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -83,86 +84,21 @@ EOT
|
|||||||
if ( ! $cacheDriver) {
|
if ( ! $cacheDriver) {
|
||||||
throw new \InvalidArgumentException('No Result cache driver is configured on given EntityManager.');
|
throw new \InvalidArgumentException('No Result cache driver is configured on given EntityManager.');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($cacheDriver instanceof \Doctrine\Common\Cache\ApcCache) {
|
if ($cacheDriver instanceof Cache\ApcCache) {
|
||||||
throw new \LogicException("Cannot clear APC Cache from Console, its shared in the Webserver memory and not accessible from the CLI.");
|
throw new \LogicException("Cannot clear APC Cache from Console, its shared in the Webserver memory and not accessible from the CLI.");
|
||||||
}
|
}
|
||||||
|
|
||||||
$outputed = false;
|
$output->write('Clearing ALL Result cache entries' . PHP_EOL);
|
||||||
|
|
||||||
// Removing based on --id
|
$result = $cacheDriver->deleteAll();
|
||||||
if (($ids = $input->getOption('id')) !== null && $ids) {
|
$message = ($result) ? 'Successfully deleted cache entries.' : 'No cache entries were deleted.';
|
||||||
foreach ($ids as $id) {
|
|
||||||
$output->write($outputed ? PHP_EOL : '');
|
if (true === $input->getOption('flush')) {
|
||||||
$output->write(sprintf('Clearing Result cache entries that match the id "<info>%s</info>"', $id) . PHP_EOL);
|
$result = $cacheDriver->flushAll();
|
||||||
|
$message = ($result) ? 'Successfully flushed cache entries.' : $message;
|
||||||
$deleted = $cacheDriver->delete($id);
|
|
||||||
|
|
||||||
if (is_array($deleted)) {
|
|
||||||
$this->_printDeleted($output, $deleted);
|
|
||||||
} else if (is_bool($deleted) && $deleted) {
|
|
||||||
$this->_printDeleted($output, array($id));
|
|
||||||
}
|
|
||||||
|
|
||||||
$outputed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Removing based on --regex
|
|
||||||
if (($regexps = $input->getOption('regex')) !== null && $regexps) {
|
|
||||||
foreach($regexps as $regex) {
|
|
||||||
$output->write($outputed ? PHP_EOL : '');
|
|
||||||
$output->write(sprintf('Clearing Result cache entries that match the regular expression "<info>%s</info>"', $regex) . PHP_EOL);
|
|
||||||
|
|
||||||
$this->_printDeleted($output, $cacheDriver->deleteByRegex('/' . $regex. '/'));
|
|
||||||
|
|
||||||
$outputed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Removing based on --prefix
|
|
||||||
if (($prefixes = $input->getOption('prefix')) !== null & $prefixes) {
|
|
||||||
foreach ($prefixes as $prefix) {
|
|
||||||
$output->write($outputed ? PHP_EOL : '');
|
|
||||||
$output->write(sprintf('Clearing Result cache entries that have the prefix "<info>%s</info>"', $prefix) . PHP_EOL);
|
|
||||||
|
|
||||||
$this->_printDeleted($output, $cacheDriver->deleteByPrefix($prefix));
|
|
||||||
|
|
||||||
$outputed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Removing based on --suffix
|
|
||||||
if (($suffixes = $input->getOption('suffix')) !== null && $suffixes) {
|
|
||||||
foreach ($suffixes as $suffix) {
|
|
||||||
$output->write($outputed ? PHP_EOL : '');
|
|
||||||
$output->write(sprintf('Clearing Result cache entries that have the suffix "<info>%s</info>"', $suffix) . PHP_EOL);
|
|
||||||
|
|
||||||
$this->_printDeleted($output, $cacheDriver->deleteBySuffix($suffix));
|
|
||||||
|
|
||||||
$outputed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Removing ALL entries
|
|
||||||
if ( ! $ids && ! $regexps && ! $prefixes && ! $suffixes) {
|
|
||||||
$output->write($outputed ? PHP_EOL : '');
|
|
||||||
$output->write('Clearing ALL Result cache entries' . PHP_EOL);
|
|
||||||
|
|
||||||
$this->_printDeleted($output, $cacheDriver->deleteAll());
|
|
||||||
|
|
||||||
$outputed = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$output->write($message . PHP_EOL);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
private function _printDeleted(Console\Output\OutputInterface $output, array $items)
|
|
||||||
{
|
|
||||||
if ($items) {
|
|
||||||
foreach ($items as $item) {
|
|
||||||
$output->write(' - ' . $item . PHP_EOL);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$output->write('No entries to be deleted.' . PHP_EOL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -137,7 +137,7 @@ EOT
|
|||||||
|
|
||||||
if ( ! file_exists($destPath)) {
|
if ( ! file_exists($destPath)) {
|
||||||
throw new \InvalidArgumentException(
|
throw new \InvalidArgumentException(
|
||||||
sprintf("Mapping destination directory '<info>%s</info>' does not exist.", $destPath)
|
sprintf("Mapping destination directory '<info>%s</info>' does not exist.", $input->getArgument('dest-path'))
|
||||||
);
|
);
|
||||||
} else if ( ! is_writable($destPath)) {
|
} else if ( ! is_writable($destPath)) {
|
||||||
throw new \InvalidArgumentException(
|
throw new \InvalidArgumentException(
|
||||||
|
@ -123,7 +123,7 @@ EOT
|
|||||||
|
|
||||||
if ( ! file_exists($destPath)) {
|
if ( ! file_exists($destPath)) {
|
||||||
throw new \InvalidArgumentException(
|
throw new \InvalidArgumentException(
|
||||||
sprintf("Entities destination directory '<info>%s</info>' does not exist.", $destPath)
|
sprintf("Entities destination directory '<info>%s</info>' does not exist.", $input->getArgument('dest-path'))
|
||||||
);
|
);
|
||||||
} else if ( ! is_writable($destPath)) {
|
} else if ( ! is_writable($destPath)) {
|
||||||
throw new \InvalidArgumentException(
|
throw new \InvalidArgumentException(
|
||||||
|
@ -87,7 +87,7 @@ EOT
|
|||||||
|
|
||||||
if ( ! file_exists($destPath)) {
|
if ( ! file_exists($destPath)) {
|
||||||
throw new \InvalidArgumentException(
|
throw new \InvalidArgumentException(
|
||||||
sprintf("Proxies destination directory '<info>%s</info>' does not exist.", $destPath)
|
sprintf("Proxies destination directory '<info>%s</info>' does not exist.", $em->getConfiguration()->getProxyDir())
|
||||||
);
|
);
|
||||||
} else if ( ! is_writable($destPath)) {
|
} else if ( ! is_writable($destPath)) {
|
||||||
throw new \InvalidArgumentException(
|
throw new \InvalidArgumentException(
|
||||||
|
@ -79,7 +79,7 @@ EOT
|
|||||||
|
|
||||||
if ( ! file_exists($destPath)) {
|
if ( ! file_exists($destPath)) {
|
||||||
throw new \InvalidArgumentException(
|
throw new \InvalidArgumentException(
|
||||||
sprintf("Entities destination directory '<info>%s</info>' does not exist.", $destPath)
|
sprintf("Entities destination directory '<info>%s</info>' does not exist.", $input->getArgument('dest-path'))
|
||||||
);
|
);
|
||||||
} else if ( ! is_writable($destPath)) {
|
} else if ( ! is_writable($destPath)) {
|
||||||
throw new \InvalidArgumentException(
|
throw new \InvalidArgumentException(
|
||||||
|
@ -46,7 +46,7 @@ class ValidateSchemaCommand extends Console\Command\Command
|
|||||||
{
|
{
|
||||||
$this
|
$this
|
||||||
->setName('orm:validate-schema')
|
->setName('orm:validate-schema')
|
||||||
->setDescription('Validate that the mapping files.')
|
->setDescription('Validate the mapping files.')
|
||||||
->setHelp(<<<EOT
|
->setHelp(<<<EOT
|
||||||
'Validate that the mapping files are correct and in sync with the database.'
|
'Validate that the mapping files are correct and in sync with the database.'
|
||||||
EOT
|
EOT
|
||||||
|
@ -101,6 +101,7 @@ class ConvertDoctrine1Schema
|
|||||||
{
|
{
|
||||||
if (isset($model['tableName']) && $model['tableName']) {
|
if (isset($model['tableName']) && $model['tableName']) {
|
||||||
$e = explode('.', $model['tableName']);
|
$e = explode('.', $model['tableName']);
|
||||||
|
|
||||||
if (count($e) > 1) {
|
if (count($e) > 1) {
|
||||||
$metadata->table['schema'] = $e[0];
|
$metadata->table['schema'] = $e[0];
|
||||||
$metadata->table['name'] = $e[1];
|
$metadata->table['name'] = $e[1];
|
||||||
|
@ -150,7 +150,7 @@ public function <methodName>()
|
|||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
if (version_compare(\Doctrine\Common\Version::VERSION, '3.0.0-DEV', '>=')) {
|
if (version_compare(\Doctrine\Common\Version::VERSION, '2.2.0-DEV', '>=')) {
|
||||||
$this->_annotationsPrefix = 'ORM\\';
|
$this->_annotationsPrefix = 'ORM\\';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -399,14 +399,17 @@ public function <methodName>()
|
|||||||
}
|
}
|
||||||
|
|
||||||
$collections = array();
|
$collections = array();
|
||||||
|
|
||||||
foreach ($metadata->associationMappings AS $mapping) {
|
foreach ($metadata->associationMappings AS $mapping) {
|
||||||
if ($mapping['type'] & ClassMetadataInfo::TO_MANY) {
|
if ($mapping['type'] & ClassMetadataInfo::TO_MANY) {
|
||||||
$collections[] = '$this->'.$mapping['fieldName'].' = new \Doctrine\Common\Collections\ArrayCollection();';
|
$collections[] = '$this->'.$mapping['fieldName'].' = new \Doctrine\Common\Collections\ArrayCollection();';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($collections) {
|
if ($collections) {
|
||||||
return $this->_prefixCodeWithSpaces(str_replace("<collections>", implode("\n", $collections), self::$_constructorMethodTemplate));
|
return $this->_prefixCodeWithSpaces(str_replace("<collections>", implode("\n", $collections), self::$_constructorMethodTemplate));
|
||||||
}
|
}
|
||||||
|
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -570,7 +573,12 @@ public function <methodName>()
|
|||||||
private function _generateTableAnnotation($metadata)
|
private function _generateTableAnnotation($metadata)
|
||||||
{
|
{
|
||||||
$table = array();
|
$table = array();
|
||||||
if ($metadata->table['name']) {
|
|
||||||
|
if (isset($metadata->table['schema'])) {
|
||||||
|
$table[] = 'schema="' . $metadata->table['schema'] . '"';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($metadata->table['name'])) {
|
||||||
$table[] = 'name="' . $metadata->table['name'] . '"';
|
$table[] = 'name="' . $metadata->table['name'] . '"';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,11 +49,13 @@ class YamlExporter extends AbstractExporter
|
|||||||
public function exportClassMetadata(ClassMetadataInfo $metadata)
|
public function exportClassMetadata(ClassMetadataInfo $metadata)
|
||||||
{
|
{
|
||||||
$array = array();
|
$array = array();
|
||||||
|
|
||||||
if ($metadata->isMappedSuperclass) {
|
if ($metadata->isMappedSuperclass) {
|
||||||
$array['type'] = 'mappedSuperclass';
|
$array['type'] = 'mappedSuperclass';
|
||||||
} else {
|
} else {
|
||||||
$array['type'] = 'entity';
|
$array['type'] = 'entity';
|
||||||
}
|
}
|
||||||
|
|
||||||
$array['table'] = $metadata->table['name'];
|
$array['table'] = $metadata->table['name'];
|
||||||
|
|
||||||
if (isset($metadata->table['schema'])) {
|
if (isset($metadata->table['schema'])) {
|
||||||
@ -81,6 +83,10 @@ class YamlExporter extends AbstractExporter
|
|||||||
$array['indexes'] = $metadata->table['indexes'];
|
$array['indexes'] = $metadata->table['indexes'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($metadata->customRepositoryClassName) {
|
||||||
|
$array['repositoryClass'] = $metadata->customRepositoryClassName;
|
||||||
|
}
|
||||||
|
|
||||||
if (isset($metadata->table['uniqueConstraints'])) {
|
if (isset($metadata->table['uniqueConstraints'])) {
|
||||||
$array['uniqueConstraints'] = $metadata->table['uniqueConstraints'];
|
$array['uniqueConstraints'] = $metadata->table['uniqueConstraints'];
|
||||||
}
|
}
|
||||||
|
@ -97,7 +97,7 @@ class Setup
|
|||||||
require_once $directory . "/Doctrine/Common/ClassLoader.php";
|
require_once $directory . "/Doctrine/Common/ClassLoader.php";
|
||||||
}
|
}
|
||||||
|
|
||||||
$loader = new ClassLoader("Doctrine");
|
$loader = new ClassLoader("Doctrine", $directory);
|
||||||
$loader->register();
|
$loader->register();
|
||||||
|
|
||||||
$loader = new ClassLoader("Symfony\Component", $directory . "/Doctrine");
|
$loader = new ClassLoader("Symfony\Component", $directory . "/Doctrine");
|
||||||
@ -115,13 +115,13 @@ class Setup
|
|||||||
*/
|
*/
|
||||||
static public function createAnnotationMetadataConfiguration(array $paths, $isDevMode = false, $proxyDir = null, Cache $cache = null)
|
static public function createAnnotationMetadataConfiguration(array $paths, $isDevMode = false, $proxyDir = null, Cache $cache = null)
|
||||||
{
|
{
|
||||||
$config = self::createConfiguration($isDevMode, $cache, $proxyDir);
|
$config = self::createConfiguration($isDevMode, $proxyDir, $cache);
|
||||||
$config->setMetadataDriverImpl($config->newDefaultAnnotationDriver($paths));
|
$config->setMetadataDriverImpl($config->newDefaultAnnotationDriver($paths));
|
||||||
return $config;
|
return $config;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a configuration with an annotation metadata driver.
|
* Create a configuration with a xml metadata driver.
|
||||||
*
|
*
|
||||||
* @param array $paths
|
* @param array $paths
|
||||||
* @param boolean $isDevMode
|
* @param boolean $isDevMode
|
||||||
@ -131,13 +131,13 @@ class Setup
|
|||||||
*/
|
*/
|
||||||
static public function createXMLMetadataConfiguration(array $paths, $isDevMode = false, $proxyDir = null, Cache $cache = null)
|
static public function createXMLMetadataConfiguration(array $paths, $isDevMode = false, $proxyDir = null, Cache $cache = null)
|
||||||
{
|
{
|
||||||
$config = self::createConfiguration($isDevMode, $cache, $proxyDir);
|
$config = self::createConfiguration($isDevMode, $proxyDir, $cache);
|
||||||
$config->setMetadataDriverImpl(new XmlDriver($paths));
|
$config->setMetadataDriverImpl(new XmlDriver($paths));
|
||||||
return $config;
|
return $config;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a configuration with an annotation metadata driver.
|
* Create a configuration with a yaml metadata driver.
|
||||||
*
|
*
|
||||||
* @param array $paths
|
* @param array $paths
|
||||||
* @param boolean $isDevMode
|
* @param boolean $isDevMode
|
||||||
@ -147,7 +147,7 @@ class Setup
|
|||||||
*/
|
*/
|
||||||
static public function createYAMLMetadataConfiguration(array $paths, $isDevMode = false, $proxyDir = null, Cache $cache = null)
|
static public function createYAMLMetadataConfiguration(array $paths, $isDevMode = false, $proxyDir = null, Cache $cache = null)
|
||||||
{
|
{
|
||||||
$config = self::createConfiguration($isDevMode, $cache, $proxyDir);
|
$config = self::createConfiguration($isDevMode, $proxyDir, $cache);
|
||||||
$config->setMetadataDriverImpl(new YamlDriver($paths));
|
$config->setMetadataDriverImpl(new YamlDriver($paths));
|
||||||
return $config;
|
return $config;
|
||||||
}
|
}
|
||||||
@ -162,6 +162,7 @@ class Setup
|
|||||||
*/
|
*/
|
||||||
static public function createConfiguration($isDevMode = false, $proxyDir = null, Cache $cache = null)
|
static public function createConfiguration($isDevMode = false, $proxyDir = null, Cache $cache = null)
|
||||||
{
|
{
|
||||||
|
$proxyDir = $proxyDir ?: sys_get_temp_dir();
|
||||||
if ($isDevMode === false && $cache === null) {
|
if ($isDevMode === false && $cache === null) {
|
||||||
if (extension_loaded('apc')) {
|
if (extension_loaded('apc')) {
|
||||||
$cache = new \Doctrine\Common\Cache\ApcCache;
|
$cache = new \Doctrine\Common\Cache\ApcCache;
|
||||||
@ -175,16 +176,16 @@ class Setup
|
|||||||
} else {
|
} else {
|
||||||
$cache = new ArrayCache;
|
$cache = new ArrayCache;
|
||||||
}
|
}
|
||||||
$cache->setNamespace("dc2_"); // to avoid collisions
|
|
||||||
} else if ($cache === null) {
|
} else if ($cache === null) {
|
||||||
$cache = new ArrayCache;
|
$cache = new ArrayCache;
|
||||||
}
|
}
|
||||||
|
$cache->setNamespace("dc2_" . md5($proxyDir) . "_"); // to avoid collisions
|
||||||
|
|
||||||
$config = new Configuration();
|
$config = new Configuration();
|
||||||
$config->setMetadataCacheImpl($cache);
|
$config->setMetadataCacheImpl($cache);
|
||||||
$config->setQueryCacheImpl($cache);
|
$config->setQueryCacheImpl($cache);
|
||||||
$config->setResultCacheImpl($cache);
|
$config->setResultCacheImpl($cache);
|
||||||
$config->setProxyDir( $proxyDir ?: sys_get_temp_dir() );
|
$config->setProxyDir( $proxyDir );
|
||||||
$config->setProxyNamespace('DoctrineProxies');
|
$config->setProxyNamespace('DoctrineProxies');
|
||||||
$config->setAutoGenerateProxyClasses($isDevMode);
|
$config->setAutoGenerateProxyClasses($isDevMode);
|
||||||
|
|
||||||
|
@ -834,6 +834,8 @@ class UnitOfWork implements PropertyChangedListener
|
|||||||
|
|
||||||
// See if there are any new classes in the changeset, that are not in the
|
// See if there are any new classes in the changeset, that are not in the
|
||||||
// commit order graph yet (dont have a node).
|
// commit order graph yet (dont have a node).
|
||||||
|
|
||||||
|
// TODO: Can we know the know the possible $newNodes based on something more efficient? IdentityMap?
|
||||||
$newNodes = array();
|
$newNodes = array();
|
||||||
foreach ($entityChangeSet as $oid => $entity) {
|
foreach ($entityChangeSet as $oid => $entity) {
|
||||||
$className = get_class($entity);
|
$className = get_class($entity);
|
||||||
@ -845,7 +847,7 @@ class UnitOfWork implements PropertyChangedListener
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Calculate dependencies for new nodes
|
// Calculate dependencies for new nodes
|
||||||
foreach ($newNodes as $class) {
|
while ($class = array_pop($newNodes)) {
|
||||||
foreach ($class->associationMappings as $assoc) {
|
foreach ($class->associationMappings as $assoc) {
|
||||||
if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) {
|
if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) {
|
||||||
$targetClass = $this->em->getClassMetadata($assoc['targetEntity']);
|
$targetClass = $this->em->getClassMetadata($assoc['targetEntity']);
|
||||||
@ -860,6 +862,7 @@ class UnitOfWork implements PropertyChangedListener
|
|||||||
$targetSubClass = $this->em->getClassMetadata($subClassName);
|
$targetSubClass = $this->em->getClassMetadata($subClassName);
|
||||||
if ( ! $calc->hasClass($subClassName)) {
|
if ( ! $calc->hasClass($subClassName)) {
|
||||||
$calc->addClass($targetSubClass);
|
$calc->addClass($targetSubClass);
|
||||||
|
$newNodes[] = $targetSubClass;
|
||||||
}
|
}
|
||||||
$calc->addDependency($targetSubClass, $class);
|
$calc->addDependency($targetSubClass, $class);
|
||||||
}
|
}
|
||||||
@ -1102,6 +1105,22 @@ class UnitOfWork implements PropertyChangedListener
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (!$class->idGenerator->isPostInsertGenerator()) {
|
||||||
|
// if we have a pre insert generator we can't be sure that having an id
|
||||||
|
// really means that the entity exists. We have to verify this through
|
||||||
|
// the last resort: a db lookup
|
||||||
|
|
||||||
|
// Last try before db lookup: check the identity map.
|
||||||
|
if ($this->tryGetById($id, $class->rootEntityName)) {
|
||||||
|
return self::STATE_DETACHED;
|
||||||
|
} else {
|
||||||
|
// db lookup
|
||||||
|
if ($this->getEntityPersister(get_class($entity))->exists($entity)) {
|
||||||
|
return self::STATE_DETACHED;
|
||||||
|
} else {
|
||||||
|
return self::STATE_NEW;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return self::STATE_DETACHED;
|
return self::STATE_DETACHED;
|
||||||
}
|
}
|
||||||
@ -1368,6 +1387,10 @@ class UnitOfWork implements PropertyChangedListener
|
|||||||
if ($this->getEntityState($entity, self::STATE_DETACHED) == self::STATE_MANAGED) {
|
if ($this->getEntityState($entity, self::STATE_DETACHED) == self::STATE_MANAGED) {
|
||||||
$managedCopy = $entity;
|
$managedCopy = $entity;
|
||||||
} else {
|
} else {
|
||||||
|
if ($entity instanceof Proxy && ! $entity->__isInitialized__) {
|
||||||
|
$entity->__load();
|
||||||
|
}
|
||||||
|
|
||||||
// Try to look the entity up in the identity map.
|
// Try to look the entity up in the identity map.
|
||||||
$id = $class->getIdentifierValues($entity);
|
$id = $class->getIdentifierValues($entity);
|
||||||
|
|
||||||
@ -1406,7 +1429,7 @@ class UnitOfWork implements PropertyChangedListener
|
|||||||
$entityVersion = $class->reflFields[$class->versionField]->getValue($entity);
|
$entityVersion = $class->reflFields[$class->versionField]->getValue($entity);
|
||||||
// Throw exception if versions dont match.
|
// Throw exception if versions dont match.
|
||||||
if ($managedCopyVersion != $entityVersion) {
|
if ($managedCopyVersion != $entityVersion) {
|
||||||
throw OptimisticLockException::lockFailedVersionMissmatch($entityVersion, $managedCopyVersion);
|
throw OptimisticLockException::lockFailedVersionMissmatch($entity, $entityVersion, $managedCopyVersion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1742,7 +1765,7 @@ class UnitOfWork implements PropertyChangedListener
|
|||||||
*/
|
*/
|
||||||
public function lock($entity, $lockMode, $lockVersion = null)
|
public function lock($entity, $lockMode, $lockVersion = null)
|
||||||
{
|
{
|
||||||
if ($this->getEntityState($entity) != self::STATE_MANAGED) {
|
if ($this->getEntityState($entity, self::STATE_DETACHED) != self::STATE_MANAGED) {
|
||||||
throw new InvalidArgumentException("Entity is not MANAGED.");
|
throw new InvalidArgumentException("Entity is not MANAGED.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2164,9 +2187,11 @@ class UnitOfWork implements PropertyChangedListener
|
|||||||
public function tryGetById($id, $rootClassName)
|
public function tryGetById($id, $rootClassName)
|
||||||
{
|
{
|
||||||
$idHash = implode(' ', (array) $id);
|
$idHash = implode(' ', (array) $id);
|
||||||
|
|
||||||
if (isset($this->identityMap[$rootClassName][$idHash])) {
|
if (isset($this->identityMap[$rootClassName][$idHash])) {
|
||||||
return $this->identityMap[$rootClassName][$idHash];
|
return $this->identityMap[$rootClassName][$idHash];
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
lib/vendor/doctrine-common
vendored
2
lib/vendor/doctrine-common
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 74a2c924cd08b30785877808b1fb519b4b2e60b1
|
Subproject commit ef431a14852d7e8f2d0ea789487509ab266e5ce2
|
2
lib/vendor/doctrine-dbal
vendored
2
lib/vendor/doctrine-dbal
vendored
@ -1 +1 @@
|
|||||||
Subproject commit be3790059cc43b674a55548eb42d5d25846ea6a9
|
Subproject commit f91395b6f469b5076f52fefd64574c443b076485
|
48
tests/Doctrine/Tests/Models/CMS/CmsEmail.php
Normal file
48
tests/Doctrine/Tests/Models/CMS/CmsEmail.php
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Doctrine\Tests\Models\CMS;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CmsEmail
|
||||||
|
*
|
||||||
|
* @Entity
|
||||||
|
* @Table(name="cms_emails")
|
||||||
|
*/
|
||||||
|
class CmsEmail
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @Column(type="integer")
|
||||||
|
* @Id @GeneratedValue
|
||||||
|
*/
|
||||||
|
public $id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Column(length=250)
|
||||||
|
*/
|
||||||
|
public $email;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @OneToOne(targetEntity="CmsUser", mappedBy="email")
|
||||||
|
*/
|
||||||
|
public $user;
|
||||||
|
|
||||||
|
public function getId() {
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getEmail() {
|
||||||
|
return $this->email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setEmail($email) {
|
||||||
|
$this->email = $email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getUser() {
|
||||||
|
return $this->user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setUser(CmsUser $user) {
|
||||||
|
$this->user = $user;
|
||||||
|
}
|
||||||
|
}
|
@ -31,7 +31,7 @@ class CmsUser
|
|||||||
*/
|
*/
|
||||||
public $name;
|
public $name;
|
||||||
/**
|
/**
|
||||||
* @OneToMany(targetEntity="CmsPhonenumber", mappedBy="user", cascade={"persist", "remove", "merge"}, orphanRemoval=true)
|
* @OneToMany(targetEntity="CmsPhonenumber", mappedBy="user", cascade={"persist", "merge"}, orphanRemoval=true)
|
||||||
*/
|
*/
|
||||||
public $phonenumbers;
|
public $phonenumbers;
|
||||||
/**
|
/**
|
||||||
@ -42,6 +42,11 @@ class CmsUser
|
|||||||
* @OneToOne(targetEntity="CmsAddress", mappedBy="user", cascade={"persist"}, orphanRemoval=true)
|
* @OneToOne(targetEntity="CmsAddress", mappedBy="user", cascade={"persist"}, orphanRemoval=true)
|
||||||
*/
|
*/
|
||||||
public $address;
|
public $address;
|
||||||
|
/**
|
||||||
|
* @OneToOne(targetEntity="CmsEmail", inversedBy="user", cascade={"persist"}, orphanRemoval=true)
|
||||||
|
* @JoinColumn(referencedColumnName="id", nullable=true)
|
||||||
|
*/
|
||||||
|
public $email;
|
||||||
/**
|
/**
|
||||||
* @ManyToMany(targetEntity="CmsGroup", inversedBy="users", cascade={"persist", "merge"})
|
* @ManyToMany(targetEntity="CmsGroup", inversedBy="users", cascade={"persist", "merge"})
|
||||||
* @JoinTable(name="cms_users_groups",
|
* @JoinTable(name="cms_users_groups",
|
||||||
@ -119,4 +124,16 @@ class CmsUser
|
|||||||
$address->setUser($this);
|
$address->setUser($this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getEmail() { return $this->email; }
|
||||||
|
|
||||||
|
public function setEmail(CmsEmail $email = null) {
|
||||||
|
if ($this->email !== $email) {
|
||||||
|
$this->email = $email;
|
||||||
|
|
||||||
|
if ($email) {
|
||||||
|
$email->setUser($this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ class CompanyCar
|
|||||||
private $id;
|
private $id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Column(type="string", length="50")
|
* @Column(type="string", length=50)
|
||||||
*/
|
*/
|
||||||
private $brand;
|
private $brand;
|
||||||
|
|
||||||
|
@ -17,6 +17,11 @@ class CompanyEmployee extends CompanyPerson
|
|||||||
* @Column(type="string", length=255)
|
* @Column(type="string", length=255)
|
||||||
*/
|
*/
|
||||||
private $department;
|
private $department;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Column(type="datetime", nullable=true)
|
||||||
|
*/
|
||||||
|
private $startDate;
|
||||||
|
|
||||||
public function getSalary() {
|
public function getSalary() {
|
||||||
return $this->salary;
|
return $this->salary;
|
||||||
@ -33,4 +38,12 @@ class CompanyEmployee extends CompanyPerson
|
|||||||
public function setDepartment($dep) {
|
public function setDepartment($dep) {
|
||||||
$this->department = $dep;
|
$this->department = $dep;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getStartDate() {
|
||||||
|
return $this->startDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setStartDate($date) {
|
||||||
|
$this->startDate = $date;
|
||||||
|
}
|
||||||
}
|
}
|
@ -9,7 +9,7 @@ namespace Doctrine\Tests\Models\Company;
|
|||||||
class CompanyManager extends CompanyEmployee
|
class CompanyManager extends CompanyEmployee
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @Column(type="string", length="250")
|
* @Column(type="string", length=250)
|
||||||
*/
|
*/
|
||||||
private $title;
|
private $title;
|
||||||
|
|
||||||
|
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.doctrine-project.org>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Doctrine\Tests\Models\DDC753;
|
||||||
|
|
||||||
|
use Doctrine\ORM\EntityRepository;
|
||||||
|
|
||||||
|
class DDC753CustomRepository extends EntityRepository
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isCustomRepository()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.doctrine-project.org>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Doctrine\Tests\Models\DDC753;
|
||||||
|
|
||||||
|
use Doctrine\ORM\EntityRepository;
|
||||||
|
|
||||||
|
class DDC753DefaultRepository extends EntityRepository
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isDefaultRepository()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.doctrine-project.org>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Doctrine\Tests\Models\DDC753;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Entity(repositoryClass = "Doctrine\Tests\Models\DDC753\DDC753CustomRepository")
|
||||||
|
*/
|
||||||
|
class DDC753EntityWithCustomRepository
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Id
|
||||||
|
* @Column(type="integer")
|
||||||
|
* @GeneratedValue
|
||||||
|
*/
|
||||||
|
protected $id;
|
||||||
|
|
||||||
|
/** @column(type="string") */
|
||||||
|
protected $name;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.doctrine-project.org>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Doctrine\Tests\Models\DDC753;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Entity()
|
||||||
|
*/
|
||||||
|
class DDC753EntityWithDefaultCustomRepository
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Id
|
||||||
|
* @Column(type="integer")
|
||||||
|
* @GeneratedValue
|
||||||
|
*/
|
||||||
|
protected $id;
|
||||||
|
|
||||||
|
/** @column(type="string") */
|
||||||
|
protected $name;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.doctrine-project.org>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Doctrine\Tests\Models\DDC753;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Entity(repositoryClass = "\stdClass")
|
||||||
|
*/
|
||||||
|
class DDC753EntityWithInvalidRepository
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Id
|
||||||
|
* @Column(type="integer")
|
||||||
|
* @GeneratedValue
|
||||||
|
*/
|
||||||
|
protected $id;
|
||||||
|
|
||||||
|
/** @column(type="string") */
|
||||||
|
protected $name;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.doctrine-project.org>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Doctrine\Tests\Models\DDC753;
|
||||||
|
|
||||||
|
use Doctrine\ORM\EntityRepository;
|
||||||
|
|
||||||
|
class DDC753InvalidRepository
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
40
tests/Doctrine/Tests/Models/DDC869/DDC869ChequePayment.php
Normal file
40
tests/Doctrine/Tests/Models/DDC869/DDC869ChequePayment.php
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.doctrine-project.org>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Doctrine\Tests\Models\DDC869;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Entity
|
||||||
|
*/
|
||||||
|
class DDC869ChequePayment extends DDC869Payment
|
||||||
|
{
|
||||||
|
|
||||||
|
/** @column(type="string") */
|
||||||
|
protected $serialNumber;
|
||||||
|
|
||||||
|
public static function loadMetadata(\Doctrine\ORM\Mapping\ClassMetadataInfo $metadata)
|
||||||
|
{
|
||||||
|
$metadata->mapField(array(
|
||||||
|
'fieldName' => 'serialNumber',
|
||||||
|
'type' => 'string',
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.doctrine-project.org>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Doctrine\Tests\Models\DDC869;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Entity
|
||||||
|
*/
|
||||||
|
class DDC869CreditCardPayment extends DDC869Payment
|
||||||
|
{
|
||||||
|
|
||||||
|
/** @column(type="string") */
|
||||||
|
protected $creditCardNumber;
|
||||||
|
|
||||||
|
public static function loadMetadata(\Doctrine\ORM\Mapping\ClassMetadataInfo $metadata)
|
||||||
|
{
|
||||||
|
$metadata->mapField(array(
|
||||||
|
'fieldName' => 'creditCardNumber',
|
||||||
|
'type' => 'string',
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
57
tests/Doctrine/Tests/Models/DDC869/DDC869Payment.php
Normal file
57
tests/Doctrine/Tests/Models/DDC869/DDC869Payment.php
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.doctrine-project.org>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Doctrine\Tests\Models\DDC869;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @MappedSuperclass(repositoryClass = "Doctrine\Tests\Models\DDC869\DDC869PaymentRepository")
|
||||||
|
*/
|
||||||
|
class DDC869Payment
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Id
|
||||||
|
* @Column(type="integer")
|
||||||
|
* @GeneratedValue
|
||||||
|
*/
|
||||||
|
protected $id;
|
||||||
|
|
||||||
|
/** @column(type="float") */
|
||||||
|
protected $value;
|
||||||
|
|
||||||
|
|
||||||
|
public static function loadMetadata(\Doctrine\ORM\Mapping\ClassMetadataInfo $metadata)
|
||||||
|
{
|
||||||
|
$metadata->mapField(array(
|
||||||
|
'id' => true,
|
||||||
|
'fieldName' => 'id',
|
||||||
|
'type' => 'integer',
|
||||||
|
'columnName' => 'id',
|
||||||
|
));
|
||||||
|
$metadata->mapField(array(
|
||||||
|
'fieldName' => 'value',
|
||||||
|
'type' => 'float',
|
||||||
|
));
|
||||||
|
$metadata->isMappedSuperclass = true;
|
||||||
|
$metadata->setCustomRepositoryClass("Doctrine\Tests\Models\DDC869\DDC869PaymentRepository");
|
||||||
|
$metadata->setIdGeneratorType(\Doctrine\ORM\Mapping\ClassMetadataInfo::GENERATOR_TYPE_AUTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.doctrine-project.org>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Doctrine\Tests\Models\DDC869;
|
||||||
|
|
||||||
|
use Doctrine\ORM\EntityRepository;
|
||||||
|
|
||||||
|
class DDC869PaymentRepository extends EntityRepository
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Very complex method
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isTrue()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -22,7 +22,7 @@ class ECommerceProduct
|
|||||||
private $id;
|
private $id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Column(type="string", length=50, nullable="true")
|
* @Column(type="string", length=50, nullable=true)
|
||||||
*/
|
*/
|
||||||
private $name;
|
private $name;
|
||||||
|
|
||||||
|
91
tests/Doctrine/Tests/ORM/Event/EntityEventDelegateeTest.php
Normal file
91
tests/Doctrine/Tests/ORM/Event/EntityEventDelegateeTest.php
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Doctrine\Tests\ORM\Event;
|
||||||
|
|
||||||
|
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group DDC-1415
|
||||||
|
*/
|
||||||
|
class EntityEventDelegatorTest extends \Doctrine\Tests\OrmTestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var \Doctrine\ORM\Event\EntityEventDelegator
|
||||||
|
*/
|
||||||
|
private $delegator;
|
||||||
|
|
||||||
|
public function setUp()
|
||||||
|
{
|
||||||
|
$this->delegator = new \Doctrine\ORM\Event\EntityEventDelegator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetSubscribedEventsWhenEmpty()
|
||||||
|
{
|
||||||
|
$this->assertEquals(array(), $this->delegator->getSubscribedEvents());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAddListener()
|
||||||
|
{
|
||||||
|
$this->delegator->addEventListener('postLoad', 'stdClass', new DelegateeEventListener());
|
||||||
|
$this->assertEquals(array('postLoad'), $this->delegator->getSubscribedEvents());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAddSubscriber()
|
||||||
|
{
|
||||||
|
$this->delegator->addEventSubscriber(new DelegateeEventListener(), 'stdClass');
|
||||||
|
$this->assertEquals(array('postLoad'), $this->delegator->getSubscribedEvents());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAddListenerAfterFrozenThrowsException()
|
||||||
|
{
|
||||||
|
$this->delegator->getSubscribedEvents(); // freezes
|
||||||
|
|
||||||
|
$this->setExpectedException("LogicException", "Cannot add event listeners aft");
|
||||||
|
$this->delegator->addEventListener('postLoad', 'stdClass', new DelegateeEventListener());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDelegateEvent()
|
||||||
|
{
|
||||||
|
$delegatee = new DelegateeEventListener();
|
||||||
|
$this->delegator->addEventListener('postLoad', 'stdClass', $delegatee);
|
||||||
|
|
||||||
|
$event = new \Doctrine\ORM\Event\LifecycleEventArgs(new \stdClass(), $this->_getTestEntityManager());
|
||||||
|
$this->delegator->postLoad($event);
|
||||||
|
$this->delegator->postLoad($event);
|
||||||
|
|
||||||
|
$this->assertEquals(2, $delegatee->postLoad);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDelegatePickEntity()
|
||||||
|
{
|
||||||
|
$delegatee = new DelegateeEventListener();
|
||||||
|
$this->delegator->addEventListener('postLoad', 'stdClass', $delegatee);
|
||||||
|
|
||||||
|
$event1 = new \Doctrine\ORM\Event\LifecycleEventArgs(new \stdClass(), $this->_getTestEntityManager());
|
||||||
|
$event2 = new \Doctrine\ORM\Event\LifecycleEventArgs(new \Doctrine\Tests\Models\CMS\CmsUser(), $this->_getTestEntityManager());
|
||||||
|
$this->delegator->postLoad($event1);
|
||||||
|
$this->delegator->postLoad($event2);
|
||||||
|
|
||||||
|
$this->assertEquals(1, $delegatee->postLoad);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DelegateeEventListener implements \Doctrine\Common\EventSubscriber
|
||||||
|
{
|
||||||
|
public $postLoad = 0;
|
||||||
|
|
||||||
|
public function postLoad($args)
|
||||||
|
{
|
||||||
|
$this->postLoad++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array of events this subscriber wants to listen to.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
function getSubscribedEvents()
|
||||||
|
{
|
||||||
|
return array('postLoad');
|
||||||
|
}
|
||||||
|
}
|
@ -150,15 +150,15 @@ class BasicFunctionalTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
$user->username = 'gblanco';
|
$user->username = 'gblanco';
|
||||||
$user->status = 'developer';
|
$user->status = 'developer';
|
||||||
|
|
||||||
$this->assertEquals(\Doctrine\ORM\UnitOfWork::STATE_NEW, $this->_em->getUnitOfWork()->getEntityState($user));
|
$this->assertEquals(\Doctrine\ORM\UnitOfWork::STATE_NEW, $this->_em->getUnitOfWork()->getEntityState($user), "State should be UnitOfWork::STATE_NEW");
|
||||||
|
|
||||||
$this->_em->persist($user);
|
$this->_em->persist($user);
|
||||||
|
|
||||||
$this->assertEquals(\Doctrine\ORM\UnitOfWork::STATE_MANAGED, $this->_em->getUnitOfWork()->getEntityState($user));
|
$this->assertEquals(\Doctrine\ORM\UnitOfWork::STATE_MANAGED, $this->_em->getUnitOfWork()->getEntityState($user), "State should be UnitOfWork::STATE_MANAGED");
|
||||||
|
|
||||||
$this->_em->remove($user);
|
$this->_em->remove($user);
|
||||||
|
|
||||||
$this->assertEquals(\Doctrine\ORM\UnitOfWork::STATE_NEW, $this->_em->getUnitOfWork()->getEntityState($user));
|
$this->assertEquals(\Doctrine\ORM\UnitOfWork::STATE_NEW, $this->_em->getUnitOfWork()->getEntityState($user), "State should be UnitOfWork::STATE_NEW");
|
||||||
|
|
||||||
$this->_em->persist($user);
|
$this->_em->persist($user);
|
||||||
$this->_em->flush();
|
$this->_em->flush();
|
||||||
@ -166,10 +166,10 @@ class BasicFunctionalTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
|
|
||||||
$this->_em->remove($user);
|
$this->_em->remove($user);
|
||||||
|
|
||||||
$this->assertEquals(\Doctrine\ORM\UnitOfWork::STATE_REMOVED, $this->_em->getUnitOfWork()->getEntityState($user));
|
$this->assertEquals(\Doctrine\ORM\UnitOfWork::STATE_REMOVED, $this->_em->getUnitOfWork()->getEntityState($user), "State should be UnitOfWork::STATE_REMOVED");
|
||||||
$this->_em->flush();
|
$this->_em->flush();
|
||||||
|
|
||||||
$this->assertEquals(\Doctrine\ORM\UnitOfWork::STATE_NEW, $this->_em->getUnitOfWork()->getEntityState($user));
|
$this->assertEquals(\Doctrine\ORM\UnitOfWork::STATE_NEW, $this->_em->getUnitOfWork()->getEntityState($user), "State should be UnitOfWork::STATE_NEW");
|
||||||
|
|
||||||
$this->assertNull($this->_em->find('Doctrine\Tests\Models\CMS\CmsUser', $id));
|
$this->assertNull($this->_em->find('Doctrine\Tests\Models\CMS\CmsUser', $id));
|
||||||
}
|
}
|
||||||
|
@ -291,8 +291,21 @@ class ClassTableInheritanceTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
|
|
||||||
$this->assertTrue(count($this->_em->createQuery(
|
$this->assertTrue(count($this->_em->createQuery(
|
||||||
'SELECT count(p.id) FROM Doctrine\Tests\Models\Company\CompanyEmployee p WHERE p.salary = 1')
|
'SELECT count(p.id) FROM Doctrine\Tests\Models\Company\CompanyEmployee p WHERE p.salary = 1')
|
||||||
->getResult()) > 0);
|
->getResult()) > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group DDC-1341
|
||||||
|
*/
|
||||||
|
public function testBulkUpdateNonScalarParameterDDC1341()
|
||||||
|
{
|
||||||
|
$dql = 'UPDATE Doctrine\Tests\Models\Company\CompanyEmployee AS p SET p.startDate = ?0 WHERE p.department = ?1';
|
||||||
|
$query = $this->_em->createQuery($dql)
|
||||||
|
->setParameter(0, new \DateTime())
|
||||||
|
->setParameter(1, 'IT');
|
||||||
|
|
||||||
|
$result = $query->execute();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -59,7 +59,7 @@ class CustomTreeWalkersTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
{
|
{
|
||||||
$this->assertSqlGeneration(
|
$this->assertSqlGeneration(
|
||||||
'select u from Doctrine\Tests\Models\CMS\CmsUser u',
|
'select u from Doctrine\Tests\Models\CMS\CmsUser u',
|
||||||
"SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 FROM cms_users c0_ WHERE c0_.id = 1"
|
"SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3, c0_.email_id AS email_id4 FROM cms_users c0_ WHERE c0_.id = 1"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,7 +67,7 @@ class CustomTreeWalkersTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
{
|
{
|
||||||
$this->assertSqlGeneration(
|
$this->assertSqlGeneration(
|
||||||
'select u from Doctrine\Tests\Models\CMS\CmsUser u where u.name = :name or u.name = :otherName',
|
'select u from Doctrine\Tests\Models\CMS\CmsUser u where u.name = :name or u.name = :otherName',
|
||||||
"SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 FROM cms_users c0_ WHERE (c0_.name = ? OR c0_.name = ?) AND c0_.id = 1"
|
"SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3, c0_.email_id AS email_id4 FROM cms_users c0_ WHERE (c0_.name = ? OR c0_.name = ?) AND c0_.id = 1"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,7 +75,7 @@ class CustomTreeWalkersTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
{
|
{
|
||||||
$this->assertSqlGeneration(
|
$this->assertSqlGeneration(
|
||||||
'select u from Doctrine\Tests\Models\CMS\CmsUser u where u.name = :name',
|
'select u from Doctrine\Tests\Models\CMS\CmsUser u where u.name = :name',
|
||||||
"SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 FROM cms_users c0_ WHERE c0_.name = ? AND c0_.id = 1"
|
"SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3, c0_.email_id AS email_id4 FROM cms_users c0_ WHERE c0_.name = ? AND c0_.id = 1"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ namespace Doctrine\Tests\ORM\Functional;
|
|||||||
use Doctrine\Tests\Models\CMS\CmsUser;
|
use Doctrine\Tests\Models\CMS\CmsUser;
|
||||||
use Doctrine\Tests\Models\CMS\CmsPhonenumber;
|
use Doctrine\Tests\Models\CMS\CmsPhonenumber;
|
||||||
use Doctrine\Tests\Models\CMS\CmsAddress;
|
use Doctrine\Tests\Models\CMS\CmsAddress;
|
||||||
|
use Doctrine\Tests\Models\CMS\CmsArticle;
|
||||||
use Doctrine\ORM\UnitOfWork;
|
use Doctrine\ORM\UnitOfWork;
|
||||||
|
|
||||||
require_once __DIR__ . '/../../TestInit.php';
|
require_once __DIR__ . '/../../TestInit.php';
|
||||||
@ -192,5 +193,26 @@ class DetachedEntityTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
$this->assertFalse($this->_em->contains($user));
|
$this->assertFalse($this->_em->contains($user));
|
||||||
$this->assertFalse($this->_em->getUnitOfWork()->isInIdentityMap($user));
|
$this->assertFalse($this->_em->getUnitOfWork()->isInIdentityMap($user));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group DDC-1340
|
||||||
|
*/
|
||||||
|
public function testMergeArticleWrongVersion()
|
||||||
|
{
|
||||||
|
$article = new CmsArticle();
|
||||||
|
$article->topic = "test";
|
||||||
|
$article->text = "test";
|
||||||
|
|
||||||
|
$this->_em->persist($article);
|
||||||
|
$this->_em->flush();
|
||||||
|
|
||||||
|
$this->_em->detach($article);
|
||||||
|
|
||||||
|
$sql = "UPDATE cms_articles SET version = version+1 WHERE id = " . $article->id;
|
||||||
|
$this->_em->getConnection()->executeUpdate($sql);
|
||||||
|
|
||||||
|
$this->setExpectedException('Doctrine\ORM\OptimisticLockException', 'The optimistic lock failed, version 1 was expected, but is actually 2');
|
||||||
|
$this->_em->merge($article);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -433,5 +433,43 @@ class EntityRepositoryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
$this->assertSame($usersAsc[0], $usersDesc[1]);
|
$this->assertSame($usersAsc[0], $usersDesc[1]);
|
||||||
$this->assertSame($usersAsc[1], $usersDesc[0]);
|
$this->assertSame($usersAsc[1], $usersDesc[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group DDC-753
|
||||||
|
*/
|
||||||
|
public function testDefaultRepositoryClassName()
|
||||||
|
{
|
||||||
|
$this->assertEquals($this->_em->getConfiguration()->getDefaultRepositoryClassName(), "Doctrine\ORM\EntityRepository");
|
||||||
|
$this->_em->getConfiguration()->setDefaultRepositoryClassName("Doctrine\Tests\Models\DDC753\DDC753DefaultRepository");
|
||||||
|
$this->assertEquals($this->_em->getConfiguration()->getDefaultRepositoryClassName(), "Doctrine\Tests\Models\DDC753\DDC753DefaultRepository");
|
||||||
|
|
||||||
|
$repos = $this->_em->getRepository('Doctrine\Tests\Models\DDC753\DDC753EntityWithDefaultCustomRepository');
|
||||||
|
$this->assertInstanceOf("Doctrine\Tests\Models\DDC753\DDC753DefaultRepository", $repos);
|
||||||
|
$this->assertTrue($repos->isDefaultRepository());
|
||||||
|
|
||||||
|
|
||||||
|
$repos = $this->_em->getRepository('Doctrine\Tests\Models\DDC753\DDC753EntityWithCustomRepository');
|
||||||
|
$this->assertInstanceOf("Doctrine\Tests\Models\DDC753\DDC753CustomRepository", $repos);
|
||||||
|
$this->assertTrue($repos->isCustomRepository());
|
||||||
|
|
||||||
|
$this->assertEquals($this->_em->getConfiguration()->getDefaultRepositoryClassName(), "Doctrine\Tests\Models\DDC753\DDC753DefaultRepository");
|
||||||
|
$this->_em->getConfiguration()->setDefaultRepositoryClassName("Doctrine\ORM\EntityRepository");
|
||||||
|
$this->assertEquals($this->_em->getConfiguration()->getDefaultRepositoryClassName(), "Doctrine\ORM\EntityRepository");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group DDC-753
|
||||||
|
* @expectedException Doctrine\ORM\ORMException
|
||||||
|
* @expectedExceptionMessage Invalid repository class 'Doctrine\Tests\Models\DDC753\DDC753InvalidRepository'. it must be a Doctrine\ORM\EntityRepository.
|
||||||
|
*/
|
||||||
|
public function testSetDefaultRepositoryInvalidClassError()
|
||||||
|
{
|
||||||
|
$this->assertEquals($this->_em->getConfiguration()->getDefaultRepositoryClassName(), "Doctrine\ORM\EntityRepository");
|
||||||
|
$this->_em->getConfiguration()->setDefaultRepositoryClassName("Doctrine\Tests\Models\DDC753\DDC753InvalidRepository");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,58 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Doctrine\Tests\ORM\Functional;
|
||||||
|
|
||||||
|
use Doctrine\Tests\Models\CMS\CmsUser,
|
||||||
|
Doctrine\Tests\Models\CMS\CmsAddress,
|
||||||
|
Doctrine\Tests\Models\CMS\CmsPhonenumber;
|
||||||
|
|
||||||
|
require_once __DIR__ . '/../../TestInit.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests a bidirectional one-to-many association mapping with orphan removal.
|
||||||
|
*/
|
||||||
|
class OneToManyOrphanRemovalTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||||
|
{
|
||||||
|
protected function setUp()
|
||||||
|
{
|
||||||
|
$this->useModelSet('cms');
|
||||||
|
|
||||||
|
parent::setUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testOrphanRemoval()
|
||||||
|
{
|
||||||
|
$user = new CmsUser;
|
||||||
|
$user->status = 'dev';
|
||||||
|
$user->username = 'romanb';
|
||||||
|
$user->name = 'Roman B.';
|
||||||
|
|
||||||
|
$phone = new CmsPhonenumber;
|
||||||
|
$phone->phonenumber = '123456';
|
||||||
|
|
||||||
|
$user->addPhonenumber($phone);
|
||||||
|
|
||||||
|
$this->_em->persist($user);
|
||||||
|
$this->_em->flush();
|
||||||
|
|
||||||
|
$userId = $user->getId();
|
||||||
|
|
||||||
|
$this->_em->clear();
|
||||||
|
|
||||||
|
$userProxy = $this->_em->getReference('Doctrine\Tests\Models\CMS\CmsUser', $userId);
|
||||||
|
|
||||||
|
$this->_em->remove($userProxy);
|
||||||
|
$this->_em->flush();
|
||||||
|
$this->_em->clear();
|
||||||
|
|
||||||
|
$query = $this->_em->createQuery('SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u');
|
||||||
|
$result = $query->getResult();
|
||||||
|
|
||||||
|
$this->assertEquals(0, count($result), 'CmsUser should be removed by EntityManager');
|
||||||
|
|
||||||
|
$query = $this->_em->createQuery('SELECT p FROM Doctrine\Tests\Models\CMS\CmsPhonenumber p');
|
||||||
|
$result = $query->getResult();
|
||||||
|
|
||||||
|
$this->assertEquals(0, count($result), 'CmsPhonenumber should be removed by orphanRemoval');
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,94 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Doctrine\Tests\ORM\Functional;
|
||||||
|
|
||||||
|
use Doctrine\Tests\Models\CMS\CmsUser,
|
||||||
|
Doctrine\Tests\Models\CMS\CmsEmail,
|
||||||
|
Doctrine\Tests\Models\CMS\CmsAddress,
|
||||||
|
Doctrine\Tests\Models\CMS\CmsPhonenumber;
|
||||||
|
|
||||||
|
require_once __DIR__ . '/../../TestInit.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests a bidirectional one-to-one association mapping with orphan removal.
|
||||||
|
*/
|
||||||
|
class OneToOneOrphanRemovalTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||||
|
{
|
||||||
|
protected function setUp()
|
||||||
|
{
|
||||||
|
$this->useModelSet('cms');
|
||||||
|
|
||||||
|
parent::setUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testOrphanRemoval()
|
||||||
|
{
|
||||||
|
$user = new CmsUser;
|
||||||
|
$user->status = 'dev';
|
||||||
|
$user->username = 'romanb';
|
||||||
|
$user->name = 'Roman B.';
|
||||||
|
|
||||||
|
$address = new CmsAddress;
|
||||||
|
$address->country = 'de';
|
||||||
|
$address->zip = 1234;
|
||||||
|
$address->city = 'Berlin';
|
||||||
|
|
||||||
|
$user->setAddress($address);
|
||||||
|
|
||||||
|
$this->_em->persist($user);
|
||||||
|
$this->_em->flush();
|
||||||
|
|
||||||
|
$userId = $user->getId();
|
||||||
|
|
||||||
|
$this->_em->clear();
|
||||||
|
|
||||||
|
$userProxy = $this->_em->getReference('Doctrine\Tests\Models\CMS\CmsUser', $userId);
|
||||||
|
|
||||||
|
$this->_em->remove($userProxy);
|
||||||
|
$this->_em->flush();
|
||||||
|
$this->_em->clear();
|
||||||
|
|
||||||
|
$query = $this->_em->createQuery('SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u');
|
||||||
|
$result = $query->getResult();
|
||||||
|
|
||||||
|
$this->assertEquals(0, count($result), 'CmsUser should be removed by EntityManager');
|
||||||
|
|
||||||
|
$query = $this->_em->createQuery('SELECT a FROM Doctrine\Tests\Models\CMS\CmsAddress a');
|
||||||
|
$result = $query->getResult();
|
||||||
|
|
||||||
|
$this->assertEquals(0, count($result), 'CmsAddress should be removed by orphanRemoval');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testOrphanRemovalWhenUnlink()
|
||||||
|
{
|
||||||
|
$user = new CmsUser;
|
||||||
|
$user->status = 'dev';
|
||||||
|
$user->username = 'beberlei';
|
||||||
|
$user->name = 'Bejamin Eberlei';
|
||||||
|
|
||||||
|
$email = new CmsEmail;
|
||||||
|
$email->email = 'beberlei@domain.com';
|
||||||
|
|
||||||
|
$user->setEmail($email);
|
||||||
|
|
||||||
|
$this->_em->persist($user);
|
||||||
|
$this->_em->flush();
|
||||||
|
|
||||||
|
$userId = $user->getId();
|
||||||
|
|
||||||
|
$this->_em->clear();
|
||||||
|
|
||||||
|
$user = $this->_em->find('Doctrine\Tests\Models\CMS\CmsUser', $userId);
|
||||||
|
|
||||||
|
$user->setEmail(null);
|
||||||
|
|
||||||
|
$this->_em->persist($user);
|
||||||
|
$this->_em->flush();
|
||||||
|
$this->_em->clear();
|
||||||
|
|
||||||
|
$query = $this->_em->createQuery('SELECT e FROM Doctrine\Tests\Models\CMS\CmsEmail e');
|
||||||
|
$result = $query->getResult();
|
||||||
|
|
||||||
|
$this->assertEquals(0, count($result), 'CmsEmail should be removed by orphanRemoval');
|
||||||
|
}
|
||||||
|
}
|
@ -14,10 +14,27 @@ require_once __DIR__ . '/../../TestInit.php';
|
|||||||
*/
|
*/
|
||||||
class QueryCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
class QueryCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @var \ReflectionProperty
|
||||||
|
*/
|
||||||
|
private $cacheDataReflection;
|
||||||
|
|
||||||
protected function setUp() {
|
protected function setUp() {
|
||||||
|
$this->cacheDataReflection = new \ReflectionProperty("Doctrine\Common\Cache\ArrayCache", "data");
|
||||||
|
$this->cacheDataReflection->setAccessible(true);
|
||||||
$this->useModelSet('cms');
|
$this->useModelSet('cms');
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ArrayCache $cache
|
||||||
|
* @return integer
|
||||||
|
*/
|
||||||
|
private function getCacheSize(ArrayCache $cache)
|
||||||
|
{
|
||||||
|
return sizeof($this->cacheDataReflection->getValue($cache));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public function testQueryCache_DependsOnHints()
|
public function testQueryCache_DependsOnHints()
|
||||||
{
|
{
|
||||||
@ -27,12 +44,12 @@ class QueryCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
$query->setQueryCacheDriver($cache);
|
$query->setQueryCacheDriver($cache);
|
||||||
|
|
||||||
$query->getResult();
|
$query->getResult();
|
||||||
$this->assertEquals(1, count($cache->getIds()));
|
$this->assertEquals(1, $this->getCacheSize($cache));
|
||||||
|
|
||||||
$query->setHint('foo', 'bar');
|
$query->setHint('foo', 'bar');
|
||||||
|
|
||||||
$query->getResult();
|
$query->getResult();
|
||||||
$this->assertEquals(2, count($cache->getIds()));
|
$this->assertEquals(2, $this->getCacheSize($cache));
|
||||||
|
|
||||||
return $query;
|
return $query;
|
||||||
}
|
}
|
||||||
@ -44,13 +61,13 @@ class QueryCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
public function testQueryCache_DependsOnFirstResult($query)
|
public function testQueryCache_DependsOnFirstResult($query)
|
||||||
{
|
{
|
||||||
$cache = $query->getQueryCacheDriver();
|
$cache = $query->getQueryCacheDriver();
|
||||||
$cacheCount = count($cache->getIds());
|
$cacheCount = $this->getCacheSize($cache);
|
||||||
|
|
||||||
$query->setFirstResult(10);
|
$query->setFirstResult(10);
|
||||||
$query->setMaxResults(9999);
|
$query->setMaxResults(9999);
|
||||||
|
|
||||||
$query->getResult();
|
$query->getResult();
|
||||||
$this->assertEquals($cacheCount + 1, count($cache->getIds()));
|
$this->assertEquals($cacheCount + 1, $this->getCacheSize($cache));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -60,12 +77,12 @@ class QueryCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
public function testQueryCache_DependsOnMaxResults($query)
|
public function testQueryCache_DependsOnMaxResults($query)
|
||||||
{
|
{
|
||||||
$cache = $query->getQueryCacheDriver();
|
$cache = $query->getQueryCacheDriver();
|
||||||
$cacheCount = count($cache->getIds());
|
$cacheCount = $this->getCacheSize($cache);
|
||||||
|
|
||||||
$query->setMaxResults(10);
|
$query->setMaxResults(10);
|
||||||
|
|
||||||
$query->getResult();
|
$query->getResult();
|
||||||
$this->assertEquals($cacheCount + 1, count($cache->getIds()));
|
$this->assertEquals($cacheCount + 1, $this->getCacheSize($cache));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -75,10 +92,10 @@ class QueryCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
public function testQueryCache_DependsOnHydrationMode($query)
|
public function testQueryCache_DependsOnHydrationMode($query)
|
||||||
{
|
{
|
||||||
$cache = $query->getQueryCacheDriver();
|
$cache = $query->getQueryCacheDriver();
|
||||||
$cacheCount = count($cache->getIds());
|
$cacheCount = $this->getCacheSize($cache);
|
||||||
|
|
||||||
$query->getArrayResult();
|
$query->getArrayResult();
|
||||||
$this->assertEquals($cacheCount + 1, count($cache->getIds()));
|
$this->assertEquals($cacheCount + 1, $this->getCacheSize($cache));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testQueryCache_NoHitSaveParserResult()
|
public function testQueryCache_NoHitSaveParserResult()
|
||||||
@ -87,13 +104,13 @@ class QueryCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
|
|
||||||
$query = $this->_em->createQuery('select ux from Doctrine\Tests\Models\CMS\CmsUser ux');
|
$query = $this->_em->createQuery('select ux from Doctrine\Tests\Models\CMS\CmsUser ux');
|
||||||
|
|
||||||
$cache = $this->getMock('Doctrine\Common\Cache\AbstractCache', array('_doFetch', '_doContains', '_doSave', '_doDelete', 'getIds'));
|
$cache = $this->getMock('Doctrine\Common\Cache\ArrayCache', array('doFetch', 'doSave'));
|
||||||
$cache->expects($this->at(0))
|
$cache->expects($this->at(0))
|
||||||
->method('_doFetch')
|
->method('doFetch')
|
||||||
->with($this->isType('string'))
|
->with($this->isType('string'))
|
||||||
->will($this->returnValue(false));
|
->will($this->returnValue(false));
|
||||||
$cache->expects($this->at(1))
|
$cache->expects($this->at(1))
|
||||||
->method('_doSave')
|
->method('doSave')
|
||||||
->with($this->isType('string'), $this->isInstanceOf('Doctrine\ORM\Query\ParserResult'), $this->equalTo(null));
|
->with($this->isType('string'), $this->isInstanceOf('Doctrine\ORM\Query\ParserResult'), $this->equalTo(null));
|
||||||
|
|
||||||
$query->setQueryCacheDriver($cache);
|
$query->setQueryCacheDriver($cache);
|
||||||
@ -117,13 +134,14 @@ class QueryCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
->method('getSqlExecutor')
|
->method('getSqlExecutor')
|
||||||
->will($this->returnValue($sqlExecMock));
|
->will($this->returnValue($sqlExecMock));
|
||||||
|
|
||||||
$cache = $this->getMock('Doctrine\Common\Cache\AbstractCache', array('_doFetch', '_doContains', '_doSave', '_doDelete', 'getIds'));
|
$cache = $this->getMock('Doctrine\Common\Cache\CacheProvider',
|
||||||
|
array('doFetch', 'doContains', 'doSave', 'doDelete', 'doFlush'));
|
||||||
$cache->expects($this->once())
|
$cache->expects($this->once())
|
||||||
->method('_doFetch')
|
->method('doFetch')
|
||||||
->with($this->isType('string'))
|
->with($this->isType('string'))
|
||||||
->will($this->returnValue($parserResultMock));
|
->will($this->returnValue($parserResultMock));
|
||||||
$cache->expects($this->never())
|
$cache->expects($this->never())
|
||||||
->method('_doSave');
|
->method('doSave');
|
||||||
|
|
||||||
$query->setQueryCacheDriver($cache);
|
$query->setQueryCacheDriver($cache);
|
||||||
|
|
||||||
|
@ -501,4 +501,66 @@ class QueryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
|
|
||||||
$this->assertEquals(0, count($users));
|
$this->assertEquals(0, count($users));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testQueryWithArrayOfEntitiesAsParameter()
|
||||||
|
{
|
||||||
|
$userA = new CmsUser;
|
||||||
|
$userA->name = 'Benjamin';
|
||||||
|
$userA->username = 'beberlei';
|
||||||
|
$userA->status = 'developer';
|
||||||
|
$this->_em->persist($userA);
|
||||||
|
|
||||||
|
$userB = new CmsUser;
|
||||||
|
$userB->name = 'Roman';
|
||||||
|
$userB->username = 'romanb';
|
||||||
|
$userB->status = 'developer';
|
||||||
|
$this->_em->persist($userB);
|
||||||
|
|
||||||
|
$userC = new CmsUser;
|
||||||
|
$userC->name = 'Jonathan';
|
||||||
|
$userC->username = 'jwage';
|
||||||
|
$userC->status = 'developer';
|
||||||
|
$this->_em->persist($userC);
|
||||||
|
|
||||||
|
$this->_em->flush();
|
||||||
|
$this->_em->clear();
|
||||||
|
|
||||||
|
$query = $this->_em->createQuery("SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u IN (?0) OR u.username = ?1");
|
||||||
|
$query->setParameter(0, array($userA, $userC));
|
||||||
|
$query->setParameter(1, 'beberlei');
|
||||||
|
|
||||||
|
$users = $query->execute();
|
||||||
|
|
||||||
|
$this->assertEquals(2, count($users));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testQueryWithHiddenAsSelectExpression()
|
||||||
|
{
|
||||||
|
$userA = new CmsUser;
|
||||||
|
$userA->name = 'Benjamin';
|
||||||
|
$userA->username = 'beberlei';
|
||||||
|
$userA->status = 'developer';
|
||||||
|
$this->_em->persist($userA);
|
||||||
|
|
||||||
|
$userB = new CmsUser;
|
||||||
|
$userB->name = 'Roman';
|
||||||
|
$userB->username = 'romanb';
|
||||||
|
$userB->status = 'developer';
|
||||||
|
$this->_em->persist($userB);
|
||||||
|
|
||||||
|
$userC = new CmsUser;
|
||||||
|
$userC->name = 'Jonathan';
|
||||||
|
$userC->username = 'jwage';
|
||||||
|
$userC->status = 'developer';
|
||||||
|
$this->_em->persist($userC);
|
||||||
|
|
||||||
|
$this->_em->flush();
|
||||||
|
$this->_em->clear();
|
||||||
|
|
||||||
|
$query = $this->_em->createQuery("SELECT u, (SELECT COUNT(u2.id) FROM Doctrine\Tests\Models\CMS\CmsUser u2) AS HIDDEN total FROM Doctrine\Tests\Models\CMS\CmsUser u");
|
||||||
|
$users = $query->execute();
|
||||||
|
|
||||||
|
$this->assertEquals(3, count($users));
|
||||||
|
$this->assertInstanceOf('Doctrine\Tests\Models\CMS\CmsUser', $users[0]);
|
||||||
|
}
|
||||||
}
|
}
|
@ -15,10 +15,26 @@ require_once __DIR__ . '/../../TestInit.php';
|
|||||||
*/
|
*/
|
||||||
class ResultCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
class ResultCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @var \ReflectionProperty
|
||||||
|
*/
|
||||||
|
private $cacheDataReflection;
|
||||||
|
|
||||||
protected function setUp() {
|
protected function setUp() {
|
||||||
|
$this->cacheDataReflection = new \ReflectionProperty("Doctrine\Common\Cache\ArrayCache", "data");
|
||||||
|
$this->cacheDataReflection->setAccessible(true);
|
||||||
$this->useModelSet('cms');
|
$this->useModelSet('cms');
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ArrayCache $cache
|
||||||
|
* @return integer
|
||||||
|
*/
|
||||||
|
private function getCacheSize(ArrayCache $cache)
|
||||||
|
{
|
||||||
|
return sizeof($this->cacheDataReflection->getValue($cache));
|
||||||
|
}
|
||||||
|
|
||||||
public function testResultCache()
|
public function testResultCache()
|
||||||
{
|
{
|
||||||
@ -125,9 +141,9 @@ class ResultCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
$cache = new ArrayCache();
|
$cache = new ArrayCache();
|
||||||
$query->setResultCacheDriver($cache)->useResultCache(true);
|
$query->setResultCacheDriver($cache)->useResultCache(true);
|
||||||
|
|
||||||
$this->assertEquals(0, count($cache->getIds()));
|
$this->assertEquals(0, $this->getCacheSize($cache));
|
||||||
$query->getResult();
|
$query->getResult();
|
||||||
$this->assertEquals(1, count($cache->getIds()));
|
$this->assertEquals(1, $this->getCacheSize($cache));
|
||||||
|
|
||||||
return $query;
|
return $query;
|
||||||
}
|
}
|
||||||
@ -139,12 +155,12 @@ class ResultCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
public function testResultCacheDependsOnQueryHints($query)
|
public function testResultCacheDependsOnQueryHints($query)
|
||||||
{
|
{
|
||||||
$cache = $query->getResultCacheDriver();
|
$cache = $query->getResultCacheDriver();
|
||||||
$cacheCount = count($cache->getIds());
|
$cacheCount = $this->getCacheSize($cache);
|
||||||
|
|
||||||
$query->setHint('foo', 'bar');
|
$query->setHint('foo', 'bar');
|
||||||
$query->getResult();
|
$query->getResult();
|
||||||
|
|
||||||
$this->assertEquals($cacheCount + 1, count($cache->getIds()));
|
$this->assertEquals($cacheCount + 1, $this->getCacheSize($cache));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -154,12 +170,12 @@ class ResultCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
public function testResultCacheDependsOnParameters($query)
|
public function testResultCacheDependsOnParameters($query)
|
||||||
{
|
{
|
||||||
$cache = $query->getResultCacheDriver();
|
$cache = $query->getResultCacheDriver();
|
||||||
$cacheCount = count($cache->getIds());
|
$cacheCount = $this->getCacheSize($cache);
|
||||||
|
|
||||||
$query->setParameter(1, 50);
|
$query->setParameter(1, 50);
|
||||||
$query->getResult();
|
$query->getResult();
|
||||||
|
|
||||||
$this->assertEquals($cacheCount + 1, count($cache->getIds()));
|
$this->assertEquals($cacheCount + 1, $this->getCacheSize($cache));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -169,12 +185,12 @@ class ResultCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
public function testResultCacheDependsOnHydrationMode($query)
|
public function testResultCacheDependsOnHydrationMode($query)
|
||||||
{
|
{
|
||||||
$cache = $query->getResultCacheDriver();
|
$cache = $query->getResultCacheDriver();
|
||||||
$cacheCount = count($cache->getIds());
|
$cacheCount = $this->getCacheSize($cache);
|
||||||
|
|
||||||
$this->assertNotEquals(\Doctrine\ORM\Query::HYDRATE_ARRAY, $query->getHydrationMode());
|
$this->assertNotEquals(\Doctrine\ORM\Query::HYDRATE_ARRAY, $query->getHydrationMode());
|
||||||
$query->getArrayResult();
|
$query->getArrayResult();
|
||||||
|
|
||||||
$this->assertEquals($cacheCount + 1, count($cache->getIds()));
|
$this->assertEquals($cacheCount + 1, $this->getCacheSize($cache));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -253,24 +253,27 @@ class SQLFilterTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
|
|
||||||
public function testQueryCache_DependsOnFilters()
|
public function testQueryCache_DependsOnFilters()
|
||||||
{
|
{
|
||||||
|
$cacheDataReflection = new \ReflectionProperty("Doctrine\Common\Cache\ArrayCache", "data");
|
||||||
|
$cacheDataReflection->setAccessible(true);
|
||||||
|
|
||||||
$query = $this->_em->createQuery('select ux from Doctrine\Tests\Models\CMS\CmsUser ux');
|
$query = $this->_em->createQuery('select ux from Doctrine\Tests\Models\CMS\CmsUser ux');
|
||||||
|
|
||||||
$cache = new ArrayCache();
|
$cache = new ArrayCache();
|
||||||
$query->setQueryCacheDriver($cache);
|
$query->setQueryCacheDriver($cache);
|
||||||
|
|
||||||
$query->getResult();
|
$query->getResult();
|
||||||
$this->assertEquals(1, count($cache->getIds()));
|
$this->assertEquals(1, sizeof($cacheDataReflection->getValue($cache)));
|
||||||
|
|
||||||
$conf = $this->_em->getConfiguration();
|
$conf = $this->_em->getConfiguration();
|
||||||
$conf->addFilter("locale", "\Doctrine\Tests\ORM\Functional\MyLocaleFilter");
|
$conf->addFilter("locale", "\Doctrine\Tests\ORM\Functional\MyLocaleFilter");
|
||||||
$this->_em->getFilters()->enable("locale");
|
$this->_em->getFilters()->enable("locale");
|
||||||
|
|
||||||
$query->getResult();
|
$query->getResult();
|
||||||
$this->assertEquals(2, count($cache->getIds()));
|
$this->assertEquals(2, sizeof($cacheDataReflection->getValue($cache)));
|
||||||
|
|
||||||
// Another time doesn't add another cache entry
|
// Another time doesn't add another cache entry
|
||||||
$query->getResult();
|
$query->getResult();
|
||||||
$this->assertEquals(2, count($cache->getIds()));
|
$this->assertEquals(2, sizeof($cacheDataReflection->getValue($cache)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testQueryGeneration_DependsOnFilters()
|
public function testQueryGeneration_DependsOnFilters()
|
||||||
|
99
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1113Test.php
Normal file
99
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1113Test.php
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||||
|
|
||||||
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
|
|
||||||
|
require_once __DIR__ . '/../../../TestInit.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group DDC-1113
|
||||||
|
* @group DDC-1306
|
||||||
|
*/
|
||||||
|
class DDC1113Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||||
|
{
|
||||||
|
|
||||||
|
public function setUp()
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
try {
|
||||||
|
$this->_schemaTool->createSchema(array(
|
||||||
|
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1113Engine'),
|
||||||
|
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1113Vehicle'),
|
||||||
|
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1113Car'),
|
||||||
|
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1113Bus'),
|
||||||
|
));
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIssue()
|
||||||
|
{
|
||||||
|
$car = new DDC1113Car();
|
||||||
|
$car->engine = new DDC1113Engine();
|
||||||
|
|
||||||
|
$bus = new DDC1113Bus();
|
||||||
|
$bus->engine = new DDC1113Engine();
|
||||||
|
|
||||||
|
$this->_em->persist($car);
|
||||||
|
$this->_em->flush();
|
||||||
|
|
||||||
|
$this->_em->persist($bus);
|
||||||
|
$this->_em->flush();
|
||||||
|
|
||||||
|
$this->_em->remove($bus);
|
||||||
|
$this->_em->remove($car);
|
||||||
|
$this->_em->flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Entity
|
||||||
|
* @InheritanceType("SINGLE_TABLE")
|
||||||
|
* @DiscriminatorMap({"car" = "DDC1113Car", "bus" = "DDC1113Bus"})
|
||||||
|
*/
|
||||||
|
class DDC1113Vehicle
|
||||||
|
{
|
||||||
|
|
||||||
|
/** @Id @GeneratedValue @Column(type="integer") */
|
||||||
|
public $id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ManyToOne(targetEntity="DDC1113Vehicle")
|
||||||
|
*/
|
||||||
|
public $parent;
|
||||||
|
|
||||||
|
/** @OneToOne(targetEntity="DDC1113Engine", cascade={"persist", "remove"}) */
|
||||||
|
public $engine;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Entity
|
||||||
|
*/
|
||||||
|
class DDC1113Car extends DDC1113Vehicle
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Entity
|
||||||
|
*/
|
||||||
|
class DDC1113Bus extends DDC1113Vehicle
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Entity
|
||||||
|
*/
|
||||||
|
class DDC1113Engine
|
||||||
|
{
|
||||||
|
|
||||||
|
/** @Id @GeneratedValue @Column(type="integer") */
|
||||||
|
public $id;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
54
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1306Test.php
Normal file
54
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1306Test.php
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||||
|
|
||||||
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
|
use Doctrine\Tests\Models\CMS\CmsUser;
|
||||||
|
use Doctrine\Tests\Models\CMS\CmsGroup;
|
||||||
|
use Doctrine\Tests\Models\CMS\CmsPhonenumber;
|
||||||
|
|
||||||
|
require_once __DIR__ . '/../../../TestInit.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group DDC-1306
|
||||||
|
*/
|
||||||
|
class DDC1306Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||||
|
{
|
||||||
|
public function setUp()
|
||||||
|
{
|
||||||
|
$this->useModelSet('cms');
|
||||||
|
parent::setUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIssue()
|
||||||
|
{
|
||||||
|
$phone = new CmsPhonenumber();
|
||||||
|
$phone->phonenumber = "1234";
|
||||||
|
|
||||||
|
// puts user and phone into commit order calculator
|
||||||
|
$this->_em->persist($phone);
|
||||||
|
$this->_em->flush();
|
||||||
|
|
||||||
|
$address = new \Doctrine\Tests\Models\CMS\CmsAddress();
|
||||||
|
$address->city = "bonn";
|
||||||
|
$address->country = "Germany";
|
||||||
|
$address->street = "somestreet!";
|
||||||
|
$address->zip = 12345;
|
||||||
|
|
||||||
|
$this->_em->persist($address);
|
||||||
|
|
||||||
|
$user = new CmsUser();
|
||||||
|
$user->username = "beberlei";
|
||||||
|
$user->name = "benjamin";
|
||||||
|
$user->status = "active";
|
||||||
|
$user->setAddress($address);
|
||||||
|
|
||||||
|
// puts user and address into commit order calculator, but does not calculate user dependencies new
|
||||||
|
$this->_em->persist($user);
|
||||||
|
$this->_em->flush();
|
||||||
|
|
||||||
|
$this->_em->remove($user->getAddress());
|
||||||
|
$this->_em->remove($user);
|
||||||
|
$this->_em->flush();
|
||||||
|
}
|
||||||
|
}
|
214
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1335Test.php
Normal file
214
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1335Test.php
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||||
|
|
||||||
|
use DateTime;
|
||||||
|
|
||||||
|
require_once __DIR__ . '/../../../TestInit.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group DDC-1135
|
||||||
|
*/
|
||||||
|
class DDC1135Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||||
|
{
|
||||||
|
protected function setUp()
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
try {
|
||||||
|
$this->_schemaTool->createSchema(array(
|
||||||
|
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1135User'),
|
||||||
|
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1135Phone'),
|
||||||
|
));
|
||||||
|
$this->loadFixture();
|
||||||
|
} catch(\Exception $e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function testDql()
|
||||||
|
{
|
||||||
|
$dql = 'SELECT u FROM ' . __NAMESPACE__ . '\DDC1135User u INDEX BY u.id';
|
||||||
|
$query = $this->_em->createQuery($dql);
|
||||||
|
$result = $query->getResult();
|
||||||
|
|
||||||
|
$this->assertEquals(sizeof($result), 3);
|
||||||
|
$this->assertArrayHasKey(1, $result);
|
||||||
|
$this->assertArrayHasKey(2, $result);
|
||||||
|
$this->assertArrayHasKey(3, $result);
|
||||||
|
|
||||||
|
$dql = 'SELECT u, p FROM '.__NAMESPACE__ . '\DDC1135User u INDEX BY u.email INNER JOIN u.phones p INDEX BY p.id';
|
||||||
|
$query = $this->_em->createQuery($dql);
|
||||||
|
$result = $query->getResult();
|
||||||
|
|
||||||
|
$this->assertEquals(sizeof($result), 3);
|
||||||
|
$this->assertArrayHasKey('foo@foo.com', $result);
|
||||||
|
$this->assertArrayHasKey('bar@bar.com', $result);
|
||||||
|
$this->assertArrayHasKey('foobar@foobar.com', $result);
|
||||||
|
|
||||||
|
$this->assertEquals(sizeof($result['foo@foo.com']->phones), 3);
|
||||||
|
$this->assertEquals(sizeof($result['bar@bar.com']->phones), 3);
|
||||||
|
$this->assertEquals(sizeof($result['foobar@foobar.com']->phones), 3);
|
||||||
|
|
||||||
|
$this->assertArrayHasKey(1, $result['foo@foo.com']->phones->toArray());
|
||||||
|
$this->assertArrayHasKey(2, $result['foo@foo.com']->phones->toArray());
|
||||||
|
$this->assertArrayHasKey(3, $result['foo@foo.com']->phones->toArray());
|
||||||
|
|
||||||
|
$this->assertArrayHasKey(4, $result['bar@bar.com']->phones->toArray());
|
||||||
|
$this->assertArrayHasKey(5, $result['bar@bar.com']->phones->toArray());
|
||||||
|
$this->assertArrayHasKey(6, $result['bar@bar.com']->phones->toArray());
|
||||||
|
|
||||||
|
$this->assertArrayHasKey(7, $result['foobar@foobar.com']->phones->toArray());
|
||||||
|
$this->assertArrayHasKey(8, $result['foobar@foobar.com']->phones->toArray());
|
||||||
|
$this->assertArrayHasKey(9, $result['foobar@foobar.com']->phones->toArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testTicket()
|
||||||
|
{
|
||||||
|
$builder = $this->_em->createQueryBuilder();
|
||||||
|
$builder->select('u')->from(__NAMESPACE__ . '\DDC1135User', 'u', 'u.id');
|
||||||
|
|
||||||
|
$dql = $builder->getQuery()->getDQL();
|
||||||
|
$result = $builder->getQuery()->getResult();
|
||||||
|
|
||||||
|
$this->assertEquals(sizeof($result), 3);
|
||||||
|
$this->assertArrayHasKey(1, $result);
|
||||||
|
$this->assertArrayHasKey(2, $result);
|
||||||
|
$this->assertArrayHasKey(3, $result);
|
||||||
|
$this->assertEquals('SELECT u FROM ' . __NAMESPACE__ . '\DDC1135User u INDEX BY u.id', $dql);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIndexByUnique()
|
||||||
|
{
|
||||||
|
$builder = $this->_em->createQueryBuilder();
|
||||||
|
$builder->select('u')->from(__NAMESPACE__ . '\DDC1135User', 'u', 'u.email');
|
||||||
|
|
||||||
|
$dql = $builder->getQuery()->getDQL();
|
||||||
|
$result = $builder->getQuery()->getResult();
|
||||||
|
|
||||||
|
$this->assertEquals(sizeof($result), 3);
|
||||||
|
$this->assertArrayHasKey('foo@foo.com', $result);
|
||||||
|
$this->assertArrayHasKey('bar@bar.com', $result);
|
||||||
|
$this->assertArrayHasKey('foobar@foobar.com', $result);
|
||||||
|
$this->assertEquals('SELECT u FROM ' . __NAMESPACE__ . '\DDC1135User u INDEX BY u.email', $dql);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIndexWithJoin()
|
||||||
|
{
|
||||||
|
$builder = $this->_em->createQueryBuilder();
|
||||||
|
$builder->select('u','p')
|
||||||
|
->from(__NAMESPACE__ . '\DDC1135User', 'u', 'u.email')
|
||||||
|
->join('u.phones', 'p', null, null, 'p.id');
|
||||||
|
|
||||||
|
$dql = $builder->getQuery()->getDQL();
|
||||||
|
$result = $builder->getQuery()->getResult();
|
||||||
|
|
||||||
|
$this->assertEquals(sizeof($result), 3);
|
||||||
|
$this->assertArrayHasKey('foo@foo.com', $result);
|
||||||
|
$this->assertArrayHasKey('bar@bar.com', $result);
|
||||||
|
$this->assertArrayHasKey('foobar@foobar.com', $result);
|
||||||
|
|
||||||
|
$this->assertEquals(sizeof($result['foo@foo.com']->phones), 3);
|
||||||
|
$this->assertEquals(sizeof($result['bar@bar.com']->phones), 3);
|
||||||
|
$this->assertEquals(sizeof($result['foobar@foobar.com']->phones), 3);
|
||||||
|
|
||||||
|
$this->assertArrayHasKey(1, $result['foo@foo.com']->phones->toArray());
|
||||||
|
$this->assertArrayHasKey(2, $result['foo@foo.com']->phones->toArray());
|
||||||
|
$this->assertArrayHasKey(3, $result['foo@foo.com']->phones->toArray());
|
||||||
|
|
||||||
|
$this->assertArrayHasKey(4, $result['bar@bar.com']->phones->toArray());
|
||||||
|
$this->assertArrayHasKey(5, $result['bar@bar.com']->phones->toArray());
|
||||||
|
$this->assertArrayHasKey(6, $result['bar@bar.com']->phones->toArray());
|
||||||
|
|
||||||
|
$this->assertArrayHasKey(7, $result['foobar@foobar.com']->phones->toArray());
|
||||||
|
$this->assertArrayHasKey(8, $result['foobar@foobar.com']->phones->toArray());
|
||||||
|
$this->assertArrayHasKey(9, $result['foobar@foobar.com']->phones->toArray());
|
||||||
|
|
||||||
|
$this->assertEquals('SELECT u, p FROM '.__NAMESPACE__ . '\DDC1135User u INDEX BY u.email INNER JOIN u.phones p INDEX BY p.id', $dql);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function loadFixture()
|
||||||
|
{
|
||||||
|
$p1 = array('11 xxxx-xxxx','11 yyyy-yyyy','11 zzzz-zzzz');
|
||||||
|
$p2 = array('22 xxxx-xxxx','22 yyyy-yyyy','22 zzzz-zzzz');
|
||||||
|
$p3 = array('33 xxxx-xxxx','33 yyyy-yyyy','33 zzzz-zzzz');
|
||||||
|
|
||||||
|
$u1 = new DDC1135User("foo@foo.com", "Foo",$p1);
|
||||||
|
$u2 = new DDC1135User("bar@bar.com", "Bar",$p2);
|
||||||
|
$u3 = new DDC1135User("foobar@foobar.com", "Foo Bar",$p3);
|
||||||
|
|
||||||
|
$this->_em->persist($u1);
|
||||||
|
$this->_em->persist($u2);
|
||||||
|
$this->_em->persist($u3);
|
||||||
|
$this->_em->flush();
|
||||||
|
$this->_em->clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Entity
|
||||||
|
*/
|
||||||
|
class DDC1135User
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @Id @Column(type="integer")
|
||||||
|
* @GeneratedValue
|
||||||
|
*/
|
||||||
|
public $id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Column(type="string", unique=true)
|
||||||
|
*/
|
||||||
|
public $email;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Column(type="string")
|
||||||
|
*/
|
||||||
|
public $name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @OneToMany(targetEntity="DDC1135Phone", mappedBy="user", cascade={"persist", "remove"})
|
||||||
|
*/
|
||||||
|
public $phones;
|
||||||
|
|
||||||
|
public function __construct($email, $name, array $numbers = array())
|
||||||
|
{
|
||||||
|
$this->name = $name;
|
||||||
|
$this->email = $email;
|
||||||
|
$this->phones = new \Doctrine\Common\Collections\ArrayCollection();
|
||||||
|
|
||||||
|
foreach ($numbers as $number) {
|
||||||
|
$this->phones->add(new DDC1135Phone($this,$number));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Entity
|
||||||
|
*/
|
||||||
|
class DDC1135Phone
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @Id
|
||||||
|
* @Column(name="id", type="integer")
|
||||||
|
* @GeneratedValue(strategy="AUTO")
|
||||||
|
*/
|
||||||
|
public $id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Column(name="number", type="string", nullable = false)
|
||||||
|
*/
|
||||||
|
public $number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ManyToOne(targetEntity="DDC1135User", inversedBy="phones")
|
||||||
|
* @JoinColumn(name="user_id", referencedColumnName="id", nullable = false)
|
||||||
|
*/
|
||||||
|
public $user;
|
||||||
|
|
||||||
|
public function __construct($user, $number)
|
||||||
|
{
|
||||||
|
$this->user = $user;
|
||||||
|
$this->number = $number;
|
||||||
|
}
|
||||||
|
}
|
127
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1392Test.php
Normal file
127
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1392Test.php
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||||
|
use Doctrine\ORM\UnitOfWork;
|
||||||
|
|
||||||
|
require_once __DIR__ . '/../../../TestInit.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group DDC-1392
|
||||||
|
*/
|
||||||
|
class DDC1392Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||||
|
{
|
||||||
|
protected function setUp()
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->_schemaTool->createSchema(array(
|
||||||
|
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1392File'),
|
||||||
|
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1392Picture'),
|
||||||
|
));
|
||||||
|
} catch (\Exception $ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFailingCase()
|
||||||
|
{
|
||||||
|
$file = new DDC1392File;
|
||||||
|
|
||||||
|
$picture = new DDC1392Picture;
|
||||||
|
$picture->setFile($file);
|
||||||
|
|
||||||
|
$em = $this->_em;
|
||||||
|
$em->persist($picture);
|
||||||
|
$em->flush();
|
||||||
|
$em->clear();
|
||||||
|
|
||||||
|
$fileId = $file->getFileId();
|
||||||
|
$pictureId = $picture->getPictureId();
|
||||||
|
|
||||||
|
$this->assertTrue($fileId > 0);
|
||||||
|
|
||||||
|
$picture = $em->find(__NAMESPACE__ . '\DDC1392Picture', $pictureId);
|
||||||
|
$this->assertEquals(UnitOfWork::STATE_MANAGED, $em->getUnitOfWork()->getEntityState($picture->getFile()), "Lazy Proxy should be marked MANAGED.");
|
||||||
|
|
||||||
|
$file = $picture->getFile();
|
||||||
|
|
||||||
|
// With this activated there will be no problem
|
||||||
|
//$file->__load();
|
||||||
|
|
||||||
|
$picture->setFile(null);
|
||||||
|
|
||||||
|
$em->clear();
|
||||||
|
|
||||||
|
$em->merge($file);
|
||||||
|
|
||||||
|
$em->flush();
|
||||||
|
|
||||||
|
$q = $this->_em->createQuery("SELECT COUNT(e) FROM " . __NAMESPACE__ . '\DDC1392File e');
|
||||||
|
$result = $q->getSingleScalarResult();
|
||||||
|
|
||||||
|
self::assertEquals(1, $result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Entity
|
||||||
|
*/
|
||||||
|
class DDC1392Picture
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @Column(name="picture_id", type="integer")
|
||||||
|
* @Id @GeneratedValue
|
||||||
|
*/
|
||||||
|
private $pictureId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ManyToOne(targetEntity="DDC1392File", cascade={"persist", "remove"})
|
||||||
|
* @JoinColumn(name="file_id", referencedColumnName="file_id")
|
||||||
|
*/
|
||||||
|
private $file;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get pictureId
|
||||||
|
*/
|
||||||
|
public function getPictureId()
|
||||||
|
{
|
||||||
|
return $this->pictureId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set file
|
||||||
|
*/
|
||||||
|
public function setFile($value = null)
|
||||||
|
{
|
||||||
|
$this->file = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get file
|
||||||
|
*/
|
||||||
|
public function getFile()
|
||||||
|
{
|
||||||
|
return $this->file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Entity
|
||||||
|
*/
|
||||||
|
class DDC1392File
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @Column(name="file_id", type="integer")
|
||||||
|
* @Id
|
||||||
|
* @GeneratedValue(strategy="AUTO")
|
||||||
|
*/
|
||||||
|
public $fileId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get fileId
|
||||||
|
*/
|
||||||
|
public function getFileId()
|
||||||
|
{
|
||||||
|
return $this->fileId;
|
||||||
|
}
|
||||||
|
}
|
@ -92,12 +92,12 @@ abstract class DDC258Super
|
|||||||
class DDC258Class1 extends DDC258Super
|
class DDC258Class1 extends DDC258Super
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @Column(name="title", type="string", length="150")
|
* @Column(name="title", type="string", length=150)
|
||||||
*/
|
*/
|
||||||
public $title;
|
public $title;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Column(name="content", type="string", length="500")
|
* @Column(name="content", type="string", length=500)
|
||||||
*/
|
*/
|
||||||
public $description;
|
public $description;
|
||||||
}
|
}
|
||||||
@ -108,12 +108,12 @@ class DDC258Class1 extends DDC258Super
|
|||||||
class DDC258Class2 extends DDC258Super
|
class DDC258Class2 extends DDC258Super
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @Column(name="title", type="string", length="150")
|
* @Column(name="title", type="string", length=150)
|
||||||
*/
|
*/
|
||||||
public $title;
|
public $title;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Column(name="content", type="string", length="500")
|
* @Column(name="content", type="string", length=500)
|
||||||
*/
|
*/
|
||||||
public $description;
|
public $description;
|
||||||
|
|
||||||
@ -131,12 +131,12 @@ class DDC258Class2 extends DDC258Super
|
|||||||
class DDC258Class3 extends DDC258Super
|
class DDC258Class3 extends DDC258Super
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @Column(name="title", type="string", length="150")
|
* @Column(name="title", type="string", length=150)
|
||||||
*/
|
*/
|
||||||
public $apples;
|
public $apples;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Column(name="content", type="string", length="500")
|
* @Column(name="content", type="string", length=500)
|
||||||
*/
|
*/
|
||||||
public $bananas;
|
public $bananas;
|
||||||
}
|
}
|
@ -111,7 +111,7 @@ class DDC522Cart {
|
|||||||
class DDC522ForeignKeyTest {
|
class DDC522ForeignKeyTest {
|
||||||
/** @Id @Column(type="integer") @GeneratedValue */
|
/** @Id @Column(type="integer") @GeneratedValue */
|
||||||
public $id;
|
public $id;
|
||||||
/** @Column(type="integer", name="cart_id", nullable="true") */
|
/** @Column(type="integer", name="cart_id", nullable=true) */
|
||||||
public $cartId;
|
public $cartId;
|
||||||
/**
|
/**
|
||||||
* @OneToOne(targetEntity="DDC522Cart")
|
* @OneToOne(targetEntity="DDC522Cart")
|
||||||
|
@ -49,14 +49,14 @@ class DDC698Role
|
|||||||
protected $roleID;
|
protected $roleID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Column(name="name", type="string", length="45")
|
* @Column(name="name", type="string", length=45)
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
protected $name;
|
protected $name;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Column(name="shortName", type="string", length="45")
|
* @Column(name="shortName", type="string", length=45)
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@ -91,7 +91,7 @@ class DDC698Privilege
|
|||||||
protected $privilegeID;
|
protected $privilegeID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Column(name="name", type="string", length="45")
|
* @Column(name="name", type="string", length=45)
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -111,12 +111,12 @@ abstract class DDC837Super
|
|||||||
class DDC837Class1 extends DDC837Super
|
class DDC837Class1 extends DDC837Super
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @Column(name="title", type="string", length="150")
|
* @Column(name="title", type="string", length=150)
|
||||||
*/
|
*/
|
||||||
public $title;
|
public $title;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Column(name="content", type="string", length="500")
|
* @Column(name="content", type="string", length=500)
|
||||||
*/
|
*/
|
||||||
public $description;
|
public $description;
|
||||||
|
|
||||||
@ -132,12 +132,12 @@ class DDC837Class1 extends DDC837Super
|
|||||||
class DDC837Class2 extends DDC837Super
|
class DDC837Class2 extends DDC837Super
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @Column(name="title", type="string", length="150")
|
* @Column(name="title", type="string", length=150)
|
||||||
*/
|
*/
|
||||||
public $title;
|
public $title;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Column(name="content", type="string", length="500")
|
* @Column(name="content", type="string", length=500)
|
||||||
*/
|
*/
|
||||||
public $description;
|
public $description;
|
||||||
|
|
||||||
@ -160,12 +160,12 @@ class DDC837Class2 extends DDC837Super
|
|||||||
class DDC837Class3 extends DDC837Super
|
class DDC837Class3 extends DDC837Super
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @Column(name="title", type="string", length="150")
|
* @Column(name="title", type="string", length=150)
|
||||||
*/
|
*/
|
||||||
public $apples;
|
public $apples;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Column(name="content", type="string", length="500")
|
* @Column(name="content", type="string", length=500)
|
||||||
*/
|
*/
|
||||||
public $bananas;
|
public $bananas;
|
||||||
}
|
}
|
||||||
|
@ -124,7 +124,7 @@ class DDC992Role
|
|||||||
*/
|
*/
|
||||||
public $roleID;
|
public $roleID;
|
||||||
/**
|
/**
|
||||||
* @Column (name="name", type="string", length="45")
|
* @Column (name="name", type="string", length=45)
|
||||||
*/
|
*/
|
||||||
public $name;
|
public $name;
|
||||||
/**
|
/**
|
||||||
|
@ -182,7 +182,7 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase
|
|||||||
$this->assertTrue(isset($class->associationMappings['phonenumbers']));
|
$this->assertTrue(isset($class->associationMappings['phonenumbers']));
|
||||||
$this->assertFalse($class->associationMappings['phonenumbers']['isOwningSide']);
|
$this->assertFalse($class->associationMappings['phonenumbers']['isOwningSide']);
|
||||||
$this->assertTrue($class->associationMappings['phonenumbers']['isCascadePersist']);
|
$this->assertTrue($class->associationMappings['phonenumbers']['isCascadePersist']);
|
||||||
$this->assertFalse($class->associationMappings['phonenumbers']['isCascadeRemove']);
|
$this->assertTrue($class->associationMappings['phonenumbers']['isCascadeRemove']);
|
||||||
$this->assertFalse($class->associationMappings['phonenumbers']['isCascadeRefresh']);
|
$this->assertFalse($class->associationMappings['phonenumbers']['isCascadeRefresh']);
|
||||||
$this->assertFalse($class->associationMappings['phonenumbers']['isCascadeDetach']);
|
$this->assertFalse($class->associationMappings['phonenumbers']['isCascadeDetach']);
|
||||||
$this->assertFalse($class->associationMappings['phonenumbers']['isCascadeMerge']);
|
$this->assertFalse($class->associationMappings['phonenumbers']['isCascadeMerge']);
|
||||||
@ -291,6 +291,42 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase
|
|||||||
$class->discriminatorColumn
|
$class->discriminatorColumn
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group DDC-869
|
||||||
|
*/
|
||||||
|
public function testMappedSuperclassWithRepository()
|
||||||
|
{
|
||||||
|
$driver = $this->_loadDriver();
|
||||||
|
$em = $this->_getTestEntityManager();
|
||||||
|
$factory = new \Doctrine\ORM\Mapping\ClassMetadataFactory();
|
||||||
|
|
||||||
|
$em->getConfiguration()->setMetadataDriverImpl($driver);
|
||||||
|
$factory->setEntityManager($em);
|
||||||
|
|
||||||
|
|
||||||
|
$class = $factory->getMetadataFor('Doctrine\Tests\Models\DDC869\DDC869CreditCardPayment');
|
||||||
|
|
||||||
|
$this->assertTrue(isset($class->fieldMappings['id']));
|
||||||
|
$this->assertTrue(isset($class->fieldMappings['value']));
|
||||||
|
$this->assertTrue(isset($class->fieldMappings['creditCardNumber']));
|
||||||
|
$this->assertEquals($class->customRepositoryClassName, "Doctrine\Tests\Models\DDC869\DDC869PaymentRepository");
|
||||||
|
$this->assertInstanceOf("Doctrine\Tests\Models\DDC869\DDC869PaymentRepository",
|
||||||
|
$em->getRepository("Doctrine\Tests\Models\DDC869\DDC869CreditCardPayment"));
|
||||||
|
$this->assertTrue($em->getRepository("Doctrine\Tests\Models\DDC869\DDC869ChequePayment")->isTrue());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$class = $factory->getMetadataFor('Doctrine\Tests\Models\DDC869\DDC869ChequePayment');
|
||||||
|
|
||||||
|
$this->assertTrue(isset($class->fieldMappings['id']));
|
||||||
|
$this->assertTrue(isset($class->fieldMappings['value']));
|
||||||
|
$this->assertTrue(isset($class->fieldMappings['serialNumber']));
|
||||||
|
$this->assertEquals($class->customRepositoryClassName, "Doctrine\Tests\Models\DDC869\DDC869PaymentRepository");
|
||||||
|
$this->assertInstanceOf("Doctrine\Tests\Models\DDC869\DDC869PaymentRepository",
|
||||||
|
$em->getRepository("Doctrine\Tests\Models\DDC869\DDC869ChequePayment"));
|
||||||
|
$this->assertTrue($em->getRepository("Doctrine\Tests\Models\DDC869\DDC869ChequePayment")->isTrue());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -52,6 +52,35 @@ class BasicInheritanceMappingTest extends \Doctrine\Tests\OrmTestCase
|
|||||||
|
|
||||||
$this->assertTrue(isset($class->associationMappings['mappedRelated1']));
|
$this->assertTrue(isset($class->associationMappings['mappedRelated1']));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group DDC-869
|
||||||
|
*/
|
||||||
|
public function testGetMetadataForSubclassWithMappedSuperclassWhithRepository()
|
||||||
|
{
|
||||||
|
$class = $this->_factory->getMetadataFor('Doctrine\Tests\Models\DDC869\DDC869CreditCardPayment');
|
||||||
|
|
||||||
|
$this->assertTrue(isset($class->fieldMappings['id']));
|
||||||
|
$this->assertTrue(isset($class->fieldMappings['value']));
|
||||||
|
$this->assertTrue(isset($class->fieldMappings['creditCardNumber']));
|
||||||
|
$this->assertEquals($class->customRepositoryClassName, "Doctrine\Tests\Models\DDC869\DDC869PaymentRepository");
|
||||||
|
|
||||||
|
|
||||||
|
$class = $this->_factory->getMetadataFor('Doctrine\Tests\Models\DDC869\DDC869ChequePayment');
|
||||||
|
|
||||||
|
$this->assertTrue(isset($class->fieldMappings['id']));
|
||||||
|
$this->assertTrue(isset($class->fieldMappings['value']));
|
||||||
|
$this->assertTrue(isset($class->fieldMappings['serialNumber']));
|
||||||
|
$this->assertEquals($class->customRepositoryClassName, "Doctrine\Tests\Models\DDC869\DDC869PaymentRepository");
|
||||||
|
|
||||||
|
|
||||||
|
// override repositoryClass
|
||||||
|
$class = $this->_factory->getMetadataFor('Doctrine\Tests\ORM\Mapping\SubclassWithRepository');
|
||||||
|
|
||||||
|
$this->assertTrue(isset($class->fieldMappings['id']));
|
||||||
|
$this->assertTrue(isset($class->fieldMappings['value']));
|
||||||
|
$this->assertEquals($class->customRepositoryClassName, "Doctrine\ORM\EntityRepository");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @group DDC-388
|
* @group DDC-388
|
||||||
@ -191,7 +220,7 @@ abstract class HierachyBase
|
|||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @Column(type="integer") @Id @GeneratedValue(strategy="SEQUENCE")
|
* @Column(type="integer") @Id @GeneratedValue(strategy="SEQUENCE")
|
||||||
* @SequenceGenerator(sequenceName="foo", initialValue="10")
|
* @SequenceGenerator(sequenceName="foo", initialValue=10)
|
||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
public $id;
|
public $id;
|
||||||
@ -257,7 +286,7 @@ abstract class SuperclassBase
|
|||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @Column(type="integer") @Id @GeneratedValue(strategy="SEQUENCE")
|
* @Column(type="integer") @Id @GeneratedValue(strategy="SEQUENCE")
|
||||||
* @SequenceGenerator(sequenceName="foo", initialValue="10")
|
* @SequenceGenerator(sequenceName="foo", initialValue=10)
|
||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
public $id;
|
public $id;
|
||||||
@ -277,4 +306,12 @@ abstract class MediumSuperclassBase extends SuperclassBase
|
|||||||
class MediumSuperclassEntity extends MediumSuperclassBase
|
class MediumSuperclassEntity extends MediumSuperclassBase
|
||||||
{
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Entity(repositoryClass = "Doctrine\ORM\EntityRepository")
|
||||||
|
*/
|
||||||
|
class SubclassWithRepository extends \Doctrine\Tests\Models\DDC869\DDC869Payment
|
||||||
|
{
|
||||||
|
|
||||||
}
|
}
|
426
tests/Doctrine/Tests/ORM/Mapping/ClassMetadataBuilderTest.php
Normal file
426
tests/Doctrine/Tests/ORM/Mapping/ClassMetadataBuilderTest.php
Normal file
@ -0,0 +1,426 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* 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.doctrine-project.org>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
namespace Doctrine\Tests\ORM\Mapping;
|
||||||
|
|
||||||
|
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||||
|
use Doctrine\ORM\Mapping\Builder\ClassMetadataBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group DDC-659
|
||||||
|
*/
|
||||||
|
class ClassMetadataBuilderTest extends \Doctrine\Tests\OrmTestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var ClassMetadata
|
||||||
|
*/
|
||||||
|
private $cm;
|
||||||
|
/**
|
||||||
|
* @var ClassMetadataBuilder
|
||||||
|
*/
|
||||||
|
private $builder;
|
||||||
|
|
||||||
|
public function setUp()
|
||||||
|
{
|
||||||
|
$this->cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser');
|
||||||
|
$this->builder = new ClassMetadataBuilder($this->cm);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSetMappedSuperClass()
|
||||||
|
{
|
||||||
|
$this->assertIsFluent($this->builder->setMappedSuperClass());
|
||||||
|
$this->assertTrue($this->cm->isMappedSuperclass);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSetCustomRepositoryClass()
|
||||||
|
{
|
||||||
|
$this->assertIsFluent($this->builder->setCustomRepositoryClass('Doctrine\Tests\Models\CMS\CmsGroup'));
|
||||||
|
$this->assertEquals('Doctrine\Tests\Models\CMS\CmsGroup', $this->cm->customRepositoryClassName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSetReadOnly()
|
||||||
|
{
|
||||||
|
$this->assertIsFluent($this->builder->setReadOnly());
|
||||||
|
$this->assertTrue($this->cm->isReadOnly);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSetTable()
|
||||||
|
{
|
||||||
|
$this->assertIsFluent($this->builder->setTable('users'));
|
||||||
|
$this->assertEquals('users', $this->cm->table['name']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAddIndex()
|
||||||
|
{
|
||||||
|
$this->assertIsFluent($this->builder->addIndex(array('username', 'name'), 'users_idx'));
|
||||||
|
$this->assertEquals(array('users_idx' => array('columns' => array('username', 'name'))), $this->cm->table['indexes']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAddUniqueConstraint()
|
||||||
|
{
|
||||||
|
$this->assertIsFluent($this->builder->addUniqueConstraint(array('username', 'name'), 'users_idx'));
|
||||||
|
$this->assertEquals(array('users_idx' => array('columns' => array('username', 'name'))), $this->cm->table['uniqueConstraints']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSetPrimaryTableRelated()
|
||||||
|
{
|
||||||
|
$this->builder->addUniqueConstraint(array('username', 'name'), 'users_idx');
|
||||||
|
$this->builder->addIndex(array('username', 'name'), 'users_idx');
|
||||||
|
$this->builder->setTable('users');
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
array(
|
||||||
|
'name' => 'users',
|
||||||
|
'indexes' => array('users_idx' => array('columns' => array('username', 'name'))),
|
||||||
|
'uniqueConstraints' => array('users_idx' => array('columns' => array('username', 'name'))),
|
||||||
|
),
|
||||||
|
$this->cm->table
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSetInheritanceJoined()
|
||||||
|
{
|
||||||
|
$this->assertIsFluent($this->builder->setJoinedTableInheritance());
|
||||||
|
$this->assertEquals(ClassMetadata::INHERITANCE_TYPE_JOINED, $this->cm->inheritanceType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSetInheritanceSingleTable()
|
||||||
|
{
|
||||||
|
$this->assertIsFluent($this->builder->setSingleTableInheritance());
|
||||||
|
$this->assertEquals(ClassMetadata::INHERITANCE_TYPE_SINGLE_TABLE, $this->cm->inheritanceType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSetDiscriminatorColumn()
|
||||||
|
{
|
||||||
|
$this->assertIsFluent($this->builder->setDiscriminatorColumn('discr', 'string', '124'));
|
||||||
|
$this->assertEquals(array('fieldName' => 'discr', 'name' => 'discr', 'type' => 'string', 'length' => '124'), $this->cm->discriminatorColumn);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAddDiscriminatorMapClass()
|
||||||
|
{
|
||||||
|
$this->assertIsFluent($this->builder->addDiscriminatorMapClass('test', 'Doctrine\Tests\Models\CMS\CmsUser'));
|
||||||
|
$this->assertIsFluent($this->builder->addDiscriminatorMapClass('test2', 'Doctrine\Tests\Models\CMS\CmsGroup'));
|
||||||
|
|
||||||
|
$this->assertEquals(array('test' => 'Doctrine\Tests\Models\CMS\CmsUser', 'test2' => 'Doctrine\Tests\Models\CMS\CmsGroup'), $this->cm->discriminatorMap);
|
||||||
|
$this->assertEquals('test', $this->cm->discriminatorValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testChangeTrackingPolicyExplicit()
|
||||||
|
{
|
||||||
|
$this->assertIsFluent($this->builder->setChangeTrackingPolicyDeferredExplicit());
|
||||||
|
$this->assertEquals(ClassMetadata::CHANGETRACKING_DEFERRED_EXPLICIT, $this->cm->changeTrackingPolicy);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testChangeTrackingPolicyNotify()
|
||||||
|
{
|
||||||
|
$this->assertIsFluent($this->builder->setChangeTrackingPolicyNotify());
|
||||||
|
$this->assertEquals(ClassMetadata::CHANGETRACKING_NOTIFY, $this->cm->changeTrackingPolicy);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAddField()
|
||||||
|
{
|
||||||
|
$this->assertIsFluent($this->builder->addField('name', 'string'));
|
||||||
|
$this->assertEquals(array('columnName' => 'name', 'fieldName' => 'name', 'type' => 'string'), $this->cm->fieldMappings['name']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCreateField()
|
||||||
|
{
|
||||||
|
$fieldBuilder = ($this->builder->createField('name', 'string'));
|
||||||
|
$this->assertInstanceOf('Doctrine\ORM\Mapping\Builder\FieldBuilder', $fieldBuilder);
|
||||||
|
|
||||||
|
$this->assertFalse(isset($this->cm->fieldMappings['name']));
|
||||||
|
$this->assertIsFluent($fieldBuilder->build());
|
||||||
|
$this->assertEquals(array('columnName' => 'name', 'fieldName' => 'name', 'type' => 'string'), $this->cm->fieldMappings['name']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCreateVersionedField()
|
||||||
|
{
|
||||||
|
$this->builder->createField('name', 'integer')->columnName('username')->length(124)->nullable()->columnDefinition('foobar')->unique()->isVersionField()->build();
|
||||||
|
$this->assertEquals(array(
|
||||||
|
'columnDefinition' => 'foobar',
|
||||||
|
'columnName' => 'username',
|
||||||
|
'default' => 1,
|
||||||
|
'fieldName' => 'name',
|
||||||
|
'length' => 124,
|
||||||
|
'type' => 'integer',
|
||||||
|
'nullable' => true,
|
||||||
|
'unique' => true,
|
||||||
|
), $this->cm->fieldMappings['name']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCreatePrimaryField()
|
||||||
|
{
|
||||||
|
$this->builder->createField('id', 'integer')->isPrimaryKey()->generatedValue()->build();
|
||||||
|
|
||||||
|
$this->assertEquals(array('id'), $this->cm->identifier);
|
||||||
|
$this->assertEquals(array('columnName' => 'id', 'fieldName' => 'id', 'id' => true, 'type' => 'integer'), $this->cm->fieldMappings['id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAddLifecycleEvent()
|
||||||
|
{
|
||||||
|
$this->builder->addLifecycleEvent('getStatus', 'postLoad');
|
||||||
|
|
||||||
|
$this->assertEquals(array('postLoad' => array('getStatus')), $this->cm->lifecycleCallbacks);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCreateManyToOne()
|
||||||
|
{
|
||||||
|
$this->assertIsFluent(
|
||||||
|
$this->builder->createManyToOne('groups', 'Doctrine\Tests\Models\CMS\CmsGroup')
|
||||||
|
->addJoinColumn('group_id', 'id', true, false, 'CASCADE')
|
||||||
|
->cascadeAll()
|
||||||
|
->fetchExtraLazy()
|
||||||
|
->build()
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(array('groups' => array (
|
||||||
|
'fieldName' => 'groups',
|
||||||
|
'targetEntity' => 'Doctrine\\Tests\\Models\\CMS\\CmsGroup',
|
||||||
|
'cascade' => array (
|
||||||
|
0 => 'remove',
|
||||||
|
1 => 'persist',
|
||||||
|
2 => 'refresh',
|
||||||
|
3 => 'merge',
|
||||||
|
4 => 'detach',
|
||||||
|
),
|
||||||
|
'fetch' => 4,
|
||||||
|
'joinColumns' => array (
|
||||||
|
0 =>
|
||||||
|
array (
|
||||||
|
'name' => 'group_id',
|
||||||
|
'referencedColumnName' => 'id',
|
||||||
|
'nullable' => true,
|
||||||
|
'unique' => false,
|
||||||
|
'onDelete' => 'CASCADE',
|
||||||
|
'columnDefinition' => NULL,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'type' => 2,
|
||||||
|
'mappedBy' => NULL,
|
||||||
|
'inversedBy' => NULL,
|
||||||
|
'isOwningSide' => true,
|
||||||
|
'sourceEntity' => 'Doctrine\\Tests\\Models\\CMS\\CmsUser',
|
||||||
|
'isCascadeRemove' => true,
|
||||||
|
'isCascadePersist' => true,
|
||||||
|
'isCascadeRefresh' => true,
|
||||||
|
'isCascadeMerge' => true,
|
||||||
|
'isCascadeDetach' => true,
|
||||||
|
'sourceToTargetKeyColumns' =>
|
||||||
|
array (
|
||||||
|
'group_id' => 'id',
|
||||||
|
),
|
||||||
|
'joinColumnFieldNames' =>
|
||||||
|
array (
|
||||||
|
'group_id' => 'group_id',
|
||||||
|
),
|
||||||
|
'targetToSourceKeyColumns' =>
|
||||||
|
array (
|
||||||
|
'id' => 'group_id',
|
||||||
|
),
|
||||||
|
'orphanRemoval' => false,
|
||||||
|
),
|
||||||
|
), $this->cm->associationMappings);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCreateOneToOne()
|
||||||
|
{
|
||||||
|
$this->assertIsFluent(
|
||||||
|
$this->builder->createOneToOne('groups', 'Doctrine\Tests\Models\CMS\CmsGroup')
|
||||||
|
->addJoinColumn('group_id', 'id', true, false, 'CASCADE')
|
||||||
|
->cascadeAll()
|
||||||
|
->fetchExtraLazy()
|
||||||
|
->build()
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(array('groups' => array (
|
||||||
|
'fieldName' => 'groups',
|
||||||
|
'targetEntity' => 'Doctrine\\Tests\\Models\\CMS\\CmsGroup',
|
||||||
|
'cascade' => array (
|
||||||
|
0 => 'remove',
|
||||||
|
1 => 'persist',
|
||||||
|
2 => 'refresh',
|
||||||
|
3 => 'merge',
|
||||||
|
4 => 'detach',
|
||||||
|
),
|
||||||
|
'fetch' => 4,
|
||||||
|
'joinColumns' => array (
|
||||||
|
0 =>
|
||||||
|
array (
|
||||||
|
'name' => 'group_id',
|
||||||
|
'referencedColumnName' => 'id',
|
||||||
|
'nullable' => true,
|
||||||
|
'unique' => true,
|
||||||
|
'onDelete' => 'CASCADE',
|
||||||
|
'columnDefinition' => NULL,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'type' => 1,
|
||||||
|
'mappedBy' => NULL,
|
||||||
|
'inversedBy' => NULL,
|
||||||
|
'isOwningSide' => true,
|
||||||
|
'sourceEntity' => 'Doctrine\\Tests\\Models\\CMS\\CmsUser',
|
||||||
|
'isCascadeRemove' => true,
|
||||||
|
'isCascadePersist' => true,
|
||||||
|
'isCascadeRefresh' => true,
|
||||||
|
'isCascadeMerge' => true,
|
||||||
|
'isCascadeDetach' => true,
|
||||||
|
'sourceToTargetKeyColumns' =>
|
||||||
|
array (
|
||||||
|
'group_id' => 'id',
|
||||||
|
),
|
||||||
|
'joinColumnFieldNames' =>
|
||||||
|
array (
|
||||||
|
'group_id' => 'group_id',
|
||||||
|
),
|
||||||
|
'targetToSourceKeyColumns' =>
|
||||||
|
array (
|
||||||
|
'id' => 'group_id',
|
||||||
|
),
|
||||||
|
'orphanRemoval' => false,
|
||||||
|
),
|
||||||
|
), $this->cm->associationMappings);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCreateManyToMany()
|
||||||
|
{
|
||||||
|
$this->assertIsFluent(
|
||||||
|
$this->builder->createManyToMany('groups', 'Doctrine\Tests\Models\CMS\CmsGroup')
|
||||||
|
->setJoinTable('groups_users')
|
||||||
|
->addJoinColumn('group_id', 'id', true, false, 'CASCADE')
|
||||||
|
->addInverseJoinColumn('user_id', 'id')
|
||||||
|
->cascadeAll()
|
||||||
|
->fetchExtraLazy()
|
||||||
|
->build()
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(array(
|
||||||
|
'groups' =>
|
||||||
|
array(
|
||||||
|
'fieldName' => 'groups',
|
||||||
|
'targetEntity' => 'Doctrine\\Tests\\Models\\CMS\\CmsGroup',
|
||||||
|
'cascade' =>
|
||||||
|
array(
|
||||||
|
0 => 'remove',
|
||||||
|
1 => 'persist',
|
||||||
|
2 => 'refresh',
|
||||||
|
3 => 'merge',
|
||||||
|
4 => 'detach',
|
||||||
|
),
|
||||||
|
'fetch' => 4,
|
||||||
|
'joinTable' =>
|
||||||
|
array(
|
||||||
|
'joinColumns' =>
|
||||||
|
array(
|
||||||
|
0 =>
|
||||||
|
array(
|
||||||
|
'name' => 'group_id',
|
||||||
|
'referencedColumnName' => 'id',
|
||||||
|
'nullable' => true,
|
||||||
|
'unique' => false,
|
||||||
|
'onDelete' => 'CASCADE',
|
||||||
|
'columnDefinition' => NULL,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'inverseJoinColumns' =>
|
||||||
|
array(
|
||||||
|
0 =>
|
||||||
|
array(
|
||||||
|
'name' => 'user_id',
|
||||||
|
'referencedColumnName' => 'id',
|
||||||
|
'nullable' => true,
|
||||||
|
'unique' => false,
|
||||||
|
'onDelete' => NULL,
|
||||||
|
'columnDefinition' => NULL,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'name' => 'groups_users',
|
||||||
|
),
|
||||||
|
'type' => 8,
|
||||||
|
'mappedBy' => NULL,
|
||||||
|
'inversedBy' => NULL,
|
||||||
|
'isOwningSide' => true,
|
||||||
|
'sourceEntity' => 'Doctrine\\Tests\\Models\\CMS\\CmsUser',
|
||||||
|
'isCascadeRemove' => true,
|
||||||
|
'isCascadePersist' => true,
|
||||||
|
'isCascadeRefresh' => true,
|
||||||
|
'isCascadeMerge' => true,
|
||||||
|
'isCascadeDetach' => true,
|
||||||
|
'isOnDeleteCascade' => true,
|
||||||
|
'relationToSourceKeyColumns' =>
|
||||||
|
array(
|
||||||
|
'group_id' => 'id',
|
||||||
|
),
|
||||||
|
'joinTableColumns' =>
|
||||||
|
array(
|
||||||
|
0 => 'group_id',
|
||||||
|
1 => 'user_id',
|
||||||
|
),
|
||||||
|
'relationToTargetKeyColumns' =>
|
||||||
|
array(
|
||||||
|
'user_id' => 'id',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
), $this->cm->associationMappings);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCreateOneToMany()
|
||||||
|
{
|
||||||
|
$this->assertIsFluent(
|
||||||
|
$this->builder->createOneToMany('groups', 'Doctrine\Tests\Models\CMS\CmsGroup')
|
||||||
|
->mappedBy('test')
|
||||||
|
->setOrderBy(array('test'))
|
||||||
|
->setIndexBy('test')
|
||||||
|
->build()
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(array(
|
||||||
|
'groups' =>
|
||||||
|
array(
|
||||||
|
'fieldName' => 'groups',
|
||||||
|
'targetEntity' => 'Doctrine\\Tests\\Models\\CMS\\CmsGroup',
|
||||||
|
'mappedBy' => 'test',
|
||||||
|
'orderBy' =>
|
||||||
|
array(
|
||||||
|
0 => 'test',
|
||||||
|
),
|
||||||
|
'indexBy' => 'test',
|
||||||
|
'type' => 4,
|
||||||
|
'inversedBy' => NULL,
|
||||||
|
'isOwningSide' => false,
|
||||||
|
'sourceEntity' => 'Doctrine\\Tests\\Models\\CMS\\CmsUser',
|
||||||
|
'fetch' => 2,
|
||||||
|
'cascade' =>
|
||||||
|
array(
|
||||||
|
),
|
||||||
|
'isCascadeRemove' => false,
|
||||||
|
'isCascadePersist' => false,
|
||||||
|
'isCascadeRefresh' => false,
|
||||||
|
'isCascadeMerge' => false,
|
||||||
|
'isCascadeDetach' => false,
|
||||||
|
'orphanRemoval' => false,
|
||||||
|
),
|
||||||
|
), $this->cm->associationMappings);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function assertIsFluent($ret)
|
||||||
|
{
|
||||||
|
$this->assertSame($this->builder, $ret, "Return Value has to be same instance as used builder");
|
||||||
|
}
|
||||||
|
}
|
@ -45,7 +45,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase
|
|||||||
$this->assertEquals('UserParent', $cm->rootEntityName);
|
$this->assertEquals('UserParent', $cm->rootEntityName);
|
||||||
$this->assertEquals(array('Doctrine\Tests\Models\CMS\One', 'Doctrine\Tests\Models\CMS\Two', 'Doctrine\Tests\Models\CMS\Three'), $cm->subClasses);
|
$this->assertEquals(array('Doctrine\Tests\Models\CMS\One', 'Doctrine\Tests\Models\CMS\Two', 'Doctrine\Tests\Models\CMS\Three'), $cm->subClasses);
|
||||||
$this->assertEquals(array('UserParent'), $cm->parentClasses);
|
$this->assertEquals(array('UserParent'), $cm->parentClasses);
|
||||||
$this->assertEquals('UserRepository', $cm->customRepositoryClassName);
|
$this->assertEquals('Doctrine\Tests\Models\CMS\UserRepository', $cm->customRepositoryClassName);
|
||||||
$this->assertEquals(array('name' => 'disc', 'type' => 'integer', 'fieldName' => 'disc'), $cm->discriminatorColumn);
|
$this->assertEquals(array('name' => 'disc', 'type' => 'integer', 'fieldName' => 'disc'), $cm->discriminatorColumn);
|
||||||
$this->assertTrue($cm->associationMappings['phonenumbers']['type'] == ClassMetadata::ONE_TO_ONE);
|
$this->assertTrue($cm->associationMappings['phonenumbers']['type'] == ClassMetadata::ONE_TO_ONE);
|
||||||
$this->assertEquals(1, count($cm->associationMappings));
|
$this->assertEquals(1, count($cm->associationMappings));
|
||||||
@ -471,4 +471,15 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase
|
|||||||
$cm = new ClassMetadata('DOCTRINE\TESTS\MODELS\CMS\CMSUSER');
|
$cm = new ClassMetadata('DOCTRINE\TESTS\MODELS\CMS\CMSUSER');
|
||||||
$this->assertEquals('Doctrine\Tests\Models\CMS\CmsUser', $cm->name);
|
$this->assertEquals('Doctrine\Tests\Models\CMS\CmsUser', $cm->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group DDC-659
|
||||||
|
*/
|
||||||
|
public function testLifecycleCallbackNotFound()
|
||||||
|
{
|
||||||
|
$cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser');
|
||||||
|
|
||||||
|
$this->setExpectedException("Doctrine\ORM\Mapping\MappingException", "Entity 'Doctrine\Tests\Models\CMS\CmsUser' has no method 'notfound' to be registered as lifecycle callback.");
|
||||||
|
$cm->addLifecycleCallback('notfound', 'postLoad');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
113
tests/Doctrine/Tests/ORM/Mapping/Symfony/AbstractDriverTest.php
Normal file
113
tests/Doctrine/Tests/ORM/Mapping/Symfony/AbstractDriverTest.php
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* 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.doctrine-project.org>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Doctrine\Tests\ORM\Mapping\Symfony;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group DDC-1418
|
||||||
|
*/
|
||||||
|
abstract class AbstractDriverTest extends \PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
public function testFindMappingFile()
|
||||||
|
{
|
||||||
|
$driver = $this->getDriver(array(
|
||||||
|
'MyNamespace\MySubnamespace\EntityFoo' => 'foo',
|
||||||
|
'MyNamespace\MySubnamespace\Entity' => $this->dir,
|
||||||
|
));
|
||||||
|
|
||||||
|
touch($filename = $this->dir.'/Foo'.$this->getFileExtension());
|
||||||
|
$this->assertEquals($filename, $this->invoke($driver, '_findMappingFile', array('MyNamespace\MySubnamespace\Entity\Foo')));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFindMappingFileInSubnamespace()
|
||||||
|
{
|
||||||
|
$driver = $this->getDriver(array(
|
||||||
|
'MyNamespace\MySubnamespace\Entity' => $this->dir,
|
||||||
|
));
|
||||||
|
|
||||||
|
touch($filename = $this->dir.'/Foo.Bar'.$this->getFileExtension());
|
||||||
|
$this->assertEquals($filename, $this->invoke($driver, '_findMappingFile', array('MyNamespace\MySubnamespace\Entity\Foo\Bar')));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFindMappingFileNamespacedFoundFileNotFound()
|
||||||
|
{
|
||||||
|
$this->setExpectedException(
|
||||||
|
'Doctrine\ORM\Mapping\MappingException',
|
||||||
|
"No mapping file found named '".$this->dir."/Foo".$this->getFileExtension()."' for class 'MyNamespace\MySubnamespace\Entity\Foo'."
|
||||||
|
);
|
||||||
|
|
||||||
|
$driver = $this->getDriver(array(
|
||||||
|
'MyNamespace\MySubnamespace\Entity' => $this->dir,
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->invoke($driver, '_findMappingFile', array('MyNamespace\MySubnamespace\Entity\Foo'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFindMappingNamespaceNotFound()
|
||||||
|
{
|
||||||
|
$this->setExpectedException(
|
||||||
|
'Doctrine\ORM\Mapping\MappingException',
|
||||||
|
"No mapping file found named 'Foo".$this->getFileExtension()."' for class 'MyOtherNamespace\MySubnamespace\Entity\Foo'."
|
||||||
|
);
|
||||||
|
|
||||||
|
$driver = $this->getDriver(array(
|
||||||
|
'MyNamespace\MySubnamespace\Entity' => $this->dir,
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->invoke($driver, '_findMappingFile', array('MyOtherNamespace\MySubnamespace\Entity\Foo'));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function setUp()
|
||||||
|
{
|
||||||
|
$this->dir = sys_get_temp_dir().'/abstract_driver_test';
|
||||||
|
@mkdir($this->dir, 0777, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function tearDown()
|
||||||
|
{
|
||||||
|
$iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->dir), \RecursiveIteratorIterator::CHILD_FIRST);
|
||||||
|
|
||||||
|
foreach ($iterator as $path) {
|
||||||
|
if ($path->isDir()) {
|
||||||
|
@rmdir($path);
|
||||||
|
} else {
|
||||||
|
@unlink($path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@rmdir($this->dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract protected function getFileExtension();
|
||||||
|
abstract protected function getDriver(array $paths = array());
|
||||||
|
|
||||||
|
private function setField($obj, $field, $value)
|
||||||
|
{
|
||||||
|
$ref = new \ReflectionProperty($obj, $field);
|
||||||
|
$ref->setAccessible(true);
|
||||||
|
$ref->setValue($obj, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function invoke($obj, $method, array $args = array()) {
|
||||||
|
$ref = new \ReflectionMethod($obj, $method);
|
||||||
|
$ref->setAccessible(true);
|
||||||
|
|
||||||
|
return $ref->invokeArgs($obj, $args);
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user