Commit 0f7d71ca authored by Benjamin Eberlei's avatar Benjamin Eberlei

Merge commit 'dc2master/master'

parents fab5ef84 2f3e9fdc
......@@ -3,9 +3,9 @@
## Console migrated to Symfony Console
The Doctrine Cli has been replaced by Symfony Console Configuration
The Doctrine CLI has been replaced by Symfony Console Configuration
Instead of having to specifiy:
Instead of having to specify:
[php]
$cliConfig = new CliConfiguration();
......@@ -100,9 +100,22 @@ The "default" option for database column defaults has been removed. If desired,
be implemented by using the columnDefinition attribute of the @Column annotation (or the approriate XML and YAML equivalents).
Prefer PHP default values, if possible.
## Partial Objects
## Selecting Partial Objects
[TBD: New syntax, results, etc.]
Querying for partial objects now has a new syntax. The old syntax to query for partial objects
now has a different meaning. This is best illustrated by an example. If you previously
had a DQL query like this:
[sql]
SELECT u.id, u.name FROM User u
Since BETA1, simple state field path expressions in the select clause are used to select
object fields as plain scalar values (something that was not possible before).
To achieve the same result as previously (that is, a partial object with only id and name populated)
you need to use the following, explicit syntax:
[sql]
SELECT PARTIAL u.{id,name} FROM User u
## XML Mapping Driver
......@@ -133,3 +146,9 @@ by using the API on the `PreUpdateEventArgs` instance passed to the preUpdate li
to the state of the entitys properties won't affect the database UPDATE statement anymore. This gives drastic
performance benefits for the preUpdate event.
## Collection API
The Collection interface in the Common package has been updated with some missing methods
that were present only on the default implementation, ArrayCollection. Custom collection
implementations need to be updated to adhere to the updated interface.
......@@ -27,7 +27,8 @@ namespace Doctrine\Common\Annotations;
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision: 3938 $
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
......@@ -52,14 +53,29 @@ class Annotation
$this->$key = $value;
}
}
/**
* Error handler for unknown property accessor in Annotation class.
*
* @param string $name Unknown property name
*/
public function __get($name)
{
throw new \BadMethodCallException("Unknown annotation property '$name' on annotation '".get_class($this)."'.");
throw new \BadMethodCallException(
sprintf("Unknown property '%s' on annotation '%s'.", $name, get_class($this))
);
}
/**
* Error handler for unknown property mutator in Annotation class.
*
* @param string $name Unkown property name
* @param mixed $value Property value
*/
public function __set($name, $value)
{
throw new \BadMethodCallException("Unknown annotation property '$name' on annotation '".get_class($this)."'.");
throw new \BadMethodCallException(
sprintf("Unknown property '%s' on annotation '%s'.", $name, get_class($this))
);
}
}
\ No newline at end of file
......@@ -27,20 +27,32 @@ namespace Doctrine\Common\Annotations;
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision: 3938 $
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
class AnnotationException extends \Doctrine\Common\CommonException
class AnnotationException extends \Exception
{
/**
* Creates a new AnnotationException describing a Syntax error.
*
* @param string $message Exception message
* @return AnnotationException
*/
public static function syntaxError($message)
{
return new self('[Syntax Error] ' . $message);
}
public static function semanticalError($message)
/**
* Creates a new AnnotationException describing a Semantical error.
*
* @param string $message Exception message
* @return AnnotationException
*/
public static function semanticalError($message)
{
return new self('[Semantical Error] ' . $message);
}
......
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
......@@ -29,10 +27,7 @@ use \ReflectionClass,
/**
* A reader for docblock annotations.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision: 3938 $
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
......@@ -46,7 +41,7 @@ class AnnotationReader
* @var string
* @static
*/
private static $CACHE_SALT = "@<Annot>";
private static $CACHE_SALT = '@<Annot>';
/**
* Annotations Parser
......@@ -56,15 +51,14 @@ class AnnotationReader
private $_parser;
/**
* Cache machanism to store processed Annotations
* Cache mechanism to store processed Annotations
*
* @var Doctrine\Common\Cache\Cache
*/
private $_cache;
/**
* Constructor. Initializes a new AnnotationReader that uses the given
* Cache provider.
* Constructor. Initializes a new AnnotationReader that uses the given Cache provider.
*
* @param Cache $cache The cache provider to use. If none is provided, ArrayCache is used.
*/
......@@ -112,7 +106,7 @@ class AnnotationReader
return $data;
}
$annotations = $this->_parser->parse($class->getDocComment(), "class ".$class->getName());
$annotations = $this->_parser->parse($class->getDocComment(), 'class ' . $class->getName());
$this->_cache->save($cacheKey, $annotations, null);
return $annotations;
......@@ -128,6 +122,7 @@ class AnnotationReader
public function getClassAnnotation(ReflectionClass $class, $annotation)
{
$annotations = $this->getClassAnnotations($class);
return isset($annotations[$annotation]) ? $annotations[$annotation] : null;
}
......@@ -148,7 +143,7 @@ class AnnotationReader
return $data;
}
$context = "property ".$property->getDeclaringClass()->getName()."::\$".$property->getName();
$context = 'property ' . $property->getDeclaringClass()->getName() . "::\$" . $property->getName();
$annotations = $this->_parser->parse($property->getDocComment(), $context);
$this->_cache->save($cacheKey, $annotations, null);
......@@ -165,6 +160,7 @@ class AnnotationReader
public function getPropertyAnnotation(ReflectionProperty $property, $annotation)
{
$annotations = $this->getPropertyAnnotations($property);
return isset($annotations[$annotation]) ? $annotations[$annotation] : null;
}
......@@ -185,7 +181,7 @@ class AnnotationReader
return $data;
}
$context = "method ".$method->getDeclaringClass()->getName()."::".$method->getName()."()";
$context = 'method ' . $method->getDeclaringClass()->getName() . '::' . $method->getName() . '()';
$annotations = $this->_parser->parse($method->getDocComment(), $context);
$this->_cache->save($cacheKey, $annotations, null);
......@@ -202,6 +198,7 @@ class AnnotationReader
public function getMethodAnnotation(ReflectionMethod $method, $annotation)
{
$annotations = $this->getMethodAnnotations($method);
return isset($annotations[$annotation]) ? $annotations[$annotation] : null;
}
}
\ No newline at end of file
......@@ -27,7 +27,8 @@ namespace Doctrine\Common\Annotations;
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision: 3938 $
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
......@@ -80,7 +81,7 @@ class Lexer extends \Doctrine\Common\Lexer
$newVal = $this->_getNumeric($value);
// Checking numeric value
if ($newVal !== false){
if ($newVal !== false) {
$value = $newVal;
return (strpos($value, '.') !== false || stripos($value, 'e') !== false)
......@@ -93,16 +94,34 @@ class Lexer extends \Doctrine\Common\Lexer
return self::T_STRING;
} else {
switch (strtolower($value)) {
case '@': return self::T_AT;
case ',': return self::T_COMMA;
case '(': return self::T_OPEN_PARENTHESIS;
case ')': return self::T_CLOSE_PARENTHESIS;
case '{': return self::T_OPEN_CURLY_BRACES;
case '@':
return self::T_AT;
case ',':
return self::T_COMMA;
case '(':
return self::T_OPEN_PARENTHESIS;
case ')':
return self::T_CLOSE_PARENTHESIS;
case '{':
return self::T_OPEN_CURLY_BRACES;
case '}': return self::T_CLOSE_CURLY_BRACES;
case '=': return self::T_EQUALS;
case '\\': return self::T_NAMESPACE_SEPARATOR;
case 'true': return self::T_TRUE;
case 'false': return self::T_FALSE;
case '=':
return self::T_EQUALS;
case '\\':
return self::T_NAMESPACE_SEPARATOR;
case 'true':
return self::T_TRUE;
case 'false':
return self::T_FALSE;
default:
if (ctype_alpha($value[0]) || $value[0] === '_') {
return self::T_IDENTIFIER;
......@@ -126,6 +145,7 @@ class Lexer extends \Doctrine\Common\Lexer
if ( ! is_scalar($value)) {
return false;
}
// Checking for valid numeric numbers: 1.234, -1.234e-2
if (is_numeric($value)) {
return $value;
......
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
......@@ -24,14 +22,11 @@ namespace Doctrine\Common\Annotations;
/**
* A simple parser for docblock annotations.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision: 3938 $
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class Parser
{
......@@ -173,9 +168,10 @@ class Parser
$message .= "'{$token['value']}' at position {$token['position']}";
}
if(strlen($this->_context)) {
$message .= ' in '.$this->_context;
if (strlen($this->_context)) {
$message .= ' in ' . $this->_context;
}
$message .= '.';
throw AnnotationException::syntaxError($message);
......@@ -236,7 +232,7 @@ class Parser
$nameParts[] = $this->_lexer->token['value'];
}
// Effectively pick the name of class (append default NS if none, grab from NS alias, etc)
// Effectively pick the name of the class (append default NS if none, grab from NS alias, etc)
if (count($nameParts) == 1) {
if (strpos($nameParts[0], ':')) {
list ($alias, $simpleName) = explode(':', $nameParts[0]);
......@@ -250,7 +246,7 @@ class Parser
// Is it really an annotation class?
if (
(! $this->_isNestedAnnotation && $this->_lexer->lookahead != null &&
( ! $this->_isNestedAnnotation && $this->_lexer->lookahead != null &&
! $this->_lexer->isNextToken(Lexer::T_OPEN_PARENTHESIS) &&
! $this->_lexer->isNextToken(Lexer::T_AT)) ||
! class_exists($name, false)
......@@ -411,6 +407,7 @@ class Parser
foreach ($values as $value) {
list ($key, $val) = $value;
if ($key !== null) {
$array[$key] = $val;
} else {
......
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
......@@ -24,10 +22,7 @@ namespace Doctrine\Common\Cache;
/**
* Base class for cache driver implementations.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision: 3938 $
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
......
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
......
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
......@@ -21,16 +19,12 @@
namespace Doctrine\Common\Collections;
use \Closure, \ArrayIterator;
use Closure, ArrayIterator;
/**
* An ArrayCollection is a Collection implementation that uses a regular PHP array
* internally.
* An ArrayCollection is a Collection implementation that wraps a regular PHP array.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision: 3938 $
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
......@@ -39,7 +33,6 @@ class ArrayCollection implements Collection
{
/**
* An array containing the entries of this collection.
* This is the internal php array.
*
* @var array
*/
......@@ -54,7 +47,7 @@ class ArrayCollection implements Collection
{
$this->_elements = $elements;
}
/**
* Gets the PHP array representation of this collection.
*
......@@ -121,7 +114,7 @@ class ArrayCollection implements Collection
* Removes an element with a specific key/index from the collection.
*
* @param mixed $key
* @return mixed
* @return mixed The removed element or NULL, if no element exists for the given key.
*/
public function remove($key)
{
......@@ -131,7 +124,7 @@ class ArrayCollection implements Collection
return $removed;
}
return null;
}
......@@ -413,6 +406,7 @@ class ArrayCollection implements Collection
/**
* Returns a string representation of this object.
*
* @return string
*/
public function __toString()
{
......@@ -421,7 +415,6 @@ class ArrayCollection implements Collection
/**
* Clears the collection.
*
*/
public function clear()
{
......
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
......@@ -40,10 +38,7 @@ use Closure, Countable, IteratorAggregate, ArrayAccess;
* position unless you explicitly positioned it before. Prefer iteration with
* external iterators.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision: 3938 $
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
......
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
......@@ -22,15 +20,13 @@
namespace Doctrine\Common;
/**
* Simple generic lexical scanner.
* Base class for writing simple lexers, i.e. for creating small DSLs.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision: 3938 $
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
* @todo Rename: AbstractLexer
*/
abstract class Lexer
{
......@@ -50,7 +46,7 @@ abstract class Lexer
private $_peek = 0;
/**
* @var array The next token in the query string.
* @var array The next token in the input.
*/
public $lookahead;
......@@ -60,9 +56,12 @@ abstract class Lexer
public $token;
/**
* Inputs data to be tokenized
* Sets the input data to be tokenized.
*
* The Lexer is immediately reset and the new input tokenized.
* Any unprocessed tokens from any previous input are lost.
*
* @param string $input input to be tokenized
* @param string $input The input to be tokenized.
*/
public function setInput($input)
{
......@@ -72,20 +71,18 @@ abstract class Lexer
}
/**
* Resets the scanner
*
* Resets the lexer.
*/
public function reset()
{
$this->lookahead = null;
$this->token = null;
$this->_peek = 0;
$this->token = null;
$this->_peek = 0;
$this->_position = 0;
}
/**
* Resets the peek pointer to 0
*
* Resets the peek pointer to 0.
*/
public function resetPeek()
{
......@@ -93,7 +90,7 @@ abstract class Lexer
}
/**
* Resets the lexer position on the input to the given position
* Resets the lexer position on the input to the given position.
*
* @param integer $position Position to place the lexical scanner
*/
......@@ -235,14 +232,14 @@ abstract class Lexer
}
/**
* Lexical catchable patterns
* Lexical catchable patterns.
*
* @return array
*/
abstract protected function getCatchablePatterns();
/**
* Lexical non-catchable patterns
* Lexical non-catchable patterns.
*
* @return array
*/
......
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
......
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
......@@ -21,15 +19,12 @@
namespace Doctrine\DBAL;
use Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\Logging\SQLLogger;
/**
* Configuration container for the Doctrine DBAL.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision: 3938 $
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
......@@ -46,22 +41,12 @@ class Configuration
*/
protected $_attributes = array();
/**
* Creates a new DBAL configuration instance.
*/
public function __construct()
{
$this->_attributes = array(
'sqlLogger' => null
);
}
/**
* Sets the SQL logger to use. Defaults to NULL which means SQL logging is disabled.
*
* @param SQLLogger $logger
*/
public function setSQLLogger($logger)
public function setSQLLogger(SQLLogger $logger)
{
$this->_attributes['sqlLogger'] = $logger;
}
......@@ -73,6 +58,7 @@ class Configuration
*/
public function getSQLLogger()
{
return $this->_attributes['sqlLogger'];
return isset($this->_attributes['sqlLogger']) ?
$this->_attributes['sqlLogger'] : null;
}
}
\ No newline at end of file
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
......
......@@ -78,7 +78,7 @@ EOT
if (preg_match('/^select/i', $sql)) {
$resultSet = $conn->fetchAll($sql);
} else {
$resultSet = $em->getConnection()->executeUpdate($sql);
$resultSet = $conn->executeUpdate($sql);
}
\Doctrine\Common\Util\Debug::dump($resultSet, (int) $depth);
......
......@@ -27,8 +27,7 @@ use Doctrine\Common\Cache\Cache,
* It combines all configuration options from DBAL & ORM.
*
* @since 2.0
* @internal When adding a new configuration option just write a getter/setter
* pair and add the option to the _attributes array with a proper default value.
* @internal When adding a new configuration option just write a getter/setter pair.
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
......@@ -36,24 +35,6 @@ use Doctrine\Common\Cache\Cache,
*/
class Configuration extends \Doctrine\DBAL\Configuration
{
/**
* Creates a new configuration that can be used for Doctrine.
*/
public function __construct()
{
parent::__construct();
$this->_attributes = array_merge($this->_attributes, array(
'resultCacheImpl' => null,
'queryCacheImpl' => null,
'metadataCacheImpl' => null,
'metadataDriverImpl' => null,
'proxyDir' => null,
'useCExtension' => false,
'autoGenerateProxyClasses' => true,
'proxyNamespace' => null
));
}
/**
* Sets the directory where Doctrine generates any necessary proxy class files.
*
......@@ -71,7 +52,8 @@ class Configuration extends \Doctrine\DBAL\Configuration
*/
public function getProxyDir()
{
return $this->_attributes['proxyDir'];
return isset($this->_attributes['proxyDir']) ?
$this->_attributes['proxyDir'] : null;
}
/**
......@@ -82,7 +64,8 @@ class Configuration extends \Doctrine\DBAL\Configuration
*/
public function getAutoGenerateProxyClasses()
{
return $this->_attributes['autoGenerateProxyClasses'];
return isset($this->_attributes['autoGenerateProxyClasses']) ?
$this->_attributes['autoGenerateProxyClasses'] : true;
}
/**
......@@ -103,7 +86,8 @@ class Configuration extends \Doctrine\DBAL\Configuration
*/
public function getProxyNamespace()
{
return $this->_attributes['proxyNamespace'];
return isset($this->_attributes['proxyNamespace']) ?
$this->_attributes['proxyNamespace'] : null;
}
/**
......@@ -188,7 +172,8 @@ class Configuration extends \Doctrine\DBAL\Configuration
*/
public function getMetadataDriverImpl()
{
return $this->_attributes['metadataDriverImpl'];
return isset($this->_attributes['metadataDriverImpl']) ?
$this->_attributes['metadataDriverImpl'] : null;
}
/**
......@@ -198,7 +183,8 @@ class Configuration extends \Doctrine\DBAL\Configuration
*/
public function getResultCacheImpl()
{
return $this->_attributes['resultCacheImpl'];
return isset($this->_attributes['resultCacheImpl']) ?
$this->_attributes['resultCacheImpl'] : null;
}
/**
......@@ -218,7 +204,8 @@ class Configuration extends \Doctrine\DBAL\Configuration
*/
public function getQueryCacheImpl()
{
return $this->_attributes['queryCacheImpl'];
return isset($this->_attributes['queryCacheImpl']) ?
$this->_attributes['queryCacheImpl'] : null;
}
/**
......@@ -238,7 +225,8 @@ class Configuration extends \Doctrine\DBAL\Configuration
*/
public function getMetadataCacheImpl()
{
return $this->_attributes['metadataCacheImpl'];
return isset($this->_attributes['metadataCacheImpl']) ?
$this->_attributes['metadataCacheImpl'] : null;
}
/**
......@@ -259,7 +247,8 @@ class Configuration extends \Doctrine\DBAL\Configuration
*/
public function getUseCExtension()
{
return $this->_attributes['useCExtension'];
return isset($this->_attributes['useCExtension']) ?
$this->_attributes['useCExtension'] : false;
}
/**
......@@ -350,6 +339,8 @@ class Configuration extends \Doctrine\DBAL\Configuration
* Such a function can then be used in any DQL statement in any place where string
* functions are allowed.
*
* DQL function names are case-insensitive.
*
* @param string $name
* @param string $className
*/
......@@ -366,15 +357,33 @@ class Configuration extends \Doctrine\DBAL\Configuration
*/
public function getCustomStringFunction($name)
{
$name = strtolower($name);
return isset($this->_attributes['customStringFunctions'][$name]) ?
$this->_attributes['customStringFunctions'][$name] : null;
}
/**
* Sets a map of custom DQL string functions.
*
* Keys must be function names and values the FQCN of the implementing class.
* The function names will be case-insensitive in DQL.
*
* Any previously added string functions are discarded.
*
* @param array $functions The map of custom DQL string functions.
*/
public function setCustomStringFunctions(array $functions)
{
$this->_attributes['customStringFunctions'] = array_change_key_case($functions);
}
/**
* Registers a custom DQL function that produces a numeric value.
* Such a function can then be used in any DQL statement in any place where numeric
* functions are allowed.
*
* DQL function names are case-insensitive.
*
* @param string $name
* @param string $className
*/
......@@ -391,15 +400,33 @@ class Configuration extends \Doctrine\DBAL\Configuration
*/
public function getCustomNumericFunction($name)
{
$name = strtolower($name);
return isset($this->_attributes['customNumericFunctions'][$name]) ?
$this->_attributes['customNumericFunctions'][$name] : null;
}
/**
* Sets a map of custom DQL numeric functions.
*
* Keys must be function names and values the FQCN of the implementing class.
* The function names will be case-insensitive in DQL.
*
* Any previously added numeric functions are discarded.
*
* @param array $functions The map of custom DQL numeric functions.
*/
public function setCustomNumericFunctions(array $functions)
{
$this->_attributes['customNumericFunctions'] = array_change_key_case($functions);
}
/**
* Registers a custom DQL function that produces a date/time value.
* Such a function can then be used in any DQL statement in any place where date/time
* functions are allowed.
*
* DQL function names are case-insensitive.
*
* @param string $name
* @param string $className
*/
......@@ -416,7 +443,23 @@ class Configuration extends \Doctrine\DBAL\Configuration
*/
public function getCustomDatetimeFunction($name)
{
$name = strtolower($name);
return isset($this->_attributes['customDatetimeFunctions'][$name]) ?
$this->_attributes['customDatetimeFunctions'][$name] : null;
}
/**
* Sets a map of custom DQL date/time functions.
*
* Keys must be function names and values the FQCN of the implementing class.
* The function names will be case-insensitive in DQL.
*
* Any previously added date/time functions are discarded.
*
* @param array $functions The map of custom DQL date/time functions.
*/
public function setCustomDatetimeFunctions(array $functions)
{
$this->_attributes['customDatetimeFunctions'] = array_change_key_case($functions);
}
}
\ No newline at end of file
......@@ -440,7 +440,8 @@ class EntityManager
*
* @param object $entity The entity to copy.
* @return object The new entity.
* @todo Implementation or remove.
* @todo Implementation need. This is necessary since $e2 = clone $e1; throws an E_FATAL when access anything on $e:
* Fatal error: Maximum function nesting level of '100' reached, aborting!
*/
public function copy($entity, $deep = false)
{
......
<?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;
......@@ -12,6 +29,6 @@ class EntityNotFoundException extends ORMException
{
public function __construct()
{
parent::__construct('Entity was found although one item was expected.');
parent::__construct('Entity was not found.');
}
}
\ No newline at end of file
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
......@@ -28,10 +26,7 @@ namespace Doctrine\ORM;
* This class is designed for inheritance and users can subclass this class to
* write their own repositories with business-specific methods to locate entities.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
......
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
......@@ -25,12 +23,9 @@ namespace Doctrine\ORM\Event;
* Lifecycle Events are triggered by the UnitOfWork during lifecycle transitions
* of entities.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 1.0
* @version $Revision$
* @author Roman Borschel <roman@code-factory.de>
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @since 2.0
* @author Roman Borschel <roman@code-factory.de>
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class LifecycleEventArgs extends \Doctrine\Common\EventArgs
{
......
<?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\Id;
......
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
......@@ -27,10 +25,7 @@ use Doctrine\ORM\ORMException;
/**
* Special generator for application-assigned identifiers (doesnt really generate anything).
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
......
<?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\Id;
......
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
......@@ -21,7 +19,7 @@
namespace Doctrine\ORM\Id;
use Doctrine\ORM\EntityManager;
use Serializable, Doctrine\ORM\EntityManager;
/**
* Represents an ID generator that uses a database sequence.
......@@ -29,7 +27,7 @@ use Doctrine\ORM\EntityManager;
* @since 2.0
* @author Roman Borschel <roman@code-factory.org>
*/
class SequenceGenerator extends AbstractIdGenerator implements \Serializable
class SequenceGenerator extends AbstractIdGenerator implements Serializable
{
private $_allocationSize;
private $_sequenceName;
......
<?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\Id;
......
<?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\Id;
......@@ -7,10 +24,7 @@ use Doctrine\ORM\EntityManager;
/**
* Id generator that uses a single-row database table and a hi/lo algorithm.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
......
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
......
<?php
/*
* $Id: Hydrate.php 3192 2007-11-19 17:55:23Z romanb $
*
* 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
......@@ -30,10 +28,7 @@ use PDO,
* Base class for all hydrators. A hydrator is a class that provides some form
* of transformation of an SQL result set into another structure.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision: 3192 $
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Roman Borschel <roman@code-factory.org>
*/
......
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
......
<?php
/*
* $Id: UnitOfWork.php 4947 2008-09-12 13:16:05Z romanb $
*
* 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
......
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
......@@ -242,8 +240,8 @@ class ObjectHydrator extends AbstractHydrator
* specified by the FROM clause in a DQL query.
*
* @param array $data The data of the row to process.
* @param array $cache
* @param array $result
* @param array $cache The cache to use.
* @param array $result The result array to fill.
*/
protected function _hydrateRow(array $data, array &$cache, array &$result)
{
......
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
......
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
......@@ -43,6 +41,7 @@ class SingleScalarHydrator extends AbstractHydrator
} else if ($num > 1 || count($result[key($result)]) > 1) {
throw new \Doctrine\ORM\NonUniqueResultException;
}
$result = $this->_gatherScalarRowData($result[key($result)], $cache);
return array_shift($result);
......
......@@ -32,6 +32,7 @@ namespace Doctrine\ORM\Mapping;
*
* @author Roman Borschel <roman@code-factory.org>
* @since 2.0
* @todo Potentially remove if assoc mapping objects get replaced by simple arrays.
*/
abstract class AssociationMapping
{
......@@ -58,7 +59,7 @@ abstract class AssociationMapping
public $isCascadeRemove;
/**
* READ-ONLY: Whether the association cascades save() operations from the source entity
* READ-ONLY: Whether the association cascades persist() operations from the source entity
* to the target entity/entities.
*
* @var boolean
......@@ -340,5 +341,58 @@ abstract class AssociationMapping
? $platform->quoteIdentifier($this->joinTable['name'])
: $this->joinTable['name'];
}
/**
* Determines which fields get serialized.
*
* It is only serialized what is necessary for best unserialization performance.
* That means any metadata properties that are not set or empty or simply have
* their default value are NOT serialized.
*
* @return array The names of all the fields that should be serialized.
*/
public function __sleep()
{
$serialized = array(
'sourceEntityName',
'targetEntityName',
'sourceFieldName'
);
if ($this->isCascadeDetach) {
$serialized[] = 'isCascadeDetach';
}
if ($this->isCascadeMerge) {
$serialized[] = 'isCascadeMerge';
}
if ($this->isCascadePersist) {
$serialized[] = 'isCascadePersist';
}
if ($this->isCascadeRefresh) {
$serialized[] = 'isCascadeRefresh';
}
if ($this->isCascadeRemove) {
$serialized[] = 'isCascadeRemove';
}
if ( ! $this->isOwningSide) {
$serialized[] = 'isOwningSide';
}
if ($this->mappedBy) {
$serialized[] = 'mappedBy';
}
if ($this->inversedBy) {
$serialized[] = 'inversedBy';
}
if ($this->joinTable) {
$serialized[] = 'joinTable';
}
if ($this->inherited) {
$serialized[] = 'inherited';
}
if ($this->declared) {
$serialized[] = 'declared';
}
return $serialized;
}
}
......@@ -264,8 +264,12 @@ class ClassMetadata extends ClassMetadataInfo
/**
* Determines which fields get serialized.
*
* It is only serialized what is necessary for best unserialization performance.
* That means any metadata properties that are not set or empty or simply have
* their default value are NOT serialized.
*
* Parts that are NOT serialized because they can not be properly unserialized:
* Parts that are also NOT serialized because they can not be properly unserialized:
* - reflClass (ReflectionClass)
* - reflFields (ReflectionProperty array)
*
......@@ -273,31 +277,56 @@ class ClassMetadata extends ClassMetadataInfo
*/
public function __sleep()
{
return array(
'associationMappings', // unserialization "bottleneck" with many associations
'changeTrackingPolicy',
// This metadata is always serialized/cached.
$serialized = array(
'associationMappings',
'columnNames', //TODO: Not really needed. Can use fieldMappings[$fieldName]['columnName']
'customRepositoryClassName',
'discriminatorColumn',
'discriminatorValue',
'discriminatorMap',
'fieldMappings',//TODO: Not all of this stuff needs to be serialized. Only type, columnName and fieldName.
'fieldNames',
'generatorType',
'fieldMappings',
'fieldNames',
'identifier',
'idGenerator', //TODO: Does not really need to be serialized. Could be moved to runtime.
'inheritanceType',
'isIdentifierComposite',
'isMappedSuperclass',
'isVersioned',
'lifecycleCallbacks',
'isIdentifierComposite', // TODO: REMOVE
'name',
'parentClasses',
'table',
'rootEntityName',
'subClasses',
'versionField'
'idGenerator', //TODO: Does not really need to be serialized. Could be moved to runtime.
);
// The rest of the metadata is only serialized if necessary.
if ($this->changeTrackingPolicy != self::CHANGETRACKING_DEFERRED_IMPLICIT) {
$serialized[] = 'changeTrackingPolicy';
}
if ($this->customRepositoryClassName) {
$serialized[] = 'customRepositoryClassName';
}
if ($this->inheritanceType != self::INHERITANCE_TYPE_NONE) {
$serialized[] = 'inheritanceType';
$serialized[] = 'discriminatorColumn';
$serialized[] = 'discriminatorValue';
$serialized[] = 'discriminatorMap';
$serialized[] = 'parentClasses';
$serialized[] = 'subClasses';
}
if ($this->generatorType != self::GENERATOR_TYPE_NONE) {
$serialized[] = 'generatorType';
}
if ($this->isMappedSuperclass) {
$serialized[] = 'isMappedSuperclass';
}
if ($this->isVersioned) {
$serialized[] = 'isVersioned';
$serialized[] = 'versionField';
}
if ($this->lifecycleCallbacks) {
$serialized[] = 'lifecycleCallbacks';
}
return $serialized;
}
/**
......
......@@ -26,12 +26,9 @@ use Doctrine\ORM\Mapping\ClassMetadataInfo;
/**
* Contract for metadata drivers.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 2.0
* @version $Revision: 1393 $
* @author Jonathan H. Wage <jonwage@gmail.com>
* @todo Rename: MetadataDriver
* @since 2.0
* @author Jonathan H. Wage <jonwage@gmail.com>
* @todo Rename: MetadataDriver or MappingDriver
*/
interface Driver
{
......
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
......@@ -29,14 +27,12 @@ use Doctrine\ORM\Mapping\Driver\Driver,
* The DriverChain allows you to add multiple other mapping drivers for
* certain namespaces
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan H. Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
* @since 2.0
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan H. Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
* @todo Rename: MappingDriverChain or MetadataDriverChain
*/
class DriverChain implements Driver
{
......
......@@ -30,7 +30,7 @@ use Doctrine\Common\Cache\ArrayCache,
Doctrine\ORM\Mapping\Driver\AbstractFileDriver;
/**
* The PhpDriver includes php files which just populate ClassMetadataInfo
* The PHPDriver includes php files which just populate ClassMetadataInfo
* instances with plain php code
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
......@@ -43,7 +43,7 @@ use Doctrine\Common\Cache\ArrayCache,
* @author Roman Borschel <roman@code-factory.org>
* @todo Rename: PHPDriver
*/
class PhpDriver extends AbstractFileDriver
class PHPDriver extends AbstractFileDriver
{
/**
* {@inheritdoc}
......
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\ORM\Mapping\Driver;
use Doctrine\ORM\Mapping\ClassMetadataInfo,
Doctrine\ORM\Mapping\MappingException;
/**
* The StaticPHPDriver calls a static loadMetadata() method on your entity
* classes where you can manually populate the ClassMetadata instance.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan H. Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
class StaticPHPDriver implements Driver
{
private $_paths = array();
public function __construct($paths)
{
$this->addPaths((array) $paths);
}
public function addPaths(array $paths)
{
$this->_paths = array_unique(array_merge($this->_paths, $paths));
}
/**
* {@inheritdoc}
*/
public function loadMetadataForClass($className, ClassMetadataInfo $metadata)
{
call_user_func_array(array($className, 'loadMetadata'), array($metadata));
}
/**
* {@inheritDoc}
* @todo Same code exists in AnnotationDriver, should we re-use it somehow or not worry about it?
*/
public function getAllClassNames()
{
if ($this->_classNames !== null) {
return $this->_classNames;
}
if (!$this->_paths) {
throw MappingException::pathRequired();
}
$classes = array();
$includedFiles = array();
foreach ($this->_paths as $path) {
if ( ! is_dir($path)) {
throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath();
}
$iterator = new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator($path),
\RecursiveIteratorIterator::LEAVES_ONLY
);
foreach ($iterator as $file) {
if (($fileName = $file->getBasename($this->_fileExtension)) == $file->getBasename()) {
continue;
}
$sourceFile = realpath($file->getPathName());
require_once $sourceFile;
$includedFiles[] = $sourceFile;
}
}
$declared = get_declared_classes();
foreach ($declared as $className) {
$rc = new \ReflectionClass($className);
$sourceFile = $rc->getFileName();
if (in_array($sourceFile, $includedFiles) && ! $this->isTransient($className)) {
$classes[] = $className;
}
}
$this->_classNames = $classes;
return $classes;
}
/**
* {@inheritdoc}
*/
public function isTransient($className)
{
return method_exists($className, 'loadMetadata') ? false : true;
}
}
\ No newline at end of file
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
......@@ -39,6 +37,7 @@ namespace Doctrine\ORM\Mapping;
* @since 2.0
* @author Roman Borschel <roman@code-factory.org>
* @author Giorgio Sironi <piccoloprincipeazzurro@gmail.com>
* @todo Potentially remove if assoc mapping objects get replaced by simple arrays.
*/
class ManyToManyMapping extends AssociationMapping
{
......@@ -142,39 +141,11 @@ class ManyToManyMapping extends AssociationMapping
* @param object The owner of the collection.
* @param object The collection to populate.
* @param array
* @todo Remove
*/
public function load($sourceEntity, $targetCollection, $em, array $joinColumnValues = array())
{
$sourceClass = $em->getClassMetadata($this->sourceEntityName);
$joinTableConditions = array();
if ($this->isOwningSide) {
foreach ($this->relationToSourceKeyColumns as $relationKeyColumn => $sourceKeyColumn) {
// getting id
if (isset($sourceClass->fieldNames[$sourceKeyColumn])) {
$joinTableConditions[$relationKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
} else {
throw MappingException::joinColumnMustPointToMappedField(
$sourceClass->name, $sourceKeyColumn
);
}
}
} else {
$owningAssoc = $em->getClassMetadata($this->targetEntityName)->associationMappings[$this->mappedBy];
// TRICKY: since the association is inverted source and target are flipped
foreach ($owningAssoc->relationToTargetKeyColumns as $relationKeyColumn => $sourceKeyColumn) {
// getting id
if (isset($sourceClass->fieldNames[$sourceKeyColumn])) {
$joinTableConditions[$relationKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
} else {
throw MappingException::joinColumnMustPointToMappedField(
$sourceClass->name, $sourceKeyColumn
);
}
}
}
$persister = $em->getUnitOfWork()->getEntityPersister($this->targetEntityName);
$persister->loadManyToManyCollection($this, $joinTableConditions, $targetCollection);
$em->getUnitOfWork()->getEntityPersister($this->targetEntityName)->loadManyToManyCollection($this, $sourceEntity, $targetCollection);
}
/** {@inheritdoc} */
......@@ -182,4 +153,25 @@ class ManyToManyMapping extends AssociationMapping
{
return true;
}
/**
* Determines which fields get serialized.
*
* It is only serialized what is necessary for best unserialization performance.
* That means any metadata properties that are not set or empty or simply have
* their default value are NOT serialized.
*
* @return array The names of all the fields that should be serialized.
*/
public function __sleep()
{
$serialized = parent::__sleep();
$serialized[] = 'joinTableColumns';
$serialized[] = 'relationToSourceKeyColumns';
$serialized[] = 'relationToTargetKeyColumns';
if ($this->orderBy) {
$serialized[] = 'orderBy';
}
return $serialized;
}
}
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
......
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
......@@ -43,6 +41,7 @@ namespace Doctrine\ORM\Mapping;
* @author Roman Borschel <roman@code-factory.org>
* @author Giorgio Sironi <piccoloprincipeazzurro@gmail.com>
* @since 2.0
* @todo Potentially remove if assoc mapping objects get replaced by simple arrays.
*/
class OneToManyMapping extends AssociationMapping
{
......@@ -101,8 +100,6 @@ class OneToManyMapping extends AssociationMapping
/**
* {@inheritdoc}
*
* @override
*/
public function isOneToMany()
{
......@@ -117,23 +114,31 @@ class OneToManyMapping extends AssociationMapping
* @param $em The EntityManager to use.
* @param $joinColumnValues
* @return void
* @todo Remove
*/
public function load($sourceEntity, $targetCollection, $em, array $joinColumnValues = array())
{
$persister = $em->getUnitOfWork()->getEntityPersister($this->targetEntityName);
// a one-to-many is always inverse (does not have foreign key)
$sourceClass = $em->getClassMetadata($this->sourceEntityName);
$owningAssoc = $em->getClassMetadata($this->targetEntityName)->associationMappings[$this->mappedBy];
// TRICKY: since the association is specular source and target are flipped
foreach ($owningAssoc->targetToSourceKeyColumns as $sourceKeyColumn => $targetKeyColumn) {
// getting id
if (isset($sourceClass->fieldNames[$sourceKeyColumn])) {
$conditions[$targetKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
} else {
$conditions[$targetKeyColumn] = $joinColumnValues[$sourceKeyColumn];
}
}
$em->getUnitOfWork()->getEntityPersister($this->targetEntityName)->loadOneToManyCollection($this, $sourceEntity, $targetCollection);
}
$persister->loadOneToManyCollection($this, $conditions, $targetCollection);
/**
* Determines which fields get serialized.
*
* It is only serialized what is necessary for best unserialization performance.
* That means any metadata properties that are not set or empty or simply have
* their default value are NOT serialized.
*
* @return array The names of all the fields that should be serialized.
*/
public function __sleep()
{
$serialized = parent::__sleep();
if ($this->orderBy) {
$serialized[] = 'orderBy';
}
if ($this->orphanRemoval) {
$serialized[] = 'orphanRemoval';
}
return $serialized;
}
}
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
......@@ -39,6 +37,7 @@ namespace Doctrine\ORM\Mapping;
* @since 2.0
* @author Roman Borschel <roman@code-factory.org>
* @author Giorgio Sironi <piccoloprincipeazzurro@gmail.com>
* @todo Potentially remove if assoc mapping objects get replaced by simple arrays.
*/
class OneToOneMapping extends AssociationMapping
{
......@@ -135,56 +134,32 @@ class OneToOneMapping extends AssociationMapping
* @param object $targetEntity the entity to load data in
* @param EntityManager $em
* @param array $joinColumnValues Values of the join columns of $sourceEntity.
* @todo Remove
*/
public function load($sourceEntity, $targetEntity, $em, array $joinColumnValues = array())
{
$targetClass = $em->getClassMetadata($this->targetEntityName);
if ($this->isOwningSide) {
// 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).
$hints = array();
if ($this->inversedBy) {
$hints['fetched'][$targetClass->name][$this->inversedBy] = true;
if ($targetClass->subClasses) {
foreach ($targetClass->subClasses as $targetSubclassName) {
$hints['fetched'][$targetSubclassName][$this->inversedBy] = true;
}
}
}
/* cascade read-only status
if ($em->getUnitOfWork()->isReadOnly($sourceEntity)) {
$hints[Query::HINT_READ_ONLY] = true;
}
*/
$targetEntity = $em->getUnitOfWork()->getEntityPersister($this->targetEntityName)->load($joinColumnValues, $targetEntity, $this, $hints);
if ($targetEntity !== null && $this->inversedBy && ! $targetClass->isCollectionValuedAssociation($this->inversedBy)) {
$targetClass->reflFields[$this->inversedBy]->setValue($targetEntity, $sourceEntity);
}
} else {
$conditions = array();
$sourceClass = $em->getClassMetadata($this->sourceEntityName);
$owningAssoc = $targetClass->getAssociationMapping($this->mappedBy);
// TRICKY: since the association is specular source and target are flipped
foreach ($owningAssoc->targetToSourceKeyColumns as $sourceKeyColumn => $targetKeyColumn) {
if (isset($sourceClass->fieldNames[$sourceKeyColumn])) {
$conditions[$targetKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
} else {
throw MappingException::joinColumnMustPointToMappedField(
$sourceClass->name, $sourceKeyColumn
);
}
}
return $em->getUnitOfWork()->getEntityPersister($this->targetEntityName)->loadOneToOneEntity($this, $sourceEntity, $targetEntity, $joinColumnValues);
}
$targetEntity = $em->getUnitOfWork()->getEntityPersister($this->targetEntityName)->load($conditions, $targetEntity, $this);
if ($targetEntity !== null) {
$targetClass->setFieldValue($targetEntity, $this->mappedBy, $sourceEntity);
}
/**
* Determines which fields get serialized.
*
* It is only serialized what is necessary for best unserialization performance.
* That means any metadata properties that are not set or empty or simply have
* their default value are NOT serialized.
*
* @return array The names of all the fields that should be serialized.
*/
public function __sleep()
{
$serialized = parent::__sleep();
$serialized[] = 'joinColumns';
$serialized[] = 'joinColumnFieldNames';
$serialized[] = 'sourceToTargetKeyColumns';
$serialized[] = 'targetToSourceKeyColumns';
if ($this->orphanRemoval) {
$serialized[] = 'orphanRemoval';
}
return $targetEntity;
return $serialized;
}
}
<?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;
......
<?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;
......
<?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;
......
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
......
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
......
......@@ -30,7 +30,7 @@ use Doctrine\ORM\Mapping\ClassMetadata,
* @author Roman Borschel <roman@code-factory.org>
* @since 2.0
*/
abstract class AbstractEntityInheritancePersister extends StandardEntityPersister
abstract class AbstractEntityInheritancePersister extends BasicEntityPersister
{
/**
* Map from column names to class names that declare the field the column is mapped to.
......@@ -91,7 +91,7 @@ abstract class AbstractEntityInheritancePersister extends StandardEntityPersiste
protected function _getSelectColumnSQL($field, ClassMetadata $class)
{
$columnName = $class->columnNames[$field];
$sql = $this->_getSQLTableAlias($class) . '.' . $class->getQuotedColumnName($field, $this->_platform);
$sql = $this->_getSQLTableAlias($class->name) . '.' . $class->getQuotedColumnName($field, $this->_platform);
$columnAlias = $this->_platform->getSQLResultCasing($columnName . $this->_sqlAliasCounter++);
if ( ! isset($this->_resultColumnNames[$columnAlias])) {
$this->_resultColumnNames[$columnAlias] = $columnName;
......
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
......@@ -21,15 +19,14 @@
namespace Doctrine\ORM\Persisters;
use Doctrine\ORM\ORMException;
use Doctrine\ORM\ORMException,
Doctrine\ORM\Mapping\ManyToManyMapping;
/**
* The joined subclass persister maps a single entity instance to several tables in the
* database as it is defined by the <tt>Class Table Inheritance</tt> strategy.
*
* @author Roman Borschel <roman@code-factory.org>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @see http://martinfowler.com/eaaCatalog/classTableInheritance.html
*/
......@@ -116,19 +113,19 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
$this->_class : $this->_em->getClassMetadata($this->_class->rootEntityName);
$rootPersister = $this->_em->getUnitOfWork()->getEntityPersister($rootClass->name);
$rootTableName = $rootClass->table['name'];
$rootTableStmt = $this->_conn->prepare($rootPersister->getInsertSQL());
$rootTableStmt = $this->_conn->prepare($rootPersister->_getInsertSQL());
// Prepare statements for sub tables.
$subTableStmts = array();
if ($rootClass !== $this->_class) {
$subTableStmts[$this->_class->table['name']] = $this->_conn->prepare($this->getInsertSQL());
$subTableStmts[$this->_class->table['name']] = $this->_conn->prepare($this->_getInsertSQL());
}
foreach ($this->_class->parentClasses as $parentClassName) {
$parentClass = $this->_em->getClassMetadata($parentClassName);
$parentTableName = $parentClass->table['name'];
if ($parentClass !== $rootClass) {
$parentPersister = $this->_em->getUnitOfWork()->getEntityPersister($parentClassName);
$subTableStmts[$parentTableName] = $this->_conn->prepare($parentPersister->getInsertSQL());
$subTableStmts[$parentTableName] = $this->_conn->prepare($parentPersister->_getInsertSQL());
}
}
......@@ -231,27 +228,30 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
/**
* {@inheritdoc}
*/
protected function _getSelectEntitiesSQL(array &$criteria, $assoc = null, $orderBy = null)
protected function _getSelectEntitiesSQL(array $criteria, $assoc = null)
{
$idColumns = $this->_class->getIdentifierColumnNames();
$baseTableAlias = $this->_getSQLTableAlias($this->_class);
$baseTableAlias = $this->_getSQLTableAlias($this->_class->name);
// Create the column list fragment only once
if ($this->_selectColumnListSql === null) {
// Add regular columns
$columnList = '';
foreach ($this->_class->fieldMappings as $fieldName => $mapping) {
if ($columnList != '') $columnList .= ', ';
$columnList .= $this->_getSelectColumnSQL($fieldName,
isset($mapping['inherited']) ? $this->_em->getClassMetadata($mapping['inherited']) : $this->_class);
isset($mapping['inherited']) ?
$this->_em->getClassMetadata($mapping['inherited']) :
$this->_class);
}
// Add foreign key columns
foreach ($this->_class->associationMappings as $assoc) {
if ($assoc->isOwningSide && $assoc->isOneToOne()) {
$tableAlias = $assoc->inherited ?
$this->_getSQLTableAlias($this->_em->getClassMetadata($assoc->inherited))
foreach ($this->_class->associationMappings as $assoc2) {
if ($assoc2->isOwningSide && $assoc2->isOneToOne()) {
$tableAlias = $assoc2->inherited ?
$this->_getSQLTableAlias($assoc2->inherited)
: $baseTableAlias;
foreach ($assoc->targetToSourceKeyColumns as $srcColumn) {
foreach ($assoc2->targetToSourceKeyColumns as $srcColumn) {
$columnAlias = $srcColumn . $this->_sqlAliasCounter++;
$columnList .= ", $tableAlias.$srcColumn AS $columnAlias";
$resultColumnName = $this->_platform->getSQLResultCasing($columnAlias);
......@@ -262,12 +262,12 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
}
}
// Add discriminator column (DO NOT ALIAS THIS COLUMN, see StandardEntityPersister#_processSQLResultInheritanceAware).
// Add discriminator column (DO NOT ALIAS, see AbstractEntityInheritancePersister#_processSQLResult).
$discrColumn = $this->_class->discriminatorColumn['name'];
if ($this->_class->rootEntityName == $this->_class->name) {
$columnList .= ", $baseTableAlias.$discrColumn";
} else {
$columnList .= ', ' . $this->_getSQLTableAlias($this->_em->getClassMetadata($this->_class->rootEntityName))
$columnList .= ', ' . $this->_getSQLTableAlias($this->_class->rootEntityName)
. ".$discrColumn";
}
......@@ -279,7 +279,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
$joinSql = '';
foreach ($this->_class->parentClasses as $parentClassName) {
$parentClass = $this->_em->getClassMetadata($parentClassName);
$tableAlias = $this->_getSQLTableAlias($parentClass);
$tableAlias = $this->_getSQLTableAlias($parentClassName);
$joinSql .= ' INNER JOIN ' . $parentClass->getQuotedTableName($this->_platform) . ' ' . $tableAlias . ' ON ';
$first = true;
foreach ($idColumns as $idColumn) {
......@@ -291,7 +291,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
// OUTER JOIN sub tables
foreach ($this->_class->subClasses as $subClassName) {
$subClass = $this->_em->getClassMetadata($subClassName);
$tableAlias = $this->_getSQLTableAlias($subClass);
$tableAlias = $this->_getSQLTableAlias($subClassName);
if ($this->_selectColumnListSql === null) {
// Add subclass columns
......@@ -326,27 +326,14 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
}
}
$conditionSql = '';
foreach ($criteria as $field => $value) {
if ($conditionSql != '') $conditionSql .= ' AND ';
if (isset($this->_class->fieldMappings[$field]['inherited'])) {
$conditionSql .= $this->_getSQLTableAlias($this->_em->getClassMetadata($this->_class->fieldMappings[$field]['inherited'])) . '.';
} else {
$conditionSql .= $baseTableAlias . '.';
}
if (isset($this->_class->columnNames[$field])) {
$conditionSql .= $this->_class->getQuotedColumnName($field, $this->_platform);
} else if ($assoc !== null) {
$conditionSql .= $field;
} else {
throw ORMException::unrecognizedField($field);
}
$conditionSql .= ' = ?';
}
$joinSql .= $assoc != null && $assoc->isManyToMany() ?
$this->_getSelectManyToManyJoinSQL($assoc) : '';
$conditionSql = $this->_getSelectConditionSQL($criteria, $assoc);
$orderBySql = '';
if ($orderBy !== null) {
$orderBySql = $this->_getCollectionOrderBySQL($orderBy, $baseTableAlias);
if ($assoc != null && isset($assoc->orderBy)) {
$orderBySql = $this->_getCollectionOrderBySQL($assoc->orderBy, $baseTableAlias);
}
if ($this->_selectColumnListSql === null) {
......@@ -359,10 +346,10 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
. ($conditionSql != '' ? ' WHERE ' . $conditionSql : '') . $orderBySql;
}
/** Ensure this method is never called. This persister overrides _getSelectEntitiesSQL directly. */
/* Ensure this method is never called. This persister overrides _getSelectEntitiesSQL directly. */
protected function _getSelectColumnListSQL()
{
throw new \BadMethodCallException("Illegal invocation of ".__METHOD__." on JoinedSubclassPersister.");
throw new \BadMethodCallException("Illegal invocation of ".__METHOD__.".");
}
/** {@inheritdoc} */
......@@ -398,17 +385,4 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
return $columns;
}
/**
* Gets the SQL to select a collection of entities in a many-many association.
*
* @param ManyToManyMapping $manyToMany
* @param array $criteria
* @return string
*/
protected function _getSelectManyToManyEntityCollectionSQL($manyToMany, array &$criteria)
{
// @todo
throw new \BadMethodCallException("Not yet implemented, see http://www.doctrine-project.org/jira/browse/DDC-342");
}
}
......@@ -26,7 +26,6 @@ use Doctrine\ORM\Mapping\ClassMetadata;
* SINGLE_TABLE strategy.
*
* @author Roman Borschel <roman@code-factory.org>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @since 2.0
* @link http://martinfowler.com/eaaCatalog/singleTableInheritance.html
*/
......@@ -42,24 +41,25 @@ class SingleTablePersister extends AbstractEntityInheritancePersister
protected function _getSelectColumnListSQL()
{
$columnList = parent::_getSelectColumnListSQL();
// Append discriminator column
$discrColumn = $this->_class->discriminatorColumn['name'];
$columnList .= ", $discrColumn";
$rootClass = $this->_em->getClassMetadata($this->_class->rootEntityName);
$tableAlias = $this->_getSQLTableAlias($rootClass);
$tableAlias = $this->_getSQLTableAlias($rootClass->name);
$resultColumnName = $this->_platform->getSQLResultCasing($discrColumn);
$this->_resultColumnNames[$resultColumnName] = $discrColumn;
// Append subclass columns
foreach ($this->_class->subClasses as $subClassName) {
$subClass = $this->_em->getClassMetadata($subClassName);
// Append subclass columns
// Regular columns
foreach ($subClass->fieldMappings as $fieldName => $mapping) {
if ( ! isset($mapping['inherited'])) {
$columnList .= ', ' . $this->_getSelectColumnSQL($fieldName, $subClass);
}
}
// Append subclass foreign keys
// Foreign key columns
foreach ($subClass->associationMappings as $assoc) {
if ($assoc->isOwningSide && $assoc->isOneToOne() && ! $assoc->inherited) {
foreach ($assoc->targetToSourceKeyColumns as $srcColumn) {
......@@ -88,14 +88,27 @@ class SingleTablePersister extends AbstractEntityInheritancePersister
}
/** {@inheritdoc} */
protected function _getSQLTableAlias(ClassMetadata $class)
protected function _getSQLTableAlias($className)
{
if (isset($this->_sqlTableAliases[$class->rootEntityName])) {
return $this->_sqlTableAliases[$class->rootEntityName];
return parent::_getSQLTableAlias($this->_class->rootEntityName);
}
/** {@inheritdoc} */
protected function _getSelectConditionSQL(array $criteria, $assoc = null)
{
$conditionSql = parent::_getSelectConditionSQL($criteria, $assoc);
// Append discriminator condition
if ($conditionSql) $conditionSql .= ' AND ';
$values = array($this->_conn->quote($this->_class->discriminatorValue));
$discrValues = array_flip($this->_class->discriminatorMap);
foreach ($this->_class->subClasses as $subclassName) {
$values[] = $this->_conn->quote($discrValues[$subclassName]);
}
$tableAlias = $this->_em->getClassMetadata($class->rootEntityName)->table['name'][0] . $this->_sqlAliasCounter++;
$this->_sqlTableAliases[$class->rootEntityName] = $tableAlias;
$conditionSql .= $this->_getSQLTableAlias($this->_class->name) . '.'
. $this->_class->discriminatorColumn['name']
. ' IN (' . implode(', ', $values) . ')';
return $tableAlias;
return $conditionSql;
}
}
\ No newline at end of file
......@@ -2,7 +2,7 @@
namespace Doctrine\ORM\Persisters;
class UnionSubclassPersister extends StandardEntityPersister
class UnionSubclassPersister extends BasicEntityPersister
{
}
\ No newline at end of file
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
......@@ -44,13 +42,13 @@ class ProxyFactory
private $_proxyDir;
/**
* Initializes a new instance of the <tt>ProxyFactory</tt> class that is
* connected to the given <tt>EntityManager</tt>.
*
* @param EntityManager $em The EntityManager the new factory works for.
* @param string $proxyDir The directory to use for the proxy classes. It must exist.
* @param string $proxyNs The namespace to use for the proxy classes.
* @param boolean $autoGenerate Whether to automatically generate proxy classes.
* Initializes a new instance of the <tt>ProxyFactory</tt> class that is
* connected to the given <tt>EntityManager</tt>.
*
* @param EntityManager $em The EntityManager the new factory works for.
* @param string $proxyDir The directory to use for the proxy classes. It must exist.
* @param string $proxyNs The namespace to use for the proxy classes.
* @param boolean $autoGenerate Whether to automatically generate proxy classes.
*/
public function __construct(EntityManager $em, $proxyDir, $proxyNs, $autoGenerate = false)
{
......@@ -240,7 +238,7 @@ class ProxyFactory
return $sleepImpl;
}
/** Reference Proxy class code template */
/** Proxy class code template */
private static $_proxyClassTemplate =
'<?php
......
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
......@@ -31,10 +29,7 @@ namespace Doctrine\ORM\Query\AST;
* SimpleStateFieldPathExpression ::= IdentificationVariable "." StateField
* SimpleStateFieldAssociationPathExpression ::= SingleValuedAssociationPathExpression "." StateField
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision: 3938 $
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
......
This diff is collapsed.
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
......@@ -240,16 +238,17 @@ class SqlWalker implements TreeWalker
{
$sql = '';
$baseTableAlias = $this->getSqlTableAlias($class->table['name'], $dqlAlias);
$baseTableAlias = $this->getSQLTableAlias($class->table['name'], $dqlAlias);
// INNER JOIN parent class tables
foreach ($class->parentClasses as $parentClassName) {
$parentClass = $this->_em->getClassMetadata($parentClassName);
$tableAlias = $this->getSqlTableAlias($parentClass->table['name'], $dqlAlias);
$sql .= ' INNER JOIN ' . $parentClass->getQuotedTableName($this->_platform)
$tableAlias = $this->getSQLTableAlias($parentClass->table['name'], $dqlAlias);
// 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 .= 'JOIN ' . $parentClass->getQuotedTableName($this->_platform)
. ' ' . $tableAlias . ' ON ';
$first = true;
foreach ($class->identifier as $idField) {
if ($first) $first = false; else $sql .= ' AND ';
......@@ -260,14 +259,13 @@ class SqlWalker implements TreeWalker
}
}
// LEFT JOIN subclass tables, if partial objects disallowed
// LEFT JOIN subclass tables, if partial objects disallowed.
if ( ! $this->_query->getHint(Query::HINT_FORCE_PARTIAL_LOAD)) {
foreach ($class->subClasses as $subClassName) {
$subClass = $this->_em->getClassMetadata($subClassName);
$tableAlias = $this->getSqlTableAlias($subClass->table['name'], $dqlAlias);
$tableAlias = $this->getSQLTableAlias($subClass->table['name'], $dqlAlias);
$sql .= ' LEFT JOIN ' . $subClass->getQuotedTableName($this->_platform)
. ' ' . $tableAlias . ' ON ';
$first = true;
foreach ($class->identifier as $idField) {
if ($first) $first = false; else $sql .= ' AND ';
......@@ -288,9 +286,7 @@ class SqlWalker implements TreeWalker
$sql = '';
foreach ($this->_selectedClasses AS $dqlAlias => $class) {
$qComp = $this->_queryComponents[$dqlAlias];
if (isset($qComp['relation']) && ($qComp['relation']->isManyToMany() || $qComp['relation']->isOneToMany())
&& $qComp['relation']->orderBy != null) {
if (isset($qComp['relation']->orderBy)) {
foreach ($qComp['relation']->orderBy AS $fieldName => $orientation) {
if ($qComp['metadata']->isInheritanceTypeJoined()) {
$tableName = $this->_em->getUnitOfWork()->getEntityPersister($class->name)->getOwningTable($fieldName);
......@@ -301,8 +297,8 @@ class SqlWalker implements TreeWalker
if ($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";
}
}
}
......@@ -315,7 +311,7 @@ class SqlWalker implements TreeWalker
* @param string $dqlAlias
* @return string
*/
private function _generateDiscriminatorColumnConditionSql($dqlAlias)
private function _generateDiscriminatorColumnConditionSQL($dqlAlias)
{
$sql = '';
......@@ -340,7 +336,6 @@ class SqlWalker implements TreeWalker
return $sql;
}
/**
* Walks down a SelectStatement AST node, thereby generating the appropriate SQL.
*
......@@ -353,7 +348,7 @@ class SqlWalker implements TreeWalker
if (($whereClause = $AST->whereClause) !== null) {
$sql .= $this->walkWhereClause($whereClause);
} else if (($discSql = $this->_generateDiscriminatorColumnConditionSql($this->_currentRootAlias)) !== '') {
} else if (($discSql = $this->_generateDiscriminatorColumnConditionSQL($this->_currentRootAlias)) !== '') {
$sql .= ' WHERE ' . $discSql;
}
......@@ -387,7 +382,7 @@ class SqlWalker implements TreeWalker
if (($whereClause = $AST->whereClause) !== null) {
$sql .= $this->walkWhereClause($whereClause);
} else if (($discSql = $this->_generateDiscriminatorColumnConditionSql($this->_currentRootAlias)) !== '') {
} else if (($discSql = $this->_generateDiscriminatorColumnConditionSQL($this->_currentRootAlias)) !== '') {
$sql .= ' WHERE ' . $discSql;
}
......@@ -407,7 +402,7 @@ class SqlWalker implements TreeWalker
if (($whereClause = $AST->whereClause) !== null) {
$sql .= $this->walkWhereClause($whereClause);
} else if (($discSql = $this->_generateDiscriminatorColumnConditionSql($this->_currentRootAlias)) !== '') {
} else if (($discSql = $this->_generateDiscriminatorColumnConditionSQL($this->_currentRootAlias)) !== '') {
$sql .= ' WHERE ' . $discSql;
}
......@@ -458,6 +453,7 @@ class SqlWalker implements TreeWalker
$sql .= $class->getQuotedColumnName($fieldName, $this->_platform);
break;
case AST\PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION:
// 1- the owning side:
// Just use the foreign key, i.e. u.group_id
......@@ -477,13 +473,18 @@ class SqlWalker implements TreeWalker
if (count($assoc->sourceToTargetKeyColumns) > 1) {
throw QueryException::associationPathCompositeKeyNotSupported();
}
$sql .= $this->getSqlTableAlias($class->table['name'], $dqlAlias) . '.'
. reset($assoc->targetToSourceKeyColumns);
if ($this->_useSqlTableAliases) {
$sql .= $this->getSqlTableAlias($class->table['name'], $dqlAlias) . '.';
}
$sql .= reset($assoc->targetToSourceKeyColumns);
} else {
// 2- Inverse side: NOT (YET?) SUPPORTED
throw QueryException::associationPathInverseSideNotSupported();
}
break;
default:
throw QueryException::invalidPathExpression($pathExpr);
}
......@@ -780,7 +781,7 @@ class SqlWalker implements TreeWalker
). ')';
}
$discrSql = $this->_generateDiscriminatorColumnConditionSql($joinedDqlAlias);
$discrSql = $this->_generateDiscriminatorColumnConditionSQL($joinedDqlAlias);
if ($discrSql) {
$sql .= ' AND ' . $discrSql;
......@@ -1217,7 +1218,7 @@ class SqlWalker implements TreeWalker
' OR ', array_map(array($this, 'walkConditionalTerm'), $condExpr->conditionalTerms)
);
$discrSql = $this->_generateDiscriminatorColumnConditionSql($this->_currentRootAlias);
$discrSql = $this->_generateDiscriminatorColumnConditionSQL($this->_currentRootAlias);
if ($discrSql) {
$sql .= ' AND ' . $discrSql;
......
......@@ -134,16 +134,16 @@ EOT
}
$converter = new ConvertDoctrine1Schema($fromPaths);
$metadatas = $converter->getMetadatas();
$metadata = $converter->getMetadata();
if ($metadatas) {
$output->write(PHP_EOL);
foreach ($metadatas as $metadata) {
$output->write(sprintf('Processing entity "<info>%s</info>"', $metadata->name) . PHP_EOL);
foreach ($metadata as $class) {
$output->write(sprintf('Processing entity "<info>%s</info>"', $class->name) . PHP_EOL);
}
$exporter->setMetadatas($metadatas);
$exporter->setMetadata($metadata);
$exporter->export();
$output->write(PHP_EOL . sprintf(
......
......@@ -97,8 +97,8 @@ EOT
}
$cmf = new DisconnectedClassMetadataFactory($em);
$metadatas = $cmf->getAllMetadata();
$metadatas = MetadataFilter::filter($metadatas, $input->getOption('filter'));
$metadata = $cmf->getAllMetadata();
$metadata = MetadataFilter::filter($metadata, $input->getOption('filter'));
// Process destination directory
if ( ! is_dir($destPath = $input->getArgument('dest-path'))) {
......@@ -132,12 +132,12 @@ EOT
}
}
if (count($metadatas)) {
foreach ($metadatas as $metadata) {
$output->write(sprintf('Processing entity "<info>%s</info>"', $metadata->name) . PHP_EOL);
if (count($metadata)) {
foreach ($metadata as $class) {
$output->write(sprintf('Processing entity "<info>%s</info>"', $class->name) . PHP_EOL);
}
$exporter->setMetadatas($metadatas);
$exporter->setMetadata($metadata);
$exporter->export();
$output->write(PHP_EOL . sprintf(
......
......@@ -113,7 +113,7 @@ EOT
);
}
if ( count($metadatas)) {
if (count($metadatas)) {
// Create EntityGenerator
$entityGenerator = new EntityGenerator();
......
......@@ -24,7 +24,8 @@ namespace Doctrine\ORM\Tools\Console\Command;
use Symfony\Components\Console\Input\InputArgument,
Symfony\Components\Console\Input\InputOption,
Symfony\Components\Console,
Doctrine\ORM\Tools\Console\MetadataFilter;
Doctrine\ORM\Tools\Console\MetadataFilter,
Doctrine\ORM\Tools\EntityRepositoryGenerator;
/**
* Command to generate repository classes for mapping information.
......@@ -40,23 +41,6 @@ use Symfony\Components\Console\Input\InputArgument,
*/
class GenerateRepositoriesCommand extends Console\Command\Command
{
private static $_template =
'<?php
namespace <namespace>;
use \Doctrine\ORM\EntityRepository;
/**
* <className>
*
* This class was generated by the Doctrine ORM. Add your own custom
* repository methods below.
*/
class <className> extends EntityRepository
{
}';
/**
* @see Console\Command\Command
*/
......@@ -103,8 +87,9 @@ EOT
);
}
if ( count($metadatas)) {
if (count($metadatas)) {
$numRepositories = 0;
$generator = new EntityRepositoryGenerator();
foreach ($metadatas as $metadata) {
if ($metadata->customRepositoryClassName) {
......@@ -112,7 +97,7 @@ EOT
sprintf('Processing repository "<info>%s</info>"', $metadata->customRepositoryClassName) . PHP_EOL
);
$this->_generateRepositoryClass($metadata, $destPath);
$generator->writeEntityRepositoryClass($metadata->customRepositoryClassName, $destPath);
$numRepositories++;
}
......@@ -128,19 +113,4 @@ EOT
$output->write('No Metadata Classes to process.' . PHP_EOL);
}
}
private function _generateRepositoryClass($metadata, $destPath)
{
$code = $this->_generateRepositoryClass($metadata->customRepositoryClassName);
$path = $destPath . DIRECTORY_SEPARATOR
. str_replace('\\', \DIRECTORY_SEPARATOR, $metadata->customRepositoryClassName) . '.php';
$dir = dirname($path);
if ( ! is_dir($dir)) {
mkdir($dir, 0777, true);
}
file_put_contents($path, $code);
}
}
\ No newline at end of file
......@@ -41,7 +41,8 @@ class ConvertDoctrine1Schema
private $_legacyTypeMap = array(
// TODO: This list may need to be updated
'clob' => 'text',
'timestamp' => 'datetime'
'timestamp' => 'datetime',
'enum' => 'string'
);
/**
......@@ -238,6 +239,7 @@ class ConvertDoctrine1Schema
if (isset($relation['refClass'])) {
$type = 'many';
$foreignType = 'many';
$joinColumns = array();
} else {
$type = isset($relation['type']) ? $relation['type'] : 'one';
$foreignType = isset($relation['foreignType']) ? $relation['foreignType'] : 'many';
......
......@@ -98,7 +98,7 @@ class EntityGenerator
*/
public function <methodName>()
{
return $this-><fieldName>;
<spaces>return $this-><fieldName>;
}';
private static $_setMethodTemplate =
......@@ -109,7 +109,7 @@ public function <methodName>()
*/
public function <methodName>(<methodTypeHint>$<variableName>)
{
$this-><fieldName> = $<variableName>;
<spaces>$this-><fieldName> = $<variableName>;
}';
private static $_addMethodTemplate =
......@@ -120,7 +120,7 @@ public function <methodName>(<methodTypeHint>$<variableName>)
*/
public function <methodName>(<methodTypeHint>$<variableName>)
{
$this-><fieldName>[] = $<variableName>;
<spaces>$this-><fieldName>[] = $<variableName>;
}';
private static $_lifecycleCallbackMethodTemplate =
......@@ -129,7 +129,7 @@ public function <methodName>(<methodTypeHint>$<variableName>)
*/
public function <methodName>()
{
// Add your code here
<spaces>// Add your code here
}';
/**
......@@ -203,7 +203,8 @@ public function <methodName>()
$this->_generateEntityBody($metadata)
);
return str_replace($placeHolders, $replacements, self::$_classTemplate);
$code = str_replace($placeHolders, $replacements, self::$_classTemplate);
return str_replace('<spaces>', $this->_spaces, $code);
}
/**
......@@ -218,9 +219,10 @@ public function <methodName>()
$currentCode = file_get_contents($path);
$body = $this->_generateEntityBody($metadata);
$body = str_replace('<spaces>', $this->_spaces, $body);
$last = strrpos($currentCode, '}');
return substr($currentCode, 0, $last) . $body . '}';
return substr($currentCode, 0, $last) . $body . "\n}";
}
/**
......
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\ORM\Tools;
/**
* Class to generate entity repository classes
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
class EntityRepositoryGenerator
{
protected static $_template =
'<?php
namespace <namespace>;
use Doctrine\ORM\EntityRepository;
/**
* <className>
*
* This class was generated by the Doctrine ORM. Add your own custom
* repository methods below.
*/
class <className> extends EntityRepository
{
}';
public function generateEntityRepositoryClass($fullClassName)
{
$namespace = substr($fullClassName, 0, strrpos($fullClassName, '\\'));
$className = substr($fullClassName, strrpos($fullClassName, '\\') + 1, strlen($fullClassName));
$variables = array(
'<namespace>' => $namespace,
'<className>' => $className
);
return str_replace(array_keys($variables), array_values($variables), self::$_template);
}
public function writeEntityRepositoryClass($fullClassName, $outputDirectory)
{
$code = $this->generateEntityRepositoryClass($fullClassName);
$path = $outputDirectory . DIRECTORY_SEPARATOR
. str_replace('\\', \DIRECTORY_SEPARATOR, $fullClassName) . '.php';
$dir = dirname($path);
if ( ! is_dir($dir)) {
mkdir($dir, 0777, true);
}
if ( ! file_exists($path)) {
file_put_contents($path, $code);
}
}
}
\ No newline at end of file
......@@ -63,7 +63,7 @@ class ClassMetadataExporter
* @param string $source The directory where the exporter will export to
* @return AbstractExporter $exporter
*/
public function getExporter($type, $dest)
public function getExporter($type, $dest = null)
{
if ( ! isset(self::$_exporterDrivers[$type])) {
throw ExportException::invalidExporterDriverType($type);
......
......@@ -49,6 +49,9 @@ class AnnotationExporter extends AbstractExporter
*/
public function exportClassMetadata(ClassMetadataInfo $metadata)
{
if ( ! $this->_entityGenerator) {
throw new \RuntimeException('For the AnnotationExporter you must set an EntityGenerator instance with the setEntityGenerator() method.');
}
$this->_entityGenerator->setGenerateAnnotations(true);
$this->_entityGenerator->setGenerateStubMethods(false);
$this->_entityGenerator->setRegenerateEntityIfExists(false);
......
......@@ -2,8 +2,12 @@
namespace Doctrine\ORM\Tools;
class ToolsException extends ORMException {
public static function couldNotMapDoctrine1Type($type) {
use Doctrine\ORM\ORMException;
class ToolsException extends ORMException
{
public static function couldNotMapDoctrine1Type($type)
{
return new self("Could not map doctrine 1 type '$type'!");
}
}
\ No newline at end of file
<?php
/*
* $Id: UnitOfWork.php 4947 2008-09-12 13:16:05Z romanb $
*
* 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
......@@ -33,15 +31,12 @@ use Doctrine\Common\Collections\ArrayCollection,
* "object-level" transaction and for writing out changes to the database
* in the correct order.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
* @internal This class contains performance-critical code.
* @internal This class contains highly performance-sensitive code.
*/
class UnitOfWork implements PropertyChangedListener
{
......@@ -1971,7 +1966,7 @@ class UnitOfWork implements PropertyChangedListener
if ( ! isset($this->_persisters[$entityName])) {
$class = $this->_em->getClassMetadata($entityName);
if ($class->isInheritanceTypeNone()) {
$persister = new Persisters\StandardEntityPersister($this->_em, $class);
$persister = new Persisters\BasicEntityPersister($this->_em, $class);
} else if ($class->isInheritanceTypeSingleTable()) {
$persister = new Persisters\SingleTablePersister($this->_em, $class);
} else if ($class->isInheritanceTypeJoined()) {
......
......@@ -488,7 +488,7 @@ class Application
{
// namespace
$namespace = '';
if (false !== $pos = strpos($name, ':'))
if (false !== $pos = strrpos($name, ':'))
{
$namespace = $this->findNamespace(substr($name, 0, $pos));
$name = substr($name, $pos + 1);
......
......@@ -276,7 +276,7 @@ class Command
*/
public function setName($name)
{
if (false !== $pos = strpos($name, ':'))
if (false !== $pos = strrpos($name, ':'))
{
$namespace = substr($name, 0, $pos);
$name = substr($name, $pos + 1);
......@@ -375,6 +375,28 @@ class Command
return $this->help;
}
/**
* Returns the processed help for the command replacing the %command.name% and
* %command.full_name% patterns with the real values dynamically.
*
* @return string The processed help for the command
*/
public function getProcessedHelp()
{
$name = $this->namespace.':'.$this->name;
$placeholders = array(
'%command.name%',
'%command.full_name%'
);
$replacements = array(
$name,
$_SERVER['PHP_SELF'].' '.$name
);
return str_replace($placeholders, $replacements, $this->getHelp());
}
/**
* Sets the aliases for the command.
*
......@@ -457,7 +479,7 @@ class Command
$messages[] = $this->definition->asText();
if ($help = $this->getHelp())
if ($help = $this->getProcessedHelp())
{
$messages[] = '<comment>Help:</comment>';
$messages[] = ' '.implode("\n ", explode("\n", $help))."\n";
......
......@@ -70,7 +70,7 @@ class ArgvInput extends Input
protected function parse()
{
$this->parsed = $this->tokens;
while ($token = array_shift($this->parsed))
while (null !== ($token = array_shift($this->parsed)))
{
if ('--' === substr($token, 0, 2))
{
......
......@@ -5,7 +5,7 @@ namespace Doctrine\Tests\Mocks;
/**
* EntityPersister implementation used for mocking during tests.
*/
class EntityPersisterMock extends \Doctrine\ORM\Persisters\StandardEntityPersister
class EntityPersisterMock extends \Doctrine\ORM\Persisters\BasicEntityPersister
{
private $_inserts = array();
private $_updates = array();
......
......@@ -6,9 +6,9 @@ namespace Doctrine\Tests\Models\Company;
* @Entity @Table(name="company_events")
* @InheritanceType("JOINED")
* @DiscriminatorColumn(name="event_type", type="string")
* @DiscriminatorMap({"auction" = "CompanyAuction", "raffle" = "CompanyRaffle"})
* @DiscriminatorMap({"auction"="CompanyAuction", "raffle"="CompanyRaffle"})
*/
class CompanyEvent {
abstract class CompanyEvent {
/**
* @Id @Column(type="integer")
* @GeneratedValue
......
......@@ -294,5 +294,4 @@ class ClassTableInheritanceTest extends \Doctrine\Tests\OrmFunctionalTestCase
->getResult()) > 0);
}
}
......@@ -17,9 +17,10 @@ class ClassTableInheritanceTest2 extends \Doctrine\Tests\OrmFunctionalTestCase
$this->_schemaTool->createSchema(array(
$this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\CTIParent'),
$this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\CTIChild'),
$this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\CTIRelated')
$this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\CTIRelated'),
$this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\CTIRelated2')
));
} catch (\Exception $e) {
} catch (\Exception $ignored) {
// Swallow all exceptions. We do not test the schema tool here.
}
}
......@@ -49,6 +50,27 @@ class ClassTableInheritanceTest2 extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertSame($related2, $related2->getCTIParent()->getRelated());
}
public function testManyToManyToCTIHierarchy()
{
//$this->_em->getConnection()->getConfiguration()->setSQLLogger(new \Doctrine\DBAL\Logging\EchoSQLLogger());
$mmrel = new CTIRelated2;
$child = new CTIChild;
$child->setData('child');
$mmrel->addCTIChild($child);
$this->_em->persist($mmrel);
$this->_em->persist($child);
$this->_em->flush();
$this->_em->clear();
$mmrel2 = $this->_em->find(get_class($mmrel), $mmrel->getId());
$this->assertFalse($mmrel2->getCTIChildren()->isInitialized());
$this->assertEquals(1, count($mmrel2->getCTIChildren()));
$this->assertTrue($mmrel2->getCTIChildren()->isInitialized());
$this->assertTrue($mmrel2->getCTIChildren()->get(0) instanceof CTIChild);
}
}
/**
......@@ -126,3 +148,29 @@ class CTIRelated {
$this->ctiParent = $ctiParent;
}
}
/** @Entity */
class CTIRelated2
{
/** @Id @Column(type="integer") @GeneratedValue */
private $id;
/** @ManyToMany(targetEntity="CTIChild") */
private $ctiChildren;
public function __construct() {
$this->ctiChildren = new \Doctrine\Common\Collections\ArrayCollection;
}
public function getId() {
return $this->id;
}
public function addCTIChild(CTIChild $child) {
$this->ctiChildren->add($child);
}
public function getCTIChildren() {
return $this->ctiChildren;
}
}
......@@ -66,6 +66,7 @@ class SingleTableInheritanceTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->_em->clear();
// READ by DQL on subtype
$query = $this->_em->createQuery("select e from Doctrine\Tests\ORM\Functional\ChildEntity e");
$entities = $query->getResult();
$this->assertEquals(1, count($entities));
......@@ -77,6 +78,18 @@ class SingleTableInheritanceTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->_em->clear();
// READ by findAll() on subtype
$entities = $this->_em->getRepository('Doctrine\Tests\ORM\Functional\ChildEntity')->findAll();
$this->assertEquals(1, count($entities));
$this->assertTrue($entities[0] instanceof ChildEntity);
$this->assertTrue(is_numeric($entities[0]->getId()));
$this->assertEquals('thedata', $entities[0]->getData());
$this->assertEquals(1234, $entities[0]->getNumber());
$this->assertNull($entities[0]->getParentRelated());
$this->_em->clear();
// READ by joining into an STI hierarchy from outwards
$query = $this->_em->createQuery("select r,o from Doctrine\Tests\ORM\Functional\RelatedEntity r join r.owner o");
$entities = $query->getResult();
......@@ -194,7 +207,7 @@ class SingleTableInheritanceTest extends \Doctrine\Tests\OrmFunctionalTestCase
class ParentEntity {
/**
* @Id
* @Column(type="integer")
* @Column(name="parent_id", type="integer")
* @GeneratedValue(strategy="AUTO")
*/
private $id;
......@@ -317,7 +330,7 @@ class ParentRelatedEntity {
public function setData($data) {$this->data = $data;}
/**
* @OneToOne(targetEntity="ParentEntity")
* @JoinColumn(name="parent_id", referencedColumnName="id")
* @JoinColumn(name="parent_id", referencedColumnName="parent_id")
*/
private $parent;
public function getParent() {return $this->parent;}
......
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
require_once __DIR__ . '/../../../TestInit.php';
class DDC512Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
protected function setUp()
{
parent::setUp();
$this->_schemaTool->createSchema(array(
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC512Customer'),
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC512OfferItem'),
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC512Item'),
));
}
public function testIssue()
{
$customer1 = new DDC512Customer();
$item = new DDC512OfferItem();
$customer1->item = $item;
$this->_em->persist($customer1);
$customer2 = new DDC512Customer();
$this->_em->persist($customer2);
$this->_em->flush();
$this->_em->clear();
$q = $this->_em->createQuery("select u,i from ".__NAMESPACE__."\\DDC512Customer u left join u.item i");
$result = $q->getResult();
$this->assertEquals(2, count($result));
$this->assertTrue($result[0] instanceof DDC512Customer);
$this->assertTrue($result[1] instanceof DDC512Customer);
if ($result[0]->id == $customer1->id) {
$this->assertTrue($result[0]->item instanceof DDC512OfferItem);
$this->assertEquals($item->id, $result[0]->item->id);
$this->assertNull($result[1]->item);
} else {
$this->assertTrue($result[1]->item instanceof DDC512OfferItem);
$this->assertNull($result[0]->item);
}
}
}
/**
* @Entity
*/
class DDC512Customer {
/**
* @Id
* @Column(type="integer")
* @GeneratedValue(strategy="AUTO")
*/
public $id;
/**
* NOTE that we can currently not name the join column the same as the field
* (item = item), this currently confuses Doctrine.
*
* @OneToOne(targetEntity="DDC512OfferItem", cascade={"remove","persist"})
* @JoinColumn(name="item_id", referencedColumnName="id")
*/
public $item;
}
/**
* @Entity
*/
class DDC512OfferItem extends DDC512Item
{
}
/**
* @Entity
* @InheritanceType("JOINED")
* @DiscriminatorColumn(name="discr", type="string")
* @DiscriminatorMap({"item" = "DDC512Item", "offerItem" = "DDC512OfferItem"})
*/
class DDC512Item
{
/**
* @Id
* @Column(type="integer")
* @GeneratedValue(strategy="AUTO")
*/
public $id;
}
......@@ -3,6 +3,7 @@
namespace Doctrine\Tests\ORM\Mapping;
use Doctrine\ORM\Mapping\ClassMetadata,
Doctrine\ORM\Mapping\ClassMetadataInfo,
Doctrine\ORM\Mapping\Driver\XmlDriver,
Doctrine\ORM\Mapping\Driver\YamlDriver;
......@@ -264,4 +265,109 @@ class User
{
}
public static function loadMetadata(ClassMetadataInfo $metadata)
{
$metadata->setInheritanceType(ClassMetadataInfo::INHERITANCE_TYPE_NONE);
$metadata->setPrimaryTable(array(
'name' => 'cms_users',
));
$metadata->setChangeTrackingPolicy(ClassMetadataInfo::CHANGETRACKING_DEFERRED_IMPLICIT);
$metadata->addLifecycleCallback('doStuffOnPrePersist', 'prePersist');
$metadata->addLifecycleCallback('doOtherStuffOnPrePersistToo', 'prePersist');
$metadata->addLifecycleCallback('doStuffOnPostPersist', 'postPersist');
$metadata->mapField(array(
'id' => true,
'fieldName' => 'id',
'type' => 'integer',
'columnName' => 'id',
));
$metadata->mapField(array(
'fieldName' => 'name',
'type' => 'string',
'length' => 50,
'unique' => true,
'nullable' => true,
'columnName' => 'name',
));
$metadata->mapField(array(
'fieldName' => 'email',
'type' => 'string',
'columnName' => 'user_email',
'columnDefinition' => 'CHAR(32) NOT NULL',
));
$metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_AUTO);
$metadata->mapOneToOne(array(
'fieldName' => 'address',
'targetEntity' => 'Doctrine\\Tests\\ORM\\Mapping\\Address',
'cascade' =>
array(
0 => 'remove',
),
'mappedBy' => NULL,
'inversedBy' => 'user',
'joinColumns' =>
array(
0 =>
array(
'name' => 'address_id',
'referencedColumnName' => 'id',
'onDelete' => 'CASCADE',
'onUpdate' => 'CASCADE'
),
),
'orphanRemoval' => false,
));
$metadata->mapOneToMany(array(
'fieldName' => 'phonenumbers',
'targetEntity' => 'Doctrine\\Tests\\ORM\\Mapping\\Phonenumber',
'cascade' =>
array(
1 => 'persist',
),
'mappedBy' => 'user',
'orphanRemoval' => false,
'orderBy' =>
array(
'number' => 'ASC',
),
));
$metadata->mapManyToMany(array(
'fieldName' => 'groups',
'targetEntity' => 'Doctrine\\Tests\\ORM\\Mapping\\Group',
'cascade' =>
array(
0 => 'remove',
1 => 'persist',
2 => 'refresh',
3 => 'merge',
4 => 'detach',
),
'mappedBy' => NULL,
'joinTable' =>
array(
'name' => 'cms_users_groups',
'joinColumns' =>
array(
0 =>
array(
'name' => 'user_id',
'referencedColumnName' => 'id',
'unique' => false,
'nullable' => false,
),
),
'inverseJoinColumns' =>
array(
0 =>
array(
'name' => 'group_id',
'referencedColumnName' => 'id',
'columnDefinition' => 'INT NULL',
),
),
),
'orderBy' => NULL,
));
}
}
\ No newline at end of file
......@@ -23,7 +23,8 @@ class AllTests
$suite->addTestSuite('Doctrine\Tests\ORM\Mapping\XmlMappingDriverTest');
$suite->addTestSuite('Doctrine\Tests\ORM\Mapping\YamlMappingDriverTest');
$suite->addTestSuite('Doctrine\Tests\ORM\Mapping\AnnotationDriverTest');
$suite->addTestSuite('Doctrine\Tests\ORM\Mapping\PhpMappingDriverTest');
$suite->addTestSuite('Doctrine\Tests\ORM\Mapping\PHPMappingDriverTest');
$suite->addTestSuite('Doctrine\Tests\ORM\Mapping\StaticPHPMappingDriverTest');
$suite->addTestSuite('Doctrine\Tests\ORM\Mapping\ClassMetadataFactoryTest');
$suite->addTestSuite('Doctrine\Tests\ORM\Mapping\ClassMetadataLoadEventTest');
$suite->addTestSuite('Doctrine\Tests\ORM\Mapping\BasicInheritanceMappingTest');
......
......@@ -20,8 +20,10 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase
$this->assertEquals('Doctrine\Tests\Models\CMS\CmsUser', $cm->rootEntityName);
$this->assertEquals(array(), $cm->subClasses);
$this->assertEquals(array(), $cm->parentClasses);
$this->assertEquals(ClassMetadata::INHERITANCE_TYPE_NONE, $cm->inheritanceType);
// Customize state
$cm->setInheritanceType(ClassMetadata::INHERITANCE_TYPE_SINGLE_TABLE);
$cm->setSubclasses(array("One", "Two", "Three"));
$cm->setParentClasses(array("UserParent"));
$cm->setCustomRepositoryClass("UserRepository");
......
......@@ -3,12 +3,12 @@
namespace Doctrine\Tests\ORM\Mapping;
use Doctrine\ORM\Mapping\ClassMetadata,
Doctrine\ORM\Mapping\Driver\PhpDriver,
Doctrine\ORM\Mapping\Driver\PHPDriver,
Doctrine\ORM\Tools\Export\ClassMetadataExporter;
require_once __DIR__ . '/../../TestInit.php';
class PhpMappingDriverTest extends AbstractMappingDriverTest
class PHPMappingDriverTest extends AbstractMappingDriverTest
{
protected function _loadDriver()
{
......@@ -26,6 +26,6 @@ class PhpMappingDriverTest extends AbstractMappingDriverTest
$exporter->export();
*/
return new PhpDriver($path);
return new PHPDriver($path);
}
}
\ No newline at end of file
<?php
namespace Doctrine\Tests\ORM\Mapping;
use Doctrine\ORM\Mapping\ClassMetadata,
Doctrine\ORM\Mapping\Driver\StaticPHPDriver,
Doctrine\ORM\Tools\Export\ClassMetadataExporter;
require_once __DIR__ . '/../../TestInit.php';
class StaticPHPMappingDriverTest extends AbstractMappingDriverTest
{
protected function _loadDriver()
{
return new StaticPHPDriver(__DIR__ . DIRECTORY_SEPARATOR . 'php');
}
}
\ No newline at end of file
......@@ -156,7 +156,7 @@ class ProxyClassGeneratorTest extends \Doctrine\Tests\OrmTestCase
protected function _getMockPersister()
{
$persister = $this->getMock('Doctrine\ORM\Persisters\StandardEntityPersister', array('load'), array(), '', false);
$persister = $this->getMock('Doctrine\ORM\Persisters\BasicEntityPersister', array('load'), array(), '', false);
return $persister;
}
}
......
......@@ -21,6 +21,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
$query = $this->_em->createQuery($dqlToBeTested);
$query->setHint(Query::HINT_FORCE_PARTIAL_LOAD, true)
->useQueryCache(false);
parent::assertEquals($sqlToBeConfirmed, $query->getSql());
$query->free();
} catch (\Exception $e) {
......@@ -385,7 +386,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
$this->assertEquals('SELECT d0_.id AS id0 FROM date_time_model d0_ WHERE d0_.col_datetime > CURRENT_TIMESTAMP', $q->getSql());
}
/*public function testExistsExpressionInWhereCorrelatedSubqueryAssocCondition()
public function testExistsExpressionInWhereCorrelatedSubqueryAssocCondition()
{
$this->assertSqlGeneration(
// DQL
......@@ -402,7 +403,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
. ')'
);
}*/
}
public function testLimitFromQueryClass()
{
......@@ -584,4 +585,62 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
"SELECT c0_.name AS name0, (SELECT COUNT(c1_.phonenumber) AS dctrn__1 FROM cms_phonenumbers c1_ WHERE c1_.phonenumber = 1234) AS sclr1 FROM cms_users c0_ WHERE c0_.name = 'jon'"
);
}
/**
* DDC-430
*/
public function testSupportSelectWithMoreThan10InputParameters()
{
$this->assertSqlGeneration(
"SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.id = ?1 OR u.id = ?2 OR u.id = ?3 OR u.id = ?4 OR u.id = ?5 OR u.id = ?6 OR u.id = ?7 OR u.id = ?8 OR u.id = ?9 OR u.id = ?10 OR u.id = ?11",
"SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 FROM cms_users c0_ WHERE c0_.id = ? OR c0_.id = ? OR c0_.id = ? OR c0_.id = ? OR c0_.id = ? OR c0_.id = ? OR c0_.id = ? OR c0_.id = ? OR c0_.id = ? OR c0_.id = ? OR c0_.id = ?"
);
}
/**
* DDC-431
*/
public function testSupportToCustomDQLFunctions()
{
$config = $this->_em->getConfiguration();
$config->addCustomNumericFunction('MYABS', 'Doctrine\Tests\ORM\Query\MyAbsFunction');
$this->assertSqlGeneration(
'SELECT MYABS(p.phonenumber) FROM Doctrine\Tests\Models\CMS\CmsPhonenumber p',
'SELECT ABS(c0_.phonenumber) AS sclr0 FROM cms_phonenumbers c0_'
);
$config->setCustomNumericFunctions(array());
}
}
class MyAbsFunction extends \Doctrine\ORM\Query\AST\Functions\FunctionNode
{
public $simpleArithmeticExpression;
/**
* @override
*/
public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
{
return 'ABS(' . $sqlWalker->walkSimpleArithmeticExpression(
$this->simpleArithmeticExpression
) . ')';
}
/**
* @override
*/
public function parse(\Doctrine\ORM\Query\Parser $parser)
{
$lexer = $parser->getLexer();
$parser->match(\Doctrine\ORM\Query\Lexer::T_IDENTIFIER);
$parser->match(\Doctrine\ORM\Query\Lexer::T_OPEN_PARENTHESIS);
$this->simpleArithmeticExpression = $parser->SimpleArithmeticExpression();
$parser->match(\Doctrine\ORM\Query\Lexer::T_CLOSE_PARENTHESIS);
}
}
\ No newline at end of file
......@@ -159,4 +159,12 @@ class UpdateSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
'UPDATE cms_users SET status = ? WHERE id BETWEEN ? AND ?'
);
}
public function testSingleValuedAssociationFieldInWhere()
{
$this->assertSqlGeneration(
"UPDATE Doctrine\Tests\Models\CMS\CmsPhonenumber p SET p.phonenumber = 1234 WHERE p.user = ?1",
"UPDATE cms_phonenumbers SET phonenumber = 1234 WHERE user_id = ?"
);
}
}
......@@ -15,7 +15,7 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
private static $_queryCacheImpl = null;
/* Shared connection when a TestCase is run alone (outside of it's functional suite) */
private static $_sharedConn;
protected static $_sharedConn;
/**
* @var \Doctrine\ORM\EntityManager
......@@ -33,13 +33,13 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
protected $_sqlLoggerStack;
/** The names of the model sets used in this testcase. */
private $_usedModelSets = array();
protected $_usedModelSets = array();
/** Whether the database schema has already been created. */
private static $_tablesCreated = array();
protected static $_tablesCreated = array();
/** List of model sets and their classes. */
private static $_modelSets = array(
protected static $_modelSets = array(
'cms' => array(
'Doctrine\Tests\Models\CMS\CmsUser',
'Doctrine\Tests\Models\CMS\CmsPhonenumber',
......@@ -170,11 +170,11 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
$forceCreateTables = false;
if ( ! isset($this->sharedFixture['conn'])) {
if ( ! isset(self::$_sharedConn)) {
self::$_sharedConn = TestUtil::getConnection();
if ( ! isset(static::$_sharedConn)) {
static::$_sharedConn = TestUtil::getConnection();
}
$this->sharedFixture['conn'] = self::$_sharedConn;
$this->sharedFixture['conn'] = static::$_sharedConn;
if ($this->sharedFixture['conn']->getDriver() instanceof \Doctrine\DBAL\Driver\PDOSqlite\Driver) {
$forceCreateTables = true;
......@@ -189,12 +189,12 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
$classes = array();
foreach ($this->_usedModelSets as $setName => $bool) {
if ( ! isset(self::$_tablesCreated[$setName])/* || $forceCreateTables*/) {
foreach (self::$_modelSets[$setName] as $className) {
if ( ! isset(static::$_tablesCreated[$setName])/* || $forceCreateTables*/) {
foreach (static::$_modelSets[$setName] as $className) {
$classes[] = $this->_em->getClassMetadata($className);
}
self::$_tablesCreated[$setName] = true;
static::$_tablesCreated[$setName] = true;
}
}
......
......@@ -23,7 +23,7 @@ $connectionOptions = array(
$em = \Doctrine\ORM\EntityManager::create($connectionOptions, $config);
$helperSet = new \Symfony\Components\Console\Helper\HelperSet(array(
$helpers = array(
'db' => new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper($em->getConnection()),
'em' => new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($em)
));
\ No newline at end of file
);
\ No newline at end of file
......@@ -13,7 +13,10 @@ require __DIR__ . '/cli-config.php';
$cli = new \Symfony\Components\Console\Application('Doctrine Command Line Interface', Doctrine\Common\Version::VERSION);
$cli->setCatchExceptions(true);
$cli->setHelperSet($helperSet);
$helperSet = $cli->getHelperSet();
foreach ($helpers as $name => $helper) {
$helperSet->set($helper, $name);
}
$cli->addCommands(array(
// DBAL Commands
new \Doctrine\DBAL\Tools\Console\Command\RunSqlCommand(),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment