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

Merge commit 'dc2master/master'

parents fab5ef84 2f3e9fdc
...@@ -3,9 +3,9 @@ ...@@ -3,9 +3,9 @@
## Console migrated to Symfony Console ## 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] [php]
$cliConfig = new CliConfiguration(); $cliConfig = new CliConfiguration();
...@@ -100,9 +100,22 @@ The "default" option for database column defaults has been removed. If desired, ...@@ -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). be implemented by using the columnDefinition attribute of the @Column annotation (or the approriate XML and YAML equivalents).
Prefer PHP default values, if possible. 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 ## XML Mapping Driver
...@@ -133,3 +146,9 @@ by using the API on the `PreUpdateEventArgs` instance passed to the preUpdate li ...@@ -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 to the state of the entitys properties won't affect the database UPDATE statement anymore. This gives drastic
performance benefits for the preUpdate event. 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; ...@@ -27,7 +27,8 @@ namespace Doctrine\Common\Annotations;
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org * @link www.doctrine-project.org
* @since 2.0 * @since 2.0
* @version $Revision: 3938 $ * @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com> * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com> * @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org> * @author Roman Borschel <roman@code-factory.org>
...@@ -53,13 +54,28 @@ class Annotation ...@@ -53,13 +54,28 @@ class Annotation
} }
} }
/**
* Error handler for unknown property accessor in Annotation class.
*
* @param string $name Unknown property name
*/
public function __get($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) 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,19 +27,31 @@ namespace Doctrine\Common\Annotations; ...@@ -27,19 +27,31 @@ namespace Doctrine\Common\Annotations;
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org * @link www.doctrine-project.org
* @since 2.0 * @since 2.0
* @version $Revision: 3938 $ * @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com> * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com> * @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org> * @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) public static function syntaxError($message)
{ {
return new self('[Syntax Error] ' . $message); return new self('[Syntax Error] ' . $message);
} }
/**
* Creates a new AnnotationException describing a Semantical error.
*
* @param string $message Exception message
* @return AnnotationException
*/
public static function semanticalError($message) public static function semanticalError($message)
{ {
return new self('[Semantical Error] ' . $message); return new self('[Semantical Error] ' . $message);
......
<?php <?php
/* /*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
...@@ -29,10 +27,7 @@ use \ReflectionClass, ...@@ -29,10 +27,7 @@ use \ReflectionClass,
/** /**
* A reader for docblock annotations. * A reader for docblock annotations.
* *
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0 * @since 2.0
* @version $Revision: 3938 $
* @author Benjamin Eberlei <kontakt@beberlei.de> * @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com> * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com> * @author Jonathan Wage <jonwage@gmail.com>
...@@ -46,7 +41,7 @@ class AnnotationReader ...@@ -46,7 +41,7 @@ class AnnotationReader
* @var string * @var string
* @static * @static
*/ */
private static $CACHE_SALT = "@<Annot>"; private static $CACHE_SALT = '@<Annot>';
/** /**
* Annotations Parser * Annotations Parser
...@@ -56,15 +51,14 @@ class AnnotationReader ...@@ -56,15 +51,14 @@ class AnnotationReader
private $_parser; private $_parser;
/** /**
* Cache machanism to store processed Annotations * Cache mechanism to store processed Annotations
* *
* @var Doctrine\Common\Cache\Cache * @var Doctrine\Common\Cache\Cache
*/ */
private $_cache; private $_cache;
/** /**
* Constructor. Initializes a new AnnotationReader that uses the given * Constructor. Initializes a new AnnotationReader that uses the given Cache provider.
* Cache provider.
* *
* @param Cache $cache The cache provider to use. If none is provided, ArrayCache is used. * @param Cache $cache The cache provider to use. If none is provided, ArrayCache is used.
*/ */
...@@ -112,7 +106,7 @@ class AnnotationReader ...@@ -112,7 +106,7 @@ class AnnotationReader
return $data; 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); $this->_cache->save($cacheKey, $annotations, null);
return $annotations; return $annotations;
...@@ -128,6 +122,7 @@ class AnnotationReader ...@@ -128,6 +122,7 @@ class AnnotationReader
public function getClassAnnotation(ReflectionClass $class, $annotation) public function getClassAnnotation(ReflectionClass $class, $annotation)
{ {
$annotations = $this->getClassAnnotations($class); $annotations = $this->getClassAnnotations($class);
return isset($annotations[$annotation]) ? $annotations[$annotation] : null; return isset($annotations[$annotation]) ? $annotations[$annotation] : null;
} }
...@@ -148,7 +143,7 @@ class AnnotationReader ...@@ -148,7 +143,7 @@ class AnnotationReader
return $data; return $data;
} }
$context = "property ".$property->getDeclaringClass()->getName()."::\$".$property->getName(); $context = 'property ' . $property->getDeclaringClass()->getName() . "::\$" . $property->getName();
$annotations = $this->_parser->parse($property->getDocComment(), $context); $annotations = $this->_parser->parse($property->getDocComment(), $context);
$this->_cache->save($cacheKey, $annotations, null); $this->_cache->save($cacheKey, $annotations, null);
...@@ -165,6 +160,7 @@ class AnnotationReader ...@@ -165,6 +160,7 @@ class AnnotationReader
public function getPropertyAnnotation(ReflectionProperty $property, $annotation) public function getPropertyAnnotation(ReflectionProperty $property, $annotation)
{ {
$annotations = $this->getPropertyAnnotations($property); $annotations = $this->getPropertyAnnotations($property);
return isset($annotations[$annotation]) ? $annotations[$annotation] : null; return isset($annotations[$annotation]) ? $annotations[$annotation] : null;
} }
...@@ -185,7 +181,7 @@ class AnnotationReader ...@@ -185,7 +181,7 @@ class AnnotationReader
return $data; return $data;
} }
$context = "method ".$method->getDeclaringClass()->getName()."::".$method->getName()."()"; $context = 'method ' . $method->getDeclaringClass()->getName() . '::' . $method->getName() . '()';
$annotations = $this->_parser->parse($method->getDocComment(), $context); $annotations = $this->_parser->parse($method->getDocComment(), $context);
$this->_cache->save($cacheKey, $annotations, null); $this->_cache->save($cacheKey, $annotations, null);
...@@ -202,6 +198,7 @@ class AnnotationReader ...@@ -202,6 +198,7 @@ class AnnotationReader
public function getMethodAnnotation(ReflectionMethod $method, $annotation) public function getMethodAnnotation(ReflectionMethod $method, $annotation)
{ {
$annotations = $this->getMethodAnnotations($method); $annotations = $this->getMethodAnnotations($method);
return isset($annotations[$annotation]) ? $annotations[$annotation] : null; return isset($annotations[$annotation]) ? $annotations[$annotation] : null;
} }
} }
\ No newline at end of file
...@@ -27,7 +27,8 @@ namespace Doctrine\Common\Annotations; ...@@ -27,7 +27,8 @@ namespace Doctrine\Common\Annotations;
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org * @link www.doctrine-project.org
* @since 2.0 * @since 2.0
* @version $Revision: 3938 $ * @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com> * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com> * @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org> * @author Roman Borschel <roman@code-factory.org>
...@@ -80,7 +81,7 @@ class Lexer extends \Doctrine\Common\Lexer ...@@ -80,7 +81,7 @@ class Lexer extends \Doctrine\Common\Lexer
$newVal = $this->_getNumeric($value); $newVal = $this->_getNumeric($value);
// Checking numeric value // Checking numeric value
if ($newVal !== false){ if ($newVal !== false) {
$value = $newVal; $value = $newVal;
return (strpos($value, '.') !== false || stripos($value, 'e') !== false) return (strpos($value, '.') !== false || stripos($value, 'e') !== false)
...@@ -93,16 +94,34 @@ class Lexer extends \Doctrine\Common\Lexer ...@@ -93,16 +94,34 @@ class Lexer extends \Doctrine\Common\Lexer
return self::T_STRING; return self::T_STRING;
} else { } else {
switch (strtolower($value)) { switch (strtolower($value)) {
case '@': return self::T_AT; case '@':
case ',': return self::T_COMMA; return self::T_AT;
case '(': return self::T_OPEN_PARENTHESIS;
case ')': return self::T_CLOSE_PARENTHESIS; case ',':
case '{': return self::T_OPEN_CURLY_BRACES; 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_CLOSE_CURLY_BRACES;
case '=': return self::T_EQUALS; case '=':
case '\\': return self::T_NAMESPACE_SEPARATOR; return self::T_EQUALS;
case 'true': return self::T_TRUE;
case 'false': return self::T_FALSE; case '\\':
return self::T_NAMESPACE_SEPARATOR;
case 'true':
return self::T_TRUE;
case 'false':
return self::T_FALSE;
default: default:
if (ctype_alpha($value[0]) || $value[0] === '_') { if (ctype_alpha($value[0]) || $value[0] === '_') {
return self::T_IDENTIFIER; return self::T_IDENTIFIER;
...@@ -126,6 +145,7 @@ class Lexer extends \Doctrine\Common\Lexer ...@@ -126,6 +145,7 @@ class Lexer extends \Doctrine\Common\Lexer
if ( ! is_scalar($value)) { if ( ! is_scalar($value)) {
return false; return false;
} }
// Checking for valid numeric numbers: 1.234, -1.234e-2 // Checking for valid numeric numbers: 1.234, -1.234e-2
if (is_numeric($value)) { if (is_numeric($value)) {
return $value; return $value;
......
<?php <?php
/* /*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
...@@ -24,14 +22,11 @@ namespace Doctrine\Common\Annotations; ...@@ -24,14 +22,11 @@ namespace Doctrine\Common\Annotations;
/** /**
* A simple parser for docblock 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 * @since 2.0
* @version $Revision: 3938 $ * @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com> * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com> * @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org> * @author Roman Borschel <roman@code-factory.org>
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/ */
class Parser class Parser
{ {
...@@ -173,9 +168,10 @@ class Parser ...@@ -173,9 +168,10 @@ class Parser
$message .= "'{$token['value']}' at position {$token['position']}"; $message .= "'{$token['value']}' at position {$token['position']}";
} }
if(strlen($this->_context)) { if (strlen($this->_context)) {
$message .= ' in '.$this->_context; $message .= ' in ' . $this->_context;
} }
$message .= '.'; $message .= '.';
throw AnnotationException::syntaxError($message); throw AnnotationException::syntaxError($message);
...@@ -236,7 +232,7 @@ class Parser ...@@ -236,7 +232,7 @@ class Parser
$nameParts[] = $this->_lexer->token['value']; $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 (count($nameParts) == 1) {
if (strpos($nameParts[0], ':')) { if (strpos($nameParts[0], ':')) {
list ($alias, $simpleName) = explode(':', $nameParts[0]); list ($alias, $simpleName) = explode(':', $nameParts[0]);
...@@ -250,7 +246,7 @@ class Parser ...@@ -250,7 +246,7 @@ class Parser
// Is it really an annotation class? // Is it really an annotation class?
if ( 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_OPEN_PARENTHESIS) &&
! $this->_lexer->isNextToken(Lexer::T_AT)) || ! $this->_lexer->isNextToken(Lexer::T_AT)) ||
! class_exists($name, false) ! class_exists($name, false)
...@@ -411,6 +407,7 @@ class Parser ...@@ -411,6 +407,7 @@ class Parser
foreach ($values as $value) { foreach ($values as $value) {
list ($key, $val) = $value; list ($key, $val) = $value;
if ($key !== null) { if ($key !== null) {
$array[$key] = $val; $array[$key] = $val;
} else { } else {
......
<?php <?php
/* /*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
...@@ -24,10 +22,7 @@ namespace Doctrine\Common\Cache; ...@@ -24,10 +22,7 @@ namespace Doctrine\Common\Cache;
/** /**
* Base class for cache driver implementations. * Base class for cache driver implementations.
* *
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0 * @since 2.0
* @version $Revision: 3938 $
* @author Guilherme Blanco <guilhermeblanco@hotmail.com> * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com> * @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org> * @author Roman Borschel <roman@code-factory.org>
......
<?php <?php
/* /*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
......
<?php <?php
/* /*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
...@@ -21,16 +19,12 @@ ...@@ -21,16 +19,12 @@
namespace Doctrine\Common\Collections; namespace Doctrine\Common\Collections;
use \Closure, \ArrayIterator; use Closure, ArrayIterator;
/** /**
* An ArrayCollection is a Collection implementation that uses a regular PHP array * An ArrayCollection is a Collection implementation that wraps a regular PHP array.
* internally.
* *
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0 * @since 2.0
* @version $Revision: 3938 $
* @author Guilherme Blanco <guilhermeblanco@hotmail.com> * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com> * @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org> * @author Roman Borschel <roman@code-factory.org>
...@@ -39,7 +33,6 @@ class ArrayCollection implements Collection ...@@ -39,7 +33,6 @@ class ArrayCollection implements Collection
{ {
/** /**
* An array containing the entries of this collection. * An array containing the entries of this collection.
* This is the internal php array.
* *
* @var array * @var array
*/ */
...@@ -121,7 +114,7 @@ class ArrayCollection implements Collection ...@@ -121,7 +114,7 @@ class ArrayCollection implements Collection
* Removes an element with a specific key/index from the collection. * Removes an element with a specific key/index from the collection.
* *
* @param mixed $key * @param mixed $key
* @return mixed * @return mixed The removed element or NULL, if no element exists for the given key.
*/ */
public function remove($key) public function remove($key)
{ {
...@@ -413,6 +406,7 @@ class ArrayCollection implements Collection ...@@ -413,6 +406,7 @@ class ArrayCollection implements Collection
/** /**
* Returns a string representation of this object. * Returns a string representation of this object.
* *
* @return string
*/ */
public function __toString() public function __toString()
{ {
...@@ -421,7 +415,6 @@ class ArrayCollection implements Collection ...@@ -421,7 +415,6 @@ class ArrayCollection implements Collection
/** /**
* Clears the collection. * Clears the collection.
*
*/ */
public function clear() public function clear()
{ {
......
<?php <?php
/* /*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
...@@ -40,10 +38,7 @@ use Closure, Countable, IteratorAggregate, ArrayAccess; ...@@ -40,10 +38,7 @@ use Closure, Countable, IteratorAggregate, ArrayAccess;
* position unless you explicitly positioned it before. Prefer iteration with * position unless you explicitly positioned it before. Prefer iteration with
* external iterators. * external iterators.
* *
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0 * @since 2.0
* @version $Revision: 3938 $
* @author Guilherme Blanco <guilhermeblanco@hotmail.com> * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com> * @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org> * @author Roman Borschel <roman@code-factory.org>
......
<?php <?php
/* /*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
...@@ -22,15 +20,13 @@ ...@@ -22,15 +20,13 @@
namespace Doctrine\Common; 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 * @since 2.0
* @version $Revision: 3938 $
* @author Guilherme Blanco <guilhermeblanco@hotmail.com> * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com> * @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org> * @author Roman Borschel <roman@code-factory.org>
* @todo Rename: AbstractLexer
*/ */
abstract class Lexer abstract class Lexer
{ {
...@@ -50,7 +46,7 @@ abstract class Lexer ...@@ -50,7 +46,7 @@ abstract class Lexer
private $_peek = 0; private $_peek = 0;
/** /**
* @var array The next token in the query string. * @var array The next token in the input.
*/ */
public $lookahead; public $lookahead;
...@@ -60,9 +56,12 @@ abstract class Lexer ...@@ -60,9 +56,12 @@ abstract class Lexer
public $token; 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) public function setInput($input)
{ {
...@@ -72,8 +71,7 @@ abstract class Lexer ...@@ -72,8 +71,7 @@ abstract class Lexer
} }
/** /**
* Resets the scanner * Resets the lexer.
*
*/ */
public function reset() public function reset()
{ {
...@@ -84,8 +82,7 @@ abstract class Lexer ...@@ -84,8 +82,7 @@ abstract class Lexer
} }
/** /**
* Resets the peek pointer to 0 * Resets the peek pointer to 0.
*
*/ */
public function resetPeek() public function resetPeek()
{ {
...@@ -93,7 +90,7 @@ abstract class Lexer ...@@ -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 * @param integer $position Position to place the lexical scanner
*/ */
...@@ -235,14 +232,14 @@ abstract class Lexer ...@@ -235,14 +232,14 @@ abstract class Lexer
} }
/** /**
* Lexical catchable patterns * Lexical catchable patterns.
* *
* @return array * @return array
*/ */
abstract protected function getCatchablePatterns(); abstract protected function getCatchablePatterns();
/** /**
* Lexical non-catchable patterns * Lexical non-catchable patterns.
* *
* @return array * @return array
*/ */
......
<?php <?php
/* /*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
......
<?php <?php
/* /*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
...@@ -21,15 +19,12 @@ ...@@ -21,15 +19,12 @@
namespace Doctrine\DBAL; namespace Doctrine\DBAL;
use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Logging\SQLLogger;
/** /**
* Configuration container for the Doctrine DBAL. * Configuration container for the Doctrine DBAL.
* *
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0 * @since 2.0
* @version $Revision: 3938 $
* @author Guilherme Blanco <guilhermeblanco@hotmail.com> * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com> * @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org> * @author Roman Borschel <roman@code-factory.org>
...@@ -46,22 +41,12 @@ class Configuration ...@@ -46,22 +41,12 @@ class Configuration
*/ */
protected $_attributes = array(); 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. * Sets the SQL logger to use. Defaults to NULL which means SQL logging is disabled.
* *
* @param SQLLogger $logger * @param SQLLogger $logger
*/ */
public function setSQLLogger($logger) public function setSQLLogger(SQLLogger $logger)
{ {
$this->_attributes['sqlLogger'] = $logger; $this->_attributes['sqlLogger'] = $logger;
} }
...@@ -73,6 +58,7 @@ class Configuration ...@@ -73,6 +58,7 @@ class Configuration
*/ */
public function getSQLLogger() public function getSQLLogger()
{ {
return $this->_attributes['sqlLogger']; return isset($this->_attributes['sqlLogger']) ?
$this->_attributes['sqlLogger'] : null;
} }
} }
\ No newline at end of file
<?php <?php
/* /*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
......
...@@ -78,7 +78,7 @@ EOT ...@@ -78,7 +78,7 @@ EOT
if (preg_match('/^select/i', $sql)) { if (preg_match('/^select/i', $sql)) {
$resultSet = $conn->fetchAll($sql); $resultSet = $conn->fetchAll($sql);
} else { } else {
$resultSet = $em->getConnection()->executeUpdate($sql); $resultSet = $conn->executeUpdate($sql);
} }
\Doctrine\Common\Util\Debug::dump($resultSet, (int) $depth); \Doctrine\Common\Util\Debug::dump($resultSet, (int) $depth);
......
...@@ -27,8 +27,7 @@ use Doctrine\Common\Cache\Cache, ...@@ -27,8 +27,7 @@ use Doctrine\Common\Cache\Cache,
* It combines all configuration options from DBAL & ORM. * It combines all configuration options from DBAL & ORM.
* *
* @since 2.0 * @since 2.0
* @internal When adding a new configuration option just write a getter/setter * @internal When adding a new configuration option just write a getter/setter pair.
* pair and add the option to the _attributes array with a proper default value.
* @author Benjamin Eberlei <kontakt@beberlei.de> * @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com> * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com> * @author Jonathan Wage <jonwage@gmail.com>
...@@ -36,24 +35,6 @@ use Doctrine\Common\Cache\Cache, ...@@ -36,24 +35,6 @@ use Doctrine\Common\Cache\Cache,
*/ */
class Configuration extends \Doctrine\DBAL\Configuration 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. * Sets the directory where Doctrine generates any necessary proxy class files.
* *
...@@ -71,7 +52,8 @@ class Configuration extends \Doctrine\DBAL\Configuration ...@@ -71,7 +52,8 @@ class Configuration extends \Doctrine\DBAL\Configuration
*/ */
public function getProxyDir() 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 ...@@ -82,7 +64,8 @@ class Configuration extends \Doctrine\DBAL\Configuration
*/ */
public function getAutoGenerateProxyClasses() 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 ...@@ -103,7 +86,8 @@ class Configuration extends \Doctrine\DBAL\Configuration
*/ */
public function getProxyNamespace() 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 ...@@ -188,7 +172,8 @@ class Configuration extends \Doctrine\DBAL\Configuration
*/ */
public function getMetadataDriverImpl() 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 ...@@ -198,7 +183,8 @@ class Configuration extends \Doctrine\DBAL\Configuration
*/ */
public function getResultCacheImpl() 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 ...@@ -218,7 +204,8 @@ class Configuration extends \Doctrine\DBAL\Configuration
*/ */
public function getQueryCacheImpl() 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 ...@@ -238,7 +225,8 @@ class Configuration extends \Doctrine\DBAL\Configuration
*/ */
public function getMetadataCacheImpl() 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 ...@@ -259,7 +247,8 @@ class Configuration extends \Doctrine\DBAL\Configuration
*/ */
public function getUseCExtension() 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 ...@@ -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 * Such a function can then be used in any DQL statement in any place where string
* functions are allowed. * functions are allowed.
* *
* DQL function names are case-insensitive.
*
* @param string $name * @param string $name
* @param string $className * @param string $className
*/ */
...@@ -366,15 +357,33 @@ class Configuration extends \Doctrine\DBAL\Configuration ...@@ -366,15 +357,33 @@ class Configuration extends \Doctrine\DBAL\Configuration
*/ */
public function getCustomStringFunction($name) public function getCustomStringFunction($name)
{ {
$name = strtolower($name);
return isset($this->_attributes['customStringFunctions'][$name]) ? return isset($this->_attributes['customStringFunctions'][$name]) ?
$this->_attributes['customStringFunctions'][$name] : null; $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. * 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 * Such a function can then be used in any DQL statement in any place where numeric
* functions are allowed. * functions are allowed.
* *
* DQL function names are case-insensitive.
*
* @param string $name * @param string $name
* @param string $className * @param string $className
*/ */
...@@ -391,15 +400,33 @@ class Configuration extends \Doctrine\DBAL\Configuration ...@@ -391,15 +400,33 @@ class Configuration extends \Doctrine\DBAL\Configuration
*/ */
public function getCustomNumericFunction($name) public function getCustomNumericFunction($name)
{ {
$name = strtolower($name);
return isset($this->_attributes['customNumericFunctions'][$name]) ? return isset($this->_attributes['customNumericFunctions'][$name]) ?
$this->_attributes['customNumericFunctions'][$name] : null; $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. * 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 * Such a function can then be used in any DQL statement in any place where date/time
* functions are allowed. * functions are allowed.
* *
* DQL function names are case-insensitive.
*
* @param string $name * @param string $name
* @param string $className * @param string $className
*/ */
...@@ -416,7 +443,23 @@ class Configuration extends \Doctrine\DBAL\Configuration ...@@ -416,7 +443,23 @@ class Configuration extends \Doctrine\DBAL\Configuration
*/ */
public function getCustomDatetimeFunction($name) public function getCustomDatetimeFunction($name)
{ {
$name = strtolower($name);
return isset($this->_attributes['customDatetimeFunctions'][$name]) ? return isset($this->_attributes['customDatetimeFunctions'][$name]) ?
$this->_attributes['customDatetimeFunctions'][$name] : null; $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 ...@@ -440,7 +440,8 @@ class EntityManager
* *
* @param object $entity The entity to copy. * @param object $entity The entity to copy.
* @return object The new entity. * @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) public function copy($entity, $deep = false)
{ {
......
<?php <?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; namespace Doctrine\ORM;
...@@ -12,6 +29,6 @@ class EntityNotFoundException extends ORMException ...@@ -12,6 +29,6 @@ class EntityNotFoundException extends ORMException
{ {
public function __construct() 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 <?php
/* /*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
...@@ -28,10 +26,7 @@ namespace Doctrine\ORM; ...@@ -28,10 +26,7 @@ namespace Doctrine\ORM;
* This class is designed for inheritance and users can subclass this class to * This class is designed for inheritance and users can subclass this class to
* write their own repositories with business-specific methods to locate entities. * 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 * @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de> * @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com> * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com> * @author Jonathan Wage <jonwage@gmail.com>
......
<?php <?php
/* /*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
...@@ -25,10 +23,7 @@ namespace Doctrine\ORM\Event; ...@@ -25,10 +23,7 @@ namespace Doctrine\ORM\Event;
* Lifecycle Events are triggered by the UnitOfWork during lifecycle transitions * Lifecycle Events are triggered by the UnitOfWork during lifecycle transitions
* of entities. * of entities.
* *
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @since 2.0
* @link www.doctrine-project.com
* @since 1.0
* @version $Revision$
* @author Roman Borschel <roman@code-factory.de> * @author Roman Borschel <roman@code-factory.de>
* @author Benjamin Eberlei <kontakt@beberlei.de> * @author Benjamin Eberlei <kontakt@beberlei.de>
*/ */
......
<?php <?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; namespace Doctrine\ORM\Id;
......
<?php <?php
/* /*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
...@@ -27,10 +25,7 @@ use Doctrine\ORM\ORMException; ...@@ -27,10 +25,7 @@ use Doctrine\ORM\ORMException;
/** /**
* Special generator for application-assigned identifiers (doesnt really generate anything). * 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 * @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de> * @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com> * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com> * @author Jonathan Wage <jonwage@gmail.com>
......
<?php <?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; namespace Doctrine\ORM\Id;
......
<?php <?php
/* /*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
...@@ -21,7 +19,7 @@ ...@@ -21,7 +19,7 @@
namespace Doctrine\ORM\Id; namespace Doctrine\ORM\Id;
use Doctrine\ORM\EntityManager; use Serializable, Doctrine\ORM\EntityManager;
/** /**
* Represents an ID generator that uses a database sequence. * Represents an ID generator that uses a database sequence.
...@@ -29,7 +27,7 @@ use Doctrine\ORM\EntityManager; ...@@ -29,7 +27,7 @@ use Doctrine\ORM\EntityManager;
* @since 2.0 * @since 2.0
* @author Roman Borschel <roman@code-factory.org> * @author Roman Borschel <roman@code-factory.org>
*/ */
class SequenceGenerator extends AbstractIdGenerator implements \Serializable class SequenceGenerator extends AbstractIdGenerator implements Serializable
{ {
private $_allocationSize; private $_allocationSize;
private $_sequenceName; private $_sequenceName;
......
<?php <?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; namespace Doctrine\ORM\Id;
......
<?php <?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; namespace Doctrine\ORM\Id;
...@@ -7,10 +24,7 @@ use Doctrine\ORM\EntityManager; ...@@ -7,10 +24,7 @@ use Doctrine\ORM\EntityManager;
/** /**
* Id generator that uses a single-row database table and a hi/lo algorithm. * 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 * @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de> * @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com> * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com> * @author Jonathan Wage <jonwage@gmail.com>
......
<?php <?php
/* /*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
......
<?php <?php
/* /*
* $Id: Hydrate.php 3192 2007-11-19 17:55:23Z romanb $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
...@@ -30,10 +28,7 @@ use PDO, ...@@ -30,10 +28,7 @@ use PDO,
* Base class for all hydrators. A hydrator is a class that provides some form * Base class for all hydrators. A hydrator is a class that provides some form
* of transformation of an SQL result set into another structure. * 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 * @since 2.0
* @version $Revision: 3192 $
* @author Konsta Vesterinen <kvesteri@cc.hut.fi> * @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Roman Borschel <roman@code-factory.org> * @author Roman Borschel <roman@code-factory.org>
*/ */
......
<?php <?php
/* /*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
......
<?php <?php
/* /*
* $Id: UnitOfWork.php 4947 2008-09-12 13:16:05Z romanb $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
......
<?php <?php
/* /*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
...@@ -242,8 +240,8 @@ class ObjectHydrator extends AbstractHydrator ...@@ -242,8 +240,8 @@ class ObjectHydrator extends AbstractHydrator
* specified by the FROM clause in a DQL query. * specified by the FROM clause in a DQL query.
* *
* @param array $data The data of the row to process. * @param array $data The data of the row to process.
* @param array $cache * @param array $cache The cache to use.
* @param array $result * @param array $result The result array to fill.
*/ */
protected function _hydrateRow(array $data, array &$cache, array &$result) protected function _hydrateRow(array $data, array &$cache, array &$result)
{ {
......
<?php <?php
/* /*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
......
<?php <?php
/* /*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
...@@ -43,6 +41,7 @@ class SingleScalarHydrator extends AbstractHydrator ...@@ -43,6 +41,7 @@ class SingleScalarHydrator extends AbstractHydrator
} else if ($num > 1 || count($result[key($result)]) > 1) { } else if ($num > 1 || count($result[key($result)]) > 1) {
throw new \Doctrine\ORM\NonUniqueResultException; throw new \Doctrine\ORM\NonUniqueResultException;
} }
$result = $this->_gatherScalarRowData($result[key($result)], $cache); $result = $this->_gatherScalarRowData($result[key($result)], $cache);
return array_shift($result); return array_shift($result);
......
...@@ -32,6 +32,7 @@ namespace Doctrine\ORM\Mapping; ...@@ -32,6 +32,7 @@ namespace Doctrine\ORM\Mapping;
* *
* @author Roman Borschel <roman@code-factory.org> * @author Roman Borschel <roman@code-factory.org>
* @since 2.0 * @since 2.0
* @todo Potentially remove if assoc mapping objects get replaced by simple arrays.
*/ */
abstract class AssociationMapping abstract class AssociationMapping
{ {
...@@ -58,7 +59,7 @@ abstract class AssociationMapping ...@@ -58,7 +59,7 @@ abstract class AssociationMapping
public $isCascadeRemove; 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. * to the target entity/entities.
* *
* @var boolean * @var boolean
...@@ -341,4 +342,57 @@ abstract class AssociationMapping ...@@ -341,4 +342,57 @@ abstract class AssociationMapping
: $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;
}
} }
...@@ -265,7 +265,11 @@ class ClassMetadata extends ClassMetadataInfo ...@@ -265,7 +265,11 @@ class ClassMetadata extends ClassMetadataInfo
/** /**
* Determines which fields get serialized. * Determines which fields get serialized.
* *
* Parts that are NOT serialized because they can not be properly unserialized: * 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 also NOT serialized because they can not be properly unserialized:
* - reflClass (ReflectionClass) * - reflClass (ReflectionClass)
* - reflFields (ReflectionProperty array) * - reflFields (ReflectionProperty array)
* *
...@@ -273,31 +277,56 @@ class ClassMetadata extends ClassMetadataInfo ...@@ -273,31 +277,56 @@ class ClassMetadata extends ClassMetadataInfo
*/ */
public function __sleep() public function __sleep()
{ {
return array( // This metadata is always serialized/cached.
'associationMappings', // unserialization "bottleneck" with many associations $serialized = array(
'changeTrackingPolicy', 'associationMappings',
'columnNames', //TODO: Not really needed. Can use fieldMappings[$fieldName]['columnName'] 'columnNames', //TODO: Not really needed. Can use fieldMappings[$fieldName]['columnName']
'customRepositoryClassName', 'fieldMappings',
'discriminatorColumn',
'discriminatorValue',
'discriminatorMap',
'fieldMappings',//TODO: Not all of this stuff needs to be serialized. Only type, columnName and fieldName.
'fieldNames', 'fieldNames',
'generatorType',
'identifier', 'identifier',
'idGenerator', //TODO: Does not really need to be serialized. Could be moved to runtime. 'isIdentifierComposite', // TODO: REMOVE
'inheritanceType',
'isIdentifierComposite',
'isMappedSuperclass',
'isVersioned',
'lifecycleCallbacks',
'name', 'name',
'parentClasses',
'table', 'table',
'rootEntityName', 'rootEntityName',
'subClasses', 'idGenerator', //TODO: Does not really need to be serialized. Could be moved to runtime.
'versionField'
); );
// 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; ...@@ -26,12 +26,9 @@ use Doctrine\ORM\Mapping\ClassMetadataInfo;
/** /**
* Contract for metadata drivers. * Contract for metadata drivers.
* *
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 2.0 * @since 2.0
* @version $Revision: 1393 $
* @author Jonathan H. Wage <jonwage@gmail.com> * @author Jonathan H. Wage <jonwage@gmail.com>
* @todo Rename: MetadataDriver * @todo Rename: MetadataDriver or MappingDriver
*/ */
interface Driver interface Driver
{ {
......
<?php <?php
/* /*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
...@@ -29,14 +27,12 @@ use Doctrine\ORM\Mapping\Driver\Driver, ...@@ -29,14 +27,12 @@ use Doctrine\ORM\Mapping\Driver\Driver,
* The DriverChain allows you to add multiple other mapping drivers for * The DriverChain allows you to add multiple other mapping drivers for
* certain namespaces * certain namespaces
* *
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0 * @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de> * @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com> * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan H. Wage <jonwage@gmail.com> * @author Jonathan H. Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org> * @author Roman Borschel <roman@code-factory.org>
* @todo Rename: MappingDriverChain or MetadataDriverChain
*/ */
class DriverChain implements Driver class DriverChain implements Driver
{ {
......
...@@ -30,7 +30,7 @@ use Doctrine\Common\Cache\ArrayCache, ...@@ -30,7 +30,7 @@ use Doctrine\Common\Cache\ArrayCache,
Doctrine\ORM\Mapping\Driver\AbstractFileDriver; 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 * instances with plain php code
* *
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
...@@ -43,7 +43,7 @@ use Doctrine\Common\Cache\ArrayCache, ...@@ -43,7 +43,7 @@ use Doctrine\Common\Cache\ArrayCache,
* @author Roman Borschel <roman@code-factory.org> * @author Roman Borschel <roman@code-factory.org>
* @todo Rename: PHPDriver * @todo Rename: PHPDriver
*/ */
class PhpDriver extends AbstractFileDriver class PHPDriver extends AbstractFileDriver
{ {
/** /**
* {@inheritdoc} * {@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 <?php
/* /*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
...@@ -39,6 +37,7 @@ namespace Doctrine\ORM\Mapping; ...@@ -39,6 +37,7 @@ namespace Doctrine\ORM\Mapping;
* @since 2.0 * @since 2.0
* @author Roman Borschel <roman@code-factory.org> * @author Roman Borschel <roman@code-factory.org>
* @author Giorgio Sironi <piccoloprincipeazzurro@gmail.com> * @author Giorgio Sironi <piccoloprincipeazzurro@gmail.com>
* @todo Potentially remove if assoc mapping objects get replaced by simple arrays.
*/ */
class ManyToManyMapping extends AssociationMapping class ManyToManyMapping extends AssociationMapping
{ {
...@@ -142,39 +141,11 @@ class ManyToManyMapping extends AssociationMapping ...@@ -142,39 +141,11 @@ class ManyToManyMapping extends AssociationMapping
* @param object The owner of the collection. * @param object The owner of the collection.
* @param object The collection to populate. * @param object The collection to populate.
* @param array * @param array
* @todo Remove
*/ */
public function load($sourceEntity, $targetCollection, $em, array $joinColumnValues = array()) public function load($sourceEntity, $targetCollection, $em, array $joinColumnValues = array())
{ {
$sourceClass = $em->getClassMetadata($this->sourceEntityName); $em->getUnitOfWork()->getEntityPersister($this->targetEntityName)->loadManyToManyCollection($this, $sourceEntity, $targetCollection);
$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);
} }
/** {@inheritdoc} */ /** {@inheritdoc} */
...@@ -182,4 +153,25 @@ class ManyToManyMapping extends AssociationMapping ...@@ -182,4 +153,25 @@ class ManyToManyMapping extends AssociationMapping
{ {
return true; 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 <?php
/* /*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
......
<?php <?php
/* /*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
...@@ -43,6 +41,7 @@ namespace Doctrine\ORM\Mapping; ...@@ -43,6 +41,7 @@ namespace Doctrine\ORM\Mapping;
* @author Roman Borschel <roman@code-factory.org> * @author Roman Borschel <roman@code-factory.org>
* @author Giorgio Sironi <piccoloprincipeazzurro@gmail.com> * @author Giorgio Sironi <piccoloprincipeazzurro@gmail.com>
* @since 2.0 * @since 2.0
* @todo Potentially remove if assoc mapping objects get replaced by simple arrays.
*/ */
class OneToManyMapping extends AssociationMapping class OneToManyMapping extends AssociationMapping
{ {
...@@ -101,8 +100,6 @@ class OneToManyMapping extends AssociationMapping ...@@ -101,8 +100,6 @@ class OneToManyMapping extends AssociationMapping
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @override
*/ */
public function isOneToMany() public function isOneToMany()
{ {
...@@ -117,23 +114,31 @@ class OneToManyMapping extends AssociationMapping ...@@ -117,23 +114,31 @@ class OneToManyMapping extends AssociationMapping
* @param $em The EntityManager to use. * @param $em The EntityManager to use.
* @param $joinColumnValues * @param $joinColumnValues
* @return void * @return void
* @todo Remove
*/ */
public function load($sourceEntity, $targetCollection, $em, array $joinColumnValues = array()) public function load($sourceEntity, $targetCollection, $em, array $joinColumnValues = array())
{ {
$persister = $em->getUnitOfWork()->getEntityPersister($this->targetEntityName); $em->getUnitOfWork()->getEntityPersister($this->targetEntityName)->loadOneToManyCollection($this, $sourceEntity, $targetCollection);
// 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];
}
} }
$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 <?php
/* /*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
...@@ -39,6 +37,7 @@ namespace Doctrine\ORM\Mapping; ...@@ -39,6 +37,7 @@ namespace Doctrine\ORM\Mapping;
* @since 2.0 * @since 2.0
* @author Roman Borschel <roman@code-factory.org> * @author Roman Borschel <roman@code-factory.org>
* @author Giorgio Sironi <piccoloprincipeazzurro@gmail.com> * @author Giorgio Sironi <piccoloprincipeazzurro@gmail.com>
* @todo Potentially remove if assoc mapping objects get replaced by simple arrays.
*/ */
class OneToOneMapping extends AssociationMapping class OneToOneMapping extends AssociationMapping
{ {
...@@ -135,56 +134,32 @@ class OneToOneMapping extends AssociationMapping ...@@ -135,56 +134,32 @@ class OneToOneMapping extends AssociationMapping
* @param object $targetEntity the entity to load data in * @param object $targetEntity the entity to load data in
* @param EntityManager $em * @param EntityManager $em
* @param array $joinColumnValues Values of the join columns of $sourceEntity. * @param array $joinColumnValues Values of the join columns of $sourceEntity.
* @todo Remove
*/ */
public function load($sourceEntity, $targetEntity, $em, array $joinColumnValues = array()) public function load($sourceEntity, $targetEntity, $em, array $joinColumnValues = array())
{ {
$targetClass = $em->getClassMetadata($this->targetEntityName); return $em->getUnitOfWork()->getEntityPersister($this->targetEntityName)->loadOneToOneEntity($this, $sourceEntity, $targetEntity, $joinColumnValues);
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); * Determines which fields get serialized.
} *
} else { * It is only serialized what is necessary for best unserialization performance.
$conditions = array(); * That means any metadata properties that are not set or empty or simply have
$sourceClass = $em->getClassMetadata($this->sourceEntityName); * their default value are NOT serialized.
$owningAssoc = $targetClass->getAssociationMapping($this->mappedBy); *
// TRICKY: since the association is specular source and target are flipped * @return array The names of all the fields that should be serialized.
foreach ($owningAssoc->targetToSourceKeyColumns as $sourceKeyColumn => $targetKeyColumn) { */
if (isset($sourceClass->fieldNames[$sourceKeyColumn])) { public function __sleep()
$conditions[$targetKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity); {
} else { $serialized = parent::__sleep();
throw MappingException::joinColumnMustPointToMappedField( $serialized[] = 'joinColumns';
$sourceClass->name, $sourceKeyColumn $serialized[] = 'joinColumnFieldNames';
); $serialized[] = 'sourceToTargetKeyColumns';
} $serialized[] = 'targetToSourceKeyColumns';
} if ($this->orphanRemoval) {
$serialized[] = 'orphanRemoval';
$targetEntity = $em->getUnitOfWork()->getEntityPersister($this->targetEntityName)->load($conditions, $targetEntity, $this); }
return $serialized;
if ($targetEntity !== null) {
$targetClass->setFieldValue($targetEntity, $this->mappedBy, $sourceEntity);
}
}
return $targetEntity;
} }
} }
<?php <?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; namespace Doctrine\ORM;
......
<?php <?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; namespace Doctrine\ORM;
......
<?php <?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; namespace Doctrine\ORM;
......
<?php <?php
/* /*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
......
<?php <?php
/* /*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
......
...@@ -30,7 +30,7 @@ use Doctrine\ORM\Mapping\ClassMetadata, ...@@ -30,7 +30,7 @@ use Doctrine\ORM\Mapping\ClassMetadata,
* @author Roman Borschel <roman@code-factory.org> * @author Roman Borschel <roman@code-factory.org>
* @since 2.0 * @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. * 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 ...@@ -91,7 +91,7 @@ abstract class AbstractEntityInheritancePersister extends StandardEntityPersiste
protected function _getSelectColumnSQL($field, ClassMetadata $class) protected function _getSelectColumnSQL($field, ClassMetadata $class)
{ {
$columnName = $class->columnNames[$field]; $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++); $columnAlias = $this->_platform->getSQLResultCasing($columnName . $this->_sqlAliasCounter++);
if ( ! isset($this->_resultColumnNames[$columnAlias])) { if ( ! isset($this->_resultColumnNames[$columnAlias])) {
$this->_resultColumnNames[$columnAlias] = $columnName; $this->_resultColumnNames[$columnAlias] = $columnName;
......
<?php <?php
/* /*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
...@@ -21,15 +19,14 @@ ...@@ -21,15 +19,14 @@
namespace Doctrine\ORM\Persisters; 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 * 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. * database as it is defined by the <tt>Class Table Inheritance</tt> strategy.
* *
* @author Roman Borschel <roman@code-factory.org> * @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 * @since 2.0
* @see http://martinfowler.com/eaaCatalog/classTableInheritance.html * @see http://martinfowler.com/eaaCatalog/classTableInheritance.html
*/ */
...@@ -116,19 +113,19 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister ...@@ -116,19 +113,19 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
$this->_class : $this->_em->getClassMetadata($this->_class->rootEntityName); $this->_class : $this->_em->getClassMetadata($this->_class->rootEntityName);
$rootPersister = $this->_em->getUnitOfWork()->getEntityPersister($rootClass->name); $rootPersister = $this->_em->getUnitOfWork()->getEntityPersister($rootClass->name);
$rootTableName = $rootClass->table['name']; $rootTableName = $rootClass->table['name'];
$rootTableStmt = $this->_conn->prepare($rootPersister->getInsertSQL()); $rootTableStmt = $this->_conn->prepare($rootPersister->_getInsertSQL());
// Prepare statements for sub tables. // Prepare statements for sub tables.
$subTableStmts = array(); $subTableStmts = array();
if ($rootClass !== $this->_class) { if ($rootClass !== $this->_class) {
$subTableStmts[$this->_class->table['name']] = $this->_conn->prepare($this->getInsertSQL()); $subTableStmts[$this->_class->table['name']] = $this->_conn->prepare($this->_getInsertSQL());
} }
foreach ($this->_class->parentClasses as $parentClassName) { foreach ($this->_class->parentClasses as $parentClassName) {
$parentClass = $this->_em->getClassMetadata($parentClassName); $parentClass = $this->_em->getClassMetadata($parentClassName);
$parentTableName = $parentClass->table['name']; $parentTableName = $parentClass->table['name'];
if ($parentClass !== $rootClass) { if ($parentClass !== $rootClass) {
$parentPersister = $this->_em->getUnitOfWork()->getEntityPersister($parentClassName); $parentPersister = $this->_em->getUnitOfWork()->getEntityPersister($parentClassName);
$subTableStmts[$parentTableName] = $this->_conn->prepare($parentPersister->getInsertSQL()); $subTableStmts[$parentTableName] = $this->_conn->prepare($parentPersister->_getInsertSQL());
} }
} }
...@@ -231,27 +228,30 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister ...@@ -231,27 +228,30 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
protected function _getSelectEntitiesSQL(array &$criteria, $assoc = null, $orderBy = null) protected function _getSelectEntitiesSQL(array $criteria, $assoc = null)
{ {
$idColumns = $this->_class->getIdentifierColumnNames(); $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) { if ($this->_selectColumnListSql === null) {
// Add regular columns // Add regular columns
$columnList = ''; $columnList = '';
foreach ($this->_class->fieldMappings as $fieldName => $mapping) { foreach ($this->_class->fieldMappings as $fieldName => $mapping) {
if ($columnList != '') $columnList .= ', '; if ($columnList != '') $columnList .= ', ';
$columnList .= $this->_getSelectColumnSQL($fieldName, $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 // Add foreign key columns
foreach ($this->_class->associationMappings as $assoc) { foreach ($this->_class->associationMappings as $assoc2) {
if ($assoc->isOwningSide && $assoc->isOneToOne()) { if ($assoc2->isOwningSide && $assoc2->isOneToOne()) {
$tableAlias = $assoc->inherited ? $tableAlias = $assoc2->inherited ?
$this->_getSQLTableAlias($this->_em->getClassMetadata($assoc->inherited)) $this->_getSQLTableAlias($assoc2->inherited)
: $baseTableAlias; : $baseTableAlias;
foreach ($assoc->targetToSourceKeyColumns as $srcColumn) { foreach ($assoc2->targetToSourceKeyColumns as $srcColumn) {
$columnAlias = $srcColumn . $this->_sqlAliasCounter++; $columnAlias = $srcColumn . $this->_sqlAliasCounter++;
$columnList .= ", $tableAlias.$srcColumn AS $columnAlias"; $columnList .= ", $tableAlias.$srcColumn AS $columnAlias";
$resultColumnName = $this->_platform->getSQLResultCasing($columnAlias); $resultColumnName = $this->_platform->getSQLResultCasing($columnAlias);
...@@ -262,12 +262,12 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister ...@@ -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']; $discrColumn = $this->_class->discriminatorColumn['name'];
if ($this->_class->rootEntityName == $this->_class->name) { if ($this->_class->rootEntityName == $this->_class->name) {
$columnList .= ", $baseTableAlias.$discrColumn"; $columnList .= ", $baseTableAlias.$discrColumn";
} else { } else {
$columnList .= ', ' . $this->_getSQLTableAlias($this->_em->getClassMetadata($this->_class->rootEntityName)) $columnList .= ', ' . $this->_getSQLTableAlias($this->_class->rootEntityName)
. ".$discrColumn"; . ".$discrColumn";
} }
...@@ -279,7 +279,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister ...@@ -279,7 +279,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
$joinSql = ''; $joinSql = '';
foreach ($this->_class->parentClasses as $parentClassName) { foreach ($this->_class->parentClasses as $parentClassName) {
$parentClass = $this->_em->getClassMetadata($parentClassName); $parentClass = $this->_em->getClassMetadata($parentClassName);
$tableAlias = $this->_getSQLTableAlias($parentClass); $tableAlias = $this->_getSQLTableAlias($parentClassName);
$joinSql .= ' INNER JOIN ' . $parentClass->getQuotedTableName($this->_platform) . ' ' . $tableAlias . ' ON '; $joinSql .= ' INNER JOIN ' . $parentClass->getQuotedTableName($this->_platform) . ' ' . $tableAlias . ' ON ';
$first = true; $first = true;
foreach ($idColumns as $idColumn) { foreach ($idColumns as $idColumn) {
...@@ -291,7 +291,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister ...@@ -291,7 +291,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
// OUTER JOIN sub tables // OUTER JOIN sub tables
foreach ($this->_class->subClasses as $subClassName) { foreach ($this->_class->subClasses as $subClassName) {
$subClass = $this->_em->getClassMetadata($subClassName); $subClass = $this->_em->getClassMetadata($subClassName);
$tableAlias = $this->_getSQLTableAlias($subClass); $tableAlias = $this->_getSQLTableAlias($subClassName);
if ($this->_selectColumnListSql === null) { if ($this->_selectColumnListSql === null) {
// Add subclass columns // Add subclass columns
...@@ -326,27 +326,14 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister ...@@ -326,27 +326,14 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
} }
} }
$conditionSql = ''; $joinSql .= $assoc != null && $assoc->isManyToMany() ?
foreach ($criteria as $field => $value) { $this->_getSelectManyToManyJoinSQL($assoc) : '';
if ($conditionSql != '') $conditionSql .= ' AND ';
if (isset($this->_class->fieldMappings[$field]['inherited'])) { $conditionSql = $this->_getSelectConditionSQL($criteria, $assoc);
$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 .= ' = ?';
}
$orderBySql = ''; $orderBySql = '';
if ($orderBy !== null) { if ($assoc != null && isset($assoc->orderBy)) {
$orderBySql = $this->_getCollectionOrderBySQL($orderBy, $baseTableAlias); $orderBySql = $this->_getCollectionOrderBySQL($assoc->orderBy, $baseTableAlias);
} }
if ($this->_selectColumnListSql === null) { if ($this->_selectColumnListSql === null) {
...@@ -359,10 +346,10 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister ...@@ -359,10 +346,10 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
. ($conditionSql != '' ? ' WHERE ' . $conditionSql : '') . $orderBySql; . ($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() protected function _getSelectColumnListSQL()
{ {
throw new \BadMethodCallException("Illegal invocation of ".__METHOD__." on JoinedSubclassPersister."); throw new \BadMethodCallException("Illegal invocation of ".__METHOD__.".");
} }
/** {@inheritdoc} */ /** {@inheritdoc} */
...@@ -398,17 +385,4 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister ...@@ -398,17 +385,4 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
return $columns; 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; ...@@ -26,7 +26,6 @@ use Doctrine\ORM\Mapping\ClassMetadata;
* SINGLE_TABLE strategy. * SINGLE_TABLE strategy.
* *
* @author Roman Borschel <roman@code-factory.org> * @author Roman Borschel <roman@code-factory.org>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @since 2.0 * @since 2.0
* @link http://martinfowler.com/eaaCatalog/singleTableInheritance.html * @link http://martinfowler.com/eaaCatalog/singleTableInheritance.html
*/ */
...@@ -42,24 +41,25 @@ class SingleTablePersister extends AbstractEntityInheritancePersister ...@@ -42,24 +41,25 @@ class SingleTablePersister extends AbstractEntityInheritancePersister
protected function _getSelectColumnListSQL() protected function _getSelectColumnListSQL()
{ {
$columnList = parent::_getSelectColumnListSQL(); $columnList = parent::_getSelectColumnListSQL();
// Append discriminator column // Append discriminator column
$discrColumn = $this->_class->discriminatorColumn['name']; $discrColumn = $this->_class->discriminatorColumn['name'];
$columnList .= ", $discrColumn"; $columnList .= ", $discrColumn";
$rootClass = $this->_em->getClassMetadata($this->_class->rootEntityName); $rootClass = $this->_em->getClassMetadata($this->_class->rootEntityName);
$tableAlias = $this->_getSQLTableAlias($rootClass); $tableAlias = $this->_getSQLTableAlias($rootClass->name);
$resultColumnName = $this->_platform->getSQLResultCasing($discrColumn); $resultColumnName = $this->_platform->getSQLResultCasing($discrColumn);
$this->_resultColumnNames[$resultColumnName] = $discrColumn; $this->_resultColumnNames[$resultColumnName] = $discrColumn;
// Append subclass columns
foreach ($this->_class->subClasses as $subClassName) { foreach ($this->_class->subClasses as $subClassName) {
$subClass = $this->_em->getClassMetadata($subClassName); $subClass = $this->_em->getClassMetadata($subClassName);
// Append subclass columns // Regular columns
foreach ($subClass->fieldMappings as $fieldName => $mapping) { foreach ($subClass->fieldMappings as $fieldName => $mapping) {
if ( ! isset($mapping['inherited'])) { if ( ! isset($mapping['inherited'])) {
$columnList .= ', ' . $this->_getSelectColumnSQL($fieldName, $subClass); $columnList .= ', ' . $this->_getSelectColumnSQL($fieldName, $subClass);
} }
} }
// Foreign key columns
// Append subclass foreign keys
foreach ($subClass->associationMappings as $assoc) { foreach ($subClass->associationMappings as $assoc) {
if ($assoc->isOwningSide && $assoc->isOneToOne() && ! $assoc->inherited) { if ($assoc->isOwningSide && $assoc->isOneToOne() && ! $assoc->inherited) {
foreach ($assoc->targetToSourceKeyColumns as $srcColumn) { foreach ($assoc->targetToSourceKeyColumns as $srcColumn) {
...@@ -88,14 +88,27 @@ class SingleTablePersister extends AbstractEntityInheritancePersister ...@@ -88,14 +88,27 @@ class SingleTablePersister extends AbstractEntityInheritancePersister
} }
/** {@inheritdoc} */ /** {@inheritdoc} */
protected function _getSQLTableAlias(ClassMetadata $class) protected function _getSQLTableAlias($className)
{ {
if (isset($this->_sqlTableAliases[$class->rootEntityName])) { return parent::_getSQLTableAlias($this->_class->rootEntityName);
return $this->_sqlTableAliases[$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++; $conditionSql .= $this->_getSQLTableAlias($this->_class->name) . '.'
$this->_sqlTableAliases[$class->rootEntityName] = $tableAlias; . $this->_class->discriminatorColumn['name']
. ' IN (' . implode(', ', $values) . ')';
return $tableAlias; return $conditionSql;
} }
} }
\ No newline at end of file
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
namespace Doctrine\ORM\Persisters; namespace Doctrine\ORM\Persisters;
class UnionSubclassPersister extends StandardEntityPersister class UnionSubclassPersister extends BasicEntityPersister
{ {
} }
\ No newline at end of file
<?php <?php
/* /*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
...@@ -240,7 +238,7 @@ class ProxyFactory ...@@ -240,7 +238,7 @@ class ProxyFactory
return $sleepImpl; return $sleepImpl;
} }
/** Reference Proxy class code template */ /** Proxy class code template */
private static $_proxyClassTemplate = private static $_proxyClassTemplate =
'<?php '<?php
......
<?php <?php
/* /*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
...@@ -31,10 +29,7 @@ namespace Doctrine\ORM\Query\AST; ...@@ -31,10 +29,7 @@ namespace Doctrine\ORM\Query\AST;
* SimpleStateFieldPathExpression ::= IdentificationVariable "." StateField * SimpleStateFieldPathExpression ::= IdentificationVariable "." StateField
* SimpleStateFieldAssociationPathExpression ::= SingleValuedAssociationPathExpression "." StateField * SimpleStateFieldAssociationPathExpression ::= SingleValuedAssociationPathExpression "." StateField
* *
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0 * @since 2.0
* @version $Revision: 3938 $
* @author Guilherme Blanco <guilhermeblanco@hotmail.com> * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com> * @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org> * @author Roman Borschel <roman@code-factory.org>
......
<?php <?php
/* /*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
...@@ -27,10 +25,7 @@ use Doctrine\ORM\Query; ...@@ -27,10 +25,7 @@ use Doctrine\ORM\Query;
* An LL(*) recursive-descent parser for the context-free grammar of the Doctrine Query Language. * An LL(*) recursive-descent parser for the context-free grammar of the Doctrine Query Language.
* Parses a DQL query, reports any errors in it, and generates an AST. * Parses a DQL query, reports any errors in it, and generates an AST.
* *
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0 * @since 2.0
* @version $Revision: 3938 $
* @author Guilherme Blanco <guilhermeblanco@hotmail.com> * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com> * @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org> * @author Roman Borschel <roman@code-factory.org>
...@@ -208,12 +203,15 @@ class Parser ...@@ -208,12 +203,15 @@ class Parser
// Process any deferred validations of some nodes in the AST. // Process any deferred validations of some nodes in the AST.
// This also allows post-processing of the AST for modification purposes. // This also allows post-processing of the AST for modification purposes.
$this->_processDeferredIdentificationVariables(); $this->_processDeferredIdentificationVariables();
if ($this->_deferredPartialObjectExpressions) { if ($this->_deferredPartialObjectExpressions) {
$this->_processDeferredPartialObjectExpressions(); $this->_processDeferredPartialObjectExpressions();
} }
if ($this->_deferredPathExpressions) { if ($this->_deferredPathExpressions) {
$this->_processDeferredPathExpressions($AST); $this->_processDeferredPathExpressions($AST);
} }
if ($this->_deferredResultVariables) { if ($this->_deferredResultVariables) {
$this->_processDeferredResultVariables(); $this->_processDeferredResultVariables();
} }
...@@ -557,11 +555,16 @@ class Parser ...@@ -557,11 +555,16 @@ class Parser
{ {
foreach ($this->_deferredPathExpressions as $deferredItem) { foreach ($this->_deferredPathExpressions as $deferredItem) {
$pathExpression = $deferredItem['expression']; $pathExpression = $deferredItem['expression'];
$parts = $pathExpression->parts;
$numParts = count($parts);
$qComp = $this->_queryComponents[$pathExpression->identificationVariable]; $qComp = $this->_queryComponents[$pathExpression->identificationVariable];
$numParts = count($pathExpression->parts);
if ($numParts == 0) {
$pathExpression->parts = array($qComp['metadata']->identifier[0]);
$numParts++;
}
$parts = $pathExpression->parts;
$aliasIdentificationVariable = $pathExpression->identificationVariable; $aliasIdentificationVariable = $pathExpression->identificationVariable;
$parentField = $pathExpression->identificationVariable; $parentField = $pathExpression->identificationVariable;
$class = $qComp['metadata']; $class = $qComp['metadata'];
...@@ -625,6 +628,7 @@ class Parser ...@@ -625,6 +628,7 @@ class Parser
), ),
null null
); );
$AST->fromClause->identificationVariableDeclarations[0]->joinVariableDeclarations[] = $joinVariableDeclaration; $AST->fromClause->identificationVariableDeclarations[0]->joinVariableDeclarations[] = $joinVariableDeclaration;
$this->_queryComponents[$aliasIdentificationVariable . '.' . $field] = $joinQueryComponent; $this->_queryComponents[$aliasIdentificationVariable . '.' . $field] = $joinQueryComponent;
...@@ -915,12 +919,12 @@ class Parser ...@@ -915,12 +919,12 @@ class Parser
$identVariable = $this->IdentificationVariable(); $identVariable = $this->IdentificationVariable();
$parts = array(); $parts = array();
do { while ($this->_lexer->isNextToken(Lexer::T_DOT)) {
$this->match(Lexer::T_DOT); $this->match(Lexer::T_DOT);
$this->match(Lexer::T_IDENTIFIER); $this->match(Lexer::T_IDENTIFIER);
$parts[] = $this->_lexer->token['value']; $parts[] = $this->_lexer->token['value'];
} while ($this->_lexer->isNextToken(Lexer::T_DOT)); }
// Creating AST node // Creating AST node
$pathExpr = new AST\PathExpression($expectedTypes, $identVariable, $parts); $pathExpr = new AST\PathExpression($expectedTypes, $identVariable, $parts);
...@@ -2168,7 +2172,7 @@ class Parser ...@@ -2168,7 +2172,7 @@ class Parser
return $this->SingleValuedPathExpression(); return $this->SingleValuedPathExpression();
} }
return $this->IdentificationVariable(); return $this->SimpleStateFieldPathExpression();
case Lexer::T_INPUT_PARAMETER: case Lexer::T_INPUT_PARAMETER:
return $this->InputParameter(); return $this->InputParameter();
...@@ -2619,9 +2623,10 @@ class Parser ...@@ -2619,9 +2623,10 @@ class Parser
public function CustomFunctionsReturningNumerics() public function CustomFunctionsReturningNumerics()
{ {
$funcNameLower = strtolower($this->_lexer->lookahead['value']); $funcName = strtolower($this->_lexer->lookahead['value']);
$funcClass = $this->_em->getConfiguration()->getCustomNumericFunction($funcNameLower); // getCustomNumericFunction is case-insensitive
$function = new $funcClass($funcNameLower); $funcClass = $this->_em->getConfiguration()->getCustomNumericFunction($funcName);
$function = new $funcClass($funcName);
$function->parse($this); $function->parse($this);
return $function; return $function;
...@@ -2642,9 +2647,10 @@ class Parser ...@@ -2642,9 +2647,10 @@ class Parser
public function CustomFunctionsReturningDatetime() public function CustomFunctionsReturningDatetime()
{ {
$funcNameLower = strtolower($this->_lexer->lookahead['value']); $funcName = $this->_lexer->lookahead['value'];
$funcClass = $this->_em->getConfiguration()->getCustomDatetimeFunction($funcNameLower); // getCustomDatetimeFunction is case-insensitive
$function = new $funcClass($funcNameLower); $funcClass = $this->_em->getConfiguration()->getCustomDatetimeFunction($funcName);
$function = new $funcClass($funcName);
$function->parse($this); $function->parse($this);
return $function; return $function;
...@@ -2670,9 +2676,10 @@ class Parser ...@@ -2670,9 +2676,10 @@ class Parser
public function CustomFunctionsReturningStrings() public function CustomFunctionsReturningStrings()
{ {
$funcNameLower = strtolower($this->_lexer->lookahead['value']); $funcName = $this->_lexer->lookahead['value'];
$funcClass = $this->_em->getConfiguration()->getCustomStringFunction($funcNameLower); // getCustomStringFunction is case-insensitive
$function = new $funcClass($funcNameLower); $funcClass = $this->_em->getConfiguration()->getCustomStringFunction($funcName);
$function = new $funcClass($funcName);
$function->parse($this); $function->parse($this);
return $function; return $function;
......
<?php <?php
/* /*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
...@@ -240,16 +238,17 @@ class SqlWalker implements TreeWalker ...@@ -240,16 +238,17 @@ class SqlWalker implements TreeWalker
{ {
$sql = ''; $sql = '';
$baseTableAlias = $this->getSqlTableAlias($class->table['name'], $dqlAlias); $baseTableAlias = $this->getSQLTableAlias($class->table['name'], $dqlAlias);
// INNER JOIN parent class tables // INNER JOIN parent class tables
foreach ($class->parentClasses as $parentClassName) { foreach ($class->parentClasses as $parentClassName) {
$parentClass = $this->_em->getClassMetadata($parentClassName); $parentClass = $this->_em->getClassMetadata($parentClassName);
$tableAlias = $this->getSqlTableAlias($parentClass->table['name'], $dqlAlias); $tableAlias = $this->getSQLTableAlias($parentClass->table['name'], $dqlAlias);
$sql .= ' INNER JOIN ' . $parentClass->getQuotedTableName($this->_platform) // 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 '; . ' ' . $tableAlias . ' ON ';
$first = true; $first = true;
foreach ($class->identifier as $idField) { foreach ($class->identifier as $idField) {
if ($first) $first = false; else $sql .= ' AND '; if ($first) $first = false; else $sql .= ' AND ';
...@@ -260,14 +259,13 @@ class SqlWalker implements TreeWalker ...@@ -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)) { if ( ! $this->_query->getHint(Query::HINT_FORCE_PARTIAL_LOAD)) {
foreach ($class->subClasses as $subClassName) { foreach ($class->subClasses as $subClassName) {
$subClass = $this->_em->getClassMetadata($subClassName); $subClass = $this->_em->getClassMetadata($subClassName);
$tableAlias = $this->getSqlTableAlias($subClass->table['name'], $dqlAlias); $tableAlias = $this->getSQLTableAlias($subClass->table['name'], $dqlAlias);
$sql .= ' LEFT JOIN ' . $subClass->getQuotedTableName($this->_platform) $sql .= ' LEFT JOIN ' . $subClass->getQuotedTableName($this->_platform)
. ' ' . $tableAlias . ' ON '; . ' ' . $tableAlias . ' ON ';
$first = true; $first = true;
foreach ($class->identifier as $idField) { foreach ($class->identifier as $idField) {
if ($first) $first = false; else $sql .= ' AND '; if ($first) $first = false; else $sql .= ' AND ';
...@@ -288,9 +286,7 @@ class SqlWalker implements TreeWalker ...@@ -288,9 +286,7 @@ class SqlWalker implements TreeWalker
$sql = ''; $sql = '';
foreach ($this->_selectedClasses AS $dqlAlias => $class) { foreach ($this->_selectedClasses AS $dqlAlias => $class) {
$qComp = $this->_queryComponents[$dqlAlias]; $qComp = $this->_queryComponents[$dqlAlias];
if (isset($qComp['relation']) && ($qComp['relation']->isManyToMany() || $qComp['relation']->isOneToMany()) if (isset($qComp['relation']->orderBy)) {
&& $qComp['relation']->orderBy != null) {
foreach ($qComp['relation']->orderBy AS $fieldName => $orientation) { foreach ($qComp['relation']->orderBy AS $fieldName => $orientation) {
if ($qComp['metadata']->isInheritanceTypeJoined()) { if ($qComp['metadata']->isInheritanceTypeJoined()) {
$tableName = $this->_em->getUnitOfWork()->getEntityPersister($class->name)->getOwningTable($fieldName); $tableName = $this->_em->getUnitOfWork()->getEntityPersister($class->name)->getOwningTable($fieldName);
...@@ -301,8 +297,8 @@ class SqlWalker implements TreeWalker ...@@ -301,8 +297,8 @@ class SqlWalker implements TreeWalker
if ($sql != '') { if ($sql != '') {
$sql .= ', '; $sql .= ', ';
} }
$sql .= $this->getSqlTableAlias($tableName, $dqlAlias) . "." . $sql .= $this->getSqlTableAlias($tableName, $dqlAlias) . '.' .
$qComp['metadata']->getQuotedColumnName($fieldName, $this->_platform) . " ".$orientation; $qComp['metadata']->getQuotedColumnName($fieldName, $this->_platform) . " $orientation";
} }
} }
} }
...@@ -315,7 +311,7 @@ class SqlWalker implements TreeWalker ...@@ -315,7 +311,7 @@ class SqlWalker implements TreeWalker
* @param string $dqlAlias * @param string $dqlAlias
* @return string * @return string
*/ */
private function _generateDiscriminatorColumnConditionSql($dqlAlias) private function _generateDiscriminatorColumnConditionSQL($dqlAlias)
{ {
$sql = ''; $sql = '';
...@@ -340,7 +336,6 @@ class SqlWalker implements TreeWalker ...@@ -340,7 +336,6 @@ class SqlWalker implements TreeWalker
return $sql; return $sql;
} }
/** /**
* Walks down a SelectStatement AST node, thereby generating the appropriate SQL. * Walks down a SelectStatement AST node, thereby generating the appropriate SQL.
* *
...@@ -353,7 +348,7 @@ class SqlWalker implements TreeWalker ...@@ -353,7 +348,7 @@ class SqlWalker implements TreeWalker
if (($whereClause = $AST->whereClause) !== null) { if (($whereClause = $AST->whereClause) !== null) {
$sql .= $this->walkWhereClause($whereClause); $sql .= $this->walkWhereClause($whereClause);
} else if (($discSql = $this->_generateDiscriminatorColumnConditionSql($this->_currentRootAlias)) !== '') { } else if (($discSql = $this->_generateDiscriminatorColumnConditionSQL($this->_currentRootAlias)) !== '') {
$sql .= ' WHERE ' . $discSql; $sql .= ' WHERE ' . $discSql;
} }
...@@ -387,7 +382,7 @@ class SqlWalker implements TreeWalker ...@@ -387,7 +382,7 @@ class SqlWalker implements TreeWalker
if (($whereClause = $AST->whereClause) !== null) { if (($whereClause = $AST->whereClause) !== null) {
$sql .= $this->walkWhereClause($whereClause); $sql .= $this->walkWhereClause($whereClause);
} else if (($discSql = $this->_generateDiscriminatorColumnConditionSql($this->_currentRootAlias)) !== '') { } else if (($discSql = $this->_generateDiscriminatorColumnConditionSQL($this->_currentRootAlias)) !== '') {
$sql .= ' WHERE ' . $discSql; $sql .= ' WHERE ' . $discSql;
} }
...@@ -407,7 +402,7 @@ class SqlWalker implements TreeWalker ...@@ -407,7 +402,7 @@ class SqlWalker implements TreeWalker
if (($whereClause = $AST->whereClause) !== null) { if (($whereClause = $AST->whereClause) !== null) {
$sql .= $this->walkWhereClause($whereClause); $sql .= $this->walkWhereClause($whereClause);
} else if (($discSql = $this->_generateDiscriminatorColumnConditionSql($this->_currentRootAlias)) !== '') { } else if (($discSql = $this->_generateDiscriminatorColumnConditionSQL($this->_currentRootAlias)) !== '') {
$sql .= ' WHERE ' . $discSql; $sql .= ' WHERE ' . $discSql;
} }
...@@ -458,6 +453,7 @@ class SqlWalker implements TreeWalker ...@@ -458,6 +453,7 @@ class SqlWalker implements TreeWalker
$sql .= $class->getQuotedColumnName($fieldName, $this->_platform); $sql .= $class->getQuotedColumnName($fieldName, $this->_platform);
break; break;
case AST\PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION: case AST\PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION:
// 1- the owning side: // 1- the owning side:
// Just use the foreign key, i.e. u.group_id // Just use the foreign key, i.e. u.group_id
...@@ -477,13 +473,18 @@ class SqlWalker implements TreeWalker ...@@ -477,13 +473,18 @@ class SqlWalker implements TreeWalker
if (count($assoc->sourceToTargetKeyColumns) > 1) { if (count($assoc->sourceToTargetKeyColumns) > 1) {
throw QueryException::associationPathCompositeKeyNotSupported(); 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 { } else {
// 2- Inverse side: NOT (YET?) SUPPORTED // 2- Inverse side: NOT (YET?) SUPPORTED
throw QueryException::associationPathInverseSideNotSupported(); throw QueryException::associationPathInverseSideNotSupported();
} }
break; break;
default: default:
throw QueryException::invalidPathExpression($pathExpr); throw QueryException::invalidPathExpression($pathExpr);
} }
...@@ -780,7 +781,7 @@ class SqlWalker implements TreeWalker ...@@ -780,7 +781,7 @@ class SqlWalker implements TreeWalker
). ')'; ). ')';
} }
$discrSql = $this->_generateDiscriminatorColumnConditionSql($joinedDqlAlias); $discrSql = $this->_generateDiscriminatorColumnConditionSQL($joinedDqlAlias);
if ($discrSql) { if ($discrSql) {
$sql .= ' AND ' . $discrSql; $sql .= ' AND ' . $discrSql;
...@@ -1217,7 +1218,7 @@ class SqlWalker implements TreeWalker ...@@ -1217,7 +1218,7 @@ class SqlWalker implements TreeWalker
' OR ', array_map(array($this, 'walkConditionalTerm'), $condExpr->conditionalTerms) ' OR ', array_map(array($this, 'walkConditionalTerm'), $condExpr->conditionalTerms)
); );
$discrSql = $this->_generateDiscriminatorColumnConditionSql($this->_currentRootAlias); $discrSql = $this->_generateDiscriminatorColumnConditionSQL($this->_currentRootAlias);
if ($discrSql) { if ($discrSql) {
$sql .= ' AND ' . $discrSql; $sql .= ' AND ' . $discrSql;
......
...@@ -134,16 +134,16 @@ EOT ...@@ -134,16 +134,16 @@ EOT
} }
$converter = new ConvertDoctrine1Schema($fromPaths); $converter = new ConvertDoctrine1Schema($fromPaths);
$metadatas = $converter->getMetadatas(); $metadata = $converter->getMetadata();
if ($metadatas) { if ($metadatas) {
$output->write(PHP_EOL); $output->write(PHP_EOL);
foreach ($metadatas as $metadata) { foreach ($metadata as $class) {
$output->write(sprintf('Processing entity "<info>%s</info>"', $metadata->name) . PHP_EOL); $output->write(sprintf('Processing entity "<info>%s</info>"', $class->name) . PHP_EOL);
} }
$exporter->setMetadatas($metadatas); $exporter->setMetadata($metadata);
$exporter->export(); $exporter->export();
$output->write(PHP_EOL . sprintf( $output->write(PHP_EOL . sprintf(
......
...@@ -97,8 +97,8 @@ EOT ...@@ -97,8 +97,8 @@ EOT
} }
$cmf = new DisconnectedClassMetadataFactory($em); $cmf = new DisconnectedClassMetadataFactory($em);
$metadatas = $cmf->getAllMetadata(); $metadata = $cmf->getAllMetadata();
$metadatas = MetadataFilter::filter($metadatas, $input->getOption('filter')); $metadata = MetadataFilter::filter($metadata, $input->getOption('filter'));
// Process destination directory // Process destination directory
if ( ! is_dir($destPath = $input->getArgument('dest-path'))) { if ( ! is_dir($destPath = $input->getArgument('dest-path'))) {
...@@ -132,12 +132,12 @@ EOT ...@@ -132,12 +132,12 @@ EOT
} }
} }
if (count($metadatas)) { if (count($metadata)) {
foreach ($metadatas as $metadata) { foreach ($metadata as $class) {
$output->write(sprintf('Processing entity "<info>%s</info>"', $metadata->name) . PHP_EOL); $output->write(sprintf('Processing entity "<info>%s</info>"', $class->name) . PHP_EOL);
} }
$exporter->setMetadatas($metadatas); $exporter->setMetadata($metadata);
$exporter->export(); $exporter->export();
$output->write(PHP_EOL . sprintf( $output->write(PHP_EOL . sprintf(
......
...@@ -113,7 +113,7 @@ EOT ...@@ -113,7 +113,7 @@ EOT
); );
} }
if ( count($metadatas)) { if (count($metadatas)) {
// Create EntityGenerator // Create EntityGenerator
$entityGenerator = new EntityGenerator(); $entityGenerator = new EntityGenerator();
......
...@@ -24,7 +24,8 @@ namespace Doctrine\ORM\Tools\Console\Command; ...@@ -24,7 +24,8 @@ namespace Doctrine\ORM\Tools\Console\Command;
use Symfony\Components\Console\Input\InputArgument, use Symfony\Components\Console\Input\InputArgument,
Symfony\Components\Console\Input\InputOption, Symfony\Components\Console\Input\InputOption,
Symfony\Components\Console, 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. * Command to generate repository classes for mapping information.
...@@ -40,23 +41,6 @@ use Symfony\Components\Console\Input\InputArgument, ...@@ -40,23 +41,6 @@ use Symfony\Components\Console\Input\InputArgument,
*/ */
class GenerateRepositoriesCommand extends Console\Command\Command 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 * @see Console\Command\Command
*/ */
...@@ -103,8 +87,9 @@ EOT ...@@ -103,8 +87,9 @@ EOT
); );
} }
if ( count($metadatas)) { if (count($metadatas)) {
$numRepositories = 0; $numRepositories = 0;
$generator = new EntityRepositoryGenerator();
foreach ($metadatas as $metadata) { foreach ($metadatas as $metadata) {
if ($metadata->customRepositoryClassName) { if ($metadata->customRepositoryClassName) {
...@@ -112,7 +97,7 @@ EOT ...@@ -112,7 +97,7 @@ EOT
sprintf('Processing repository "<info>%s</info>"', $metadata->customRepositoryClassName) . PHP_EOL sprintf('Processing repository "<info>%s</info>"', $metadata->customRepositoryClassName) . PHP_EOL
); );
$this->_generateRepositoryClass($metadata, $destPath); $generator->writeEntityRepositoryClass($metadata->customRepositoryClassName, $destPath);
$numRepositories++; $numRepositories++;
} }
...@@ -128,19 +113,4 @@ EOT ...@@ -128,19 +113,4 @@ EOT
$output->write('No Metadata Classes to process.' . PHP_EOL); $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 ...@@ -41,7 +41,8 @@ class ConvertDoctrine1Schema
private $_legacyTypeMap = array( private $_legacyTypeMap = array(
// TODO: This list may need to be updated // TODO: This list may need to be updated
'clob' => 'text', 'clob' => 'text',
'timestamp' => 'datetime' 'timestamp' => 'datetime',
'enum' => 'string'
); );
/** /**
...@@ -238,6 +239,7 @@ class ConvertDoctrine1Schema ...@@ -238,6 +239,7 @@ class ConvertDoctrine1Schema
if (isset($relation['refClass'])) { if (isset($relation['refClass'])) {
$type = 'many'; $type = 'many';
$foreignType = 'many'; $foreignType = 'many';
$joinColumns = array();
} else { } else {
$type = isset($relation['type']) ? $relation['type'] : 'one'; $type = isset($relation['type']) ? $relation['type'] : 'one';
$foreignType = isset($relation['foreignType']) ? $relation['foreignType'] : 'many'; $foreignType = isset($relation['foreignType']) ? $relation['foreignType'] : 'many';
......
...@@ -98,7 +98,7 @@ class EntityGenerator ...@@ -98,7 +98,7 @@ class EntityGenerator
*/ */
public function <methodName>() public function <methodName>()
{ {
return $this-><fieldName>; <spaces>return $this-><fieldName>;
}'; }';
private static $_setMethodTemplate = private static $_setMethodTemplate =
...@@ -109,7 +109,7 @@ public function <methodName>() ...@@ -109,7 +109,7 @@ public function <methodName>()
*/ */
public function <methodName>(<methodTypeHint>$<variableName>) public function <methodName>(<methodTypeHint>$<variableName>)
{ {
$this-><fieldName> = $<variableName>; <spaces>$this-><fieldName> = $<variableName>;
}'; }';
private static $_addMethodTemplate = private static $_addMethodTemplate =
...@@ -120,7 +120,7 @@ public function <methodName>(<methodTypeHint>$<variableName>) ...@@ -120,7 +120,7 @@ public function <methodName>(<methodTypeHint>$<variableName>)
*/ */
public function <methodName>(<methodTypeHint>$<variableName>) public function <methodName>(<methodTypeHint>$<variableName>)
{ {
$this-><fieldName>[] = $<variableName>; <spaces>$this-><fieldName>[] = $<variableName>;
}'; }';
private static $_lifecycleCallbackMethodTemplate = private static $_lifecycleCallbackMethodTemplate =
...@@ -129,7 +129,7 @@ public function <methodName>(<methodTypeHint>$<variableName>) ...@@ -129,7 +129,7 @@ public function <methodName>(<methodTypeHint>$<variableName>)
*/ */
public function <methodName>() public function <methodName>()
{ {
// Add your code here <spaces>// Add your code here
}'; }';
/** /**
...@@ -203,7 +203,8 @@ public function <methodName>() ...@@ -203,7 +203,8 @@ public function <methodName>()
$this->_generateEntityBody($metadata) $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>() ...@@ -218,9 +219,10 @@ public function <methodName>()
$currentCode = file_get_contents($path); $currentCode = file_get_contents($path);
$body = $this->_generateEntityBody($metadata); $body = $this->_generateEntityBody($metadata);
$body = str_replace('<spaces>', $this->_spaces, $body);
$last = strrpos($currentCode, '}'); $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 ...@@ -63,7 +63,7 @@ class ClassMetadataExporter
* @param string $source The directory where the exporter will export to * @param string $source The directory where the exporter will export to
* @return AbstractExporter $exporter * @return AbstractExporter $exporter
*/ */
public function getExporter($type, $dest) public function getExporter($type, $dest = null)
{ {
if ( ! isset(self::$_exporterDrivers[$type])) { if ( ! isset(self::$_exporterDrivers[$type])) {
throw ExportException::invalidExporterDriverType($type); throw ExportException::invalidExporterDriverType($type);
......
...@@ -49,6 +49,9 @@ class AnnotationExporter extends AbstractExporter ...@@ -49,6 +49,9 @@ class AnnotationExporter extends AbstractExporter
*/ */
public function exportClassMetadata(ClassMetadataInfo $metadata) 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->setGenerateAnnotations(true);
$this->_entityGenerator->setGenerateStubMethods(false); $this->_entityGenerator->setGenerateStubMethods(false);
$this->_entityGenerator->setRegenerateEntityIfExists(false); $this->_entityGenerator->setRegenerateEntityIfExists(false);
......
...@@ -2,8 +2,12 @@ ...@@ -2,8 +2,12 @@
namespace Doctrine\ORM\Tools; namespace Doctrine\ORM\Tools;
class ToolsException extends ORMException { use Doctrine\ORM\ORMException;
public static function couldNotMapDoctrine1Type($type) {
class ToolsException extends ORMException
{
public static function couldNotMapDoctrine1Type($type)
{
return new self("Could not map doctrine 1 type '$type'!"); return new self("Could not map doctrine 1 type '$type'!");
} }
} }
\ No newline at end of file
<?php <?php
/* /*
* $Id: UnitOfWork.php 4947 2008-09-12 13:16:05Z romanb $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
...@@ -33,15 +31,12 @@ use Doctrine\Common\Collections\ArrayCollection, ...@@ -33,15 +31,12 @@ use Doctrine\Common\Collections\ArrayCollection,
* "object-level" transaction and for writing out changes to the database * "object-level" transaction and for writing out changes to the database
* in the correct order. * in the correct order.
* *
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0 * @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de> * @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com> * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com> * @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org> * @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 class UnitOfWork implements PropertyChangedListener
{ {
...@@ -1971,7 +1966,7 @@ class UnitOfWork implements PropertyChangedListener ...@@ -1971,7 +1966,7 @@ class UnitOfWork implements PropertyChangedListener
if ( ! isset($this->_persisters[$entityName])) { if ( ! isset($this->_persisters[$entityName])) {
$class = $this->_em->getClassMetadata($entityName); $class = $this->_em->getClassMetadata($entityName);
if ($class->isInheritanceTypeNone()) { if ($class->isInheritanceTypeNone()) {
$persister = new Persisters\StandardEntityPersister($this->_em, $class); $persister = new Persisters\BasicEntityPersister($this->_em, $class);
} else if ($class->isInheritanceTypeSingleTable()) { } else if ($class->isInheritanceTypeSingleTable()) {
$persister = new Persisters\SingleTablePersister($this->_em, $class); $persister = new Persisters\SingleTablePersister($this->_em, $class);
} else if ($class->isInheritanceTypeJoined()) { } else if ($class->isInheritanceTypeJoined()) {
......
...@@ -488,7 +488,7 @@ class Application ...@@ -488,7 +488,7 @@ class Application
{ {
// namespace // namespace
$namespace = ''; $namespace = '';
if (false !== $pos = strpos($name, ':')) if (false !== $pos = strrpos($name, ':'))
{ {
$namespace = $this->findNamespace(substr($name, 0, $pos)); $namespace = $this->findNamespace(substr($name, 0, $pos));
$name = substr($name, $pos + 1); $name = substr($name, $pos + 1);
......
...@@ -276,7 +276,7 @@ class Command ...@@ -276,7 +276,7 @@ class Command
*/ */
public function setName($name) public function setName($name)
{ {
if (false !== $pos = strpos($name, ':')) if (false !== $pos = strrpos($name, ':'))
{ {
$namespace = substr($name, 0, $pos); $namespace = substr($name, 0, $pos);
$name = substr($name, $pos + 1); $name = substr($name, $pos + 1);
...@@ -375,6 +375,28 @@ class Command ...@@ -375,6 +375,28 @@ class Command
return $this->help; 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. * Sets the aliases for the command.
* *
...@@ -457,7 +479,7 @@ class Command ...@@ -457,7 +479,7 @@ class Command
$messages[] = $this->definition->asText(); $messages[] = $this->definition->asText();
if ($help = $this->getHelp()) if ($help = $this->getProcessedHelp())
{ {
$messages[] = '<comment>Help:</comment>'; $messages[] = '<comment>Help:</comment>';
$messages[] = ' '.implode("\n ", explode("\n", $help))."\n"; $messages[] = ' '.implode("\n ", explode("\n", $help))."\n";
......
...@@ -70,7 +70,7 @@ class ArgvInput extends Input ...@@ -70,7 +70,7 @@ class ArgvInput extends Input
protected function parse() protected function parse()
{ {
$this->parsed = $this->tokens; $this->parsed = $this->tokens;
while ($token = array_shift($this->parsed)) while (null !== ($token = array_shift($this->parsed)))
{ {
if ('--' === substr($token, 0, 2)) if ('--' === substr($token, 0, 2))
{ {
......
...@@ -5,7 +5,7 @@ namespace Doctrine\Tests\Mocks; ...@@ -5,7 +5,7 @@ namespace Doctrine\Tests\Mocks;
/** /**
* EntityPersister implementation used for mocking during tests. * 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 $_inserts = array();
private $_updates = array(); private $_updates = array();
......
...@@ -6,9 +6,9 @@ namespace Doctrine\Tests\Models\Company; ...@@ -6,9 +6,9 @@ namespace Doctrine\Tests\Models\Company;
* @Entity @Table(name="company_events") * @Entity @Table(name="company_events")
* @InheritanceType("JOINED") * @InheritanceType("JOINED")
* @DiscriminatorColumn(name="event_type", type="string") * @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") * @Id @Column(type="integer")
* @GeneratedValue * @GeneratedValue
......
...@@ -294,5 +294,4 @@ class ClassTableInheritanceTest extends \Doctrine\Tests\OrmFunctionalTestCase ...@@ -294,5 +294,4 @@ class ClassTableInheritanceTest extends \Doctrine\Tests\OrmFunctionalTestCase
->getResult()) > 0); ->getResult()) > 0);
} }
} }
...@@ -17,9 +17,10 @@ class ClassTableInheritanceTest2 extends \Doctrine\Tests\OrmFunctionalTestCase ...@@ -17,9 +17,10 @@ class ClassTableInheritanceTest2 extends \Doctrine\Tests\OrmFunctionalTestCase
$this->_schemaTool->createSchema(array( $this->_schemaTool->createSchema(array(
$this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\CTIParent'), $this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\CTIParent'),
$this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\CTIChild'), $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. // Swallow all exceptions. We do not test the schema tool here.
} }
} }
...@@ -49,6 +50,27 @@ class ClassTableInheritanceTest2 extends \Doctrine\Tests\OrmFunctionalTestCase ...@@ -49,6 +50,27 @@ class ClassTableInheritanceTest2 extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertSame($related2, $related2->getCTIParent()->getRelated()); $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 { ...@@ -126,3 +148,29 @@ class CTIRelated {
$this->ctiParent = $ctiParent; $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 ...@@ -66,6 +66,7 @@ class SingleTableInheritanceTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->_em->clear(); $this->_em->clear();
// READ by DQL on subtype
$query = $this->_em->createQuery("select e from Doctrine\Tests\ORM\Functional\ChildEntity e"); $query = $this->_em->createQuery("select e from Doctrine\Tests\ORM\Functional\ChildEntity e");
$entities = $query->getResult(); $entities = $query->getResult();
$this->assertEquals(1, count($entities)); $this->assertEquals(1, count($entities));
...@@ -77,6 +78,18 @@ class SingleTableInheritanceTest extends \Doctrine\Tests\OrmFunctionalTestCase ...@@ -77,6 +78,18 @@ class SingleTableInheritanceTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->_em->clear(); $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"); $query = $this->_em->createQuery("select r,o from Doctrine\Tests\ORM\Functional\RelatedEntity r join r.owner o");
$entities = $query->getResult(); $entities = $query->getResult();
...@@ -194,7 +207,7 @@ class SingleTableInheritanceTest extends \Doctrine\Tests\OrmFunctionalTestCase ...@@ -194,7 +207,7 @@ class SingleTableInheritanceTest extends \Doctrine\Tests\OrmFunctionalTestCase
class ParentEntity { class ParentEntity {
/** /**
* @Id * @Id
* @Column(type="integer") * @Column(name="parent_id", type="integer")
* @GeneratedValue(strategy="AUTO") * @GeneratedValue(strategy="AUTO")
*/ */
private $id; private $id;
...@@ -317,7 +330,7 @@ class ParentRelatedEntity { ...@@ -317,7 +330,7 @@ class ParentRelatedEntity {
public function setData($data) {$this->data = $data;} public function setData($data) {$this->data = $data;}
/** /**
* @OneToOne(targetEntity="ParentEntity") * @OneToOne(targetEntity="ParentEntity")
* @JoinColumn(name="parent_id", referencedColumnName="id") * @JoinColumn(name="parent_id", referencedColumnName="parent_id")
*/ */
private $parent; private $parent;
public function getParent() {return $this->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 @@ ...@@ -3,6 +3,7 @@
namespace Doctrine\Tests\ORM\Mapping; namespace Doctrine\Tests\ORM\Mapping;
use Doctrine\ORM\Mapping\ClassMetadata, use Doctrine\ORM\Mapping\ClassMetadata,
Doctrine\ORM\Mapping\ClassMetadataInfo,
Doctrine\ORM\Mapping\Driver\XmlDriver, Doctrine\ORM\Mapping\Driver\XmlDriver,
Doctrine\ORM\Mapping\Driver\YamlDriver; Doctrine\ORM\Mapping\Driver\YamlDriver;
...@@ -264,4 +265,109 @@ class User ...@@ -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 ...@@ -23,7 +23,8 @@ class AllTests
$suite->addTestSuite('Doctrine\Tests\ORM\Mapping\XmlMappingDriverTest'); $suite->addTestSuite('Doctrine\Tests\ORM\Mapping\XmlMappingDriverTest');
$suite->addTestSuite('Doctrine\Tests\ORM\Mapping\YamlMappingDriverTest'); $suite->addTestSuite('Doctrine\Tests\ORM\Mapping\YamlMappingDriverTest');
$suite->addTestSuite('Doctrine\Tests\ORM\Mapping\AnnotationDriverTest'); $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\ClassMetadataFactoryTest');
$suite->addTestSuite('Doctrine\Tests\ORM\Mapping\ClassMetadataLoadEventTest'); $suite->addTestSuite('Doctrine\Tests\ORM\Mapping\ClassMetadataLoadEventTest');
$suite->addTestSuite('Doctrine\Tests\ORM\Mapping\BasicInheritanceMappingTest'); $suite->addTestSuite('Doctrine\Tests\ORM\Mapping\BasicInheritanceMappingTest');
......
...@@ -20,8 +20,10 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase ...@@ -20,8 +20,10 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase
$this->assertEquals('Doctrine\Tests\Models\CMS\CmsUser', $cm->rootEntityName); $this->assertEquals('Doctrine\Tests\Models\CMS\CmsUser', $cm->rootEntityName);
$this->assertEquals(array(), $cm->subClasses); $this->assertEquals(array(), $cm->subClasses);
$this->assertEquals(array(), $cm->parentClasses); $this->assertEquals(array(), $cm->parentClasses);
$this->assertEquals(ClassMetadata::INHERITANCE_TYPE_NONE, $cm->inheritanceType);
// Customize state // Customize state
$cm->setInheritanceType(ClassMetadata::INHERITANCE_TYPE_SINGLE_TABLE);
$cm->setSubclasses(array("One", "Two", "Three")); $cm->setSubclasses(array("One", "Two", "Three"));
$cm->setParentClasses(array("UserParent")); $cm->setParentClasses(array("UserParent"));
$cm->setCustomRepositoryClass("UserRepository"); $cm->setCustomRepositoryClass("UserRepository");
......
...@@ -3,12 +3,12 @@ ...@@ -3,12 +3,12 @@
namespace Doctrine\Tests\ORM\Mapping; namespace Doctrine\Tests\ORM\Mapping;
use Doctrine\ORM\Mapping\ClassMetadata, use Doctrine\ORM\Mapping\ClassMetadata,
Doctrine\ORM\Mapping\Driver\PhpDriver, Doctrine\ORM\Mapping\Driver\PHPDriver,
Doctrine\ORM\Tools\Export\ClassMetadataExporter; Doctrine\ORM\Tools\Export\ClassMetadataExporter;
require_once __DIR__ . '/../../TestInit.php'; require_once __DIR__ . '/../../TestInit.php';
class PhpMappingDriverTest extends AbstractMappingDriverTest class PHPMappingDriverTest extends AbstractMappingDriverTest
{ {
protected function _loadDriver() protected function _loadDriver()
{ {
...@@ -26,6 +26,6 @@ class PhpMappingDriverTest extends AbstractMappingDriverTest ...@@ -26,6 +26,6 @@ class PhpMappingDriverTest extends AbstractMappingDriverTest
$exporter->export(); $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 ...@@ -156,7 +156,7 @@ class ProxyClassGeneratorTest extends \Doctrine\Tests\OrmTestCase
protected function _getMockPersister() 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; return $persister;
} }
} }
......
...@@ -21,6 +21,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase ...@@ -21,6 +21,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
$query = $this->_em->createQuery($dqlToBeTested); $query = $this->_em->createQuery($dqlToBeTested);
$query->setHint(Query::HINT_FORCE_PARTIAL_LOAD, true) $query->setHint(Query::HINT_FORCE_PARTIAL_LOAD, true)
->useQueryCache(false); ->useQueryCache(false);
parent::assertEquals($sqlToBeConfirmed, $query->getSql()); parent::assertEquals($sqlToBeConfirmed, $query->getSql());
$query->free(); $query->free();
} catch (\Exception $e) { } catch (\Exception $e) {
...@@ -385,7 +386,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase ...@@ -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()); $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( $this->assertSqlGeneration(
// DQL // DQL
...@@ -402,7 +403,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase ...@@ -402,7 +403,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
. ')' . ')'
); );
}*/ }
public function testLimitFromQueryClass() public function testLimitFromQueryClass()
{ {
...@@ -584,4 +585,62 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase ...@@ -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'" "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 ...@@ -159,4 +159,12 @@ class UpdateSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
'UPDATE cms_users SET status = ? WHERE id BETWEEN ? AND ?' '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 ...@@ -15,7 +15,7 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
private static $_queryCacheImpl = null; private static $_queryCacheImpl = null;
/* Shared connection when a TestCase is run alone (outside of it's functional suite) */ /* Shared connection when a TestCase is run alone (outside of it's functional suite) */
private static $_sharedConn; protected static $_sharedConn;
/** /**
* @var \Doctrine\ORM\EntityManager * @var \Doctrine\ORM\EntityManager
...@@ -33,13 +33,13 @@ abstract class OrmFunctionalTestCase extends OrmTestCase ...@@ -33,13 +33,13 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
protected $_sqlLoggerStack; protected $_sqlLoggerStack;
/** The names of the model sets used in this testcase. */ /** The names of the model sets used in this testcase. */
private $_usedModelSets = array(); protected $_usedModelSets = array();
/** Whether the database schema has already been created. */ /** Whether the database schema has already been created. */
private static $_tablesCreated = array(); protected static $_tablesCreated = array();
/** List of model sets and their classes. */ /** List of model sets and their classes. */
private static $_modelSets = array( protected static $_modelSets = array(
'cms' => array( 'cms' => array(
'Doctrine\Tests\Models\CMS\CmsUser', 'Doctrine\Tests\Models\CMS\CmsUser',
'Doctrine\Tests\Models\CMS\CmsPhonenumber', 'Doctrine\Tests\Models\CMS\CmsPhonenumber',
...@@ -170,11 +170,11 @@ abstract class OrmFunctionalTestCase extends OrmTestCase ...@@ -170,11 +170,11 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
$forceCreateTables = false; $forceCreateTables = false;
if ( ! isset($this->sharedFixture['conn'])) { if ( ! isset($this->sharedFixture['conn'])) {
if ( ! isset(self::$_sharedConn)) { if ( ! isset(static::$_sharedConn)) {
self::$_sharedConn = TestUtil::getConnection(); 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) { if ($this->sharedFixture['conn']->getDriver() instanceof \Doctrine\DBAL\Driver\PDOSqlite\Driver) {
$forceCreateTables = true; $forceCreateTables = true;
...@@ -189,12 +189,12 @@ abstract class OrmFunctionalTestCase extends OrmTestCase ...@@ -189,12 +189,12 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
$classes = array(); $classes = array();
foreach ($this->_usedModelSets as $setName => $bool) { foreach ($this->_usedModelSets as $setName => $bool) {
if ( ! isset(self::$_tablesCreated[$setName])/* || $forceCreateTables*/) { if ( ! isset(static::$_tablesCreated[$setName])/* || $forceCreateTables*/) {
foreach (self::$_modelSets[$setName] as $className) { foreach (static::$_modelSets[$setName] as $className) {
$classes[] = $this->_em->getClassMetadata($className); $classes[] = $this->_em->getClassMetadata($className);
} }
self::$_tablesCreated[$setName] = true; static::$_tablesCreated[$setName] = true;
} }
} }
......
...@@ -23,7 +23,7 @@ $connectionOptions = array( ...@@ -23,7 +23,7 @@ $connectionOptions = array(
$em = \Doctrine\ORM\EntityManager::create($connectionOptions, $config); $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()), 'db' => new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper($em->getConnection()),
'em' => new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($em) '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'; ...@@ -13,7 +13,10 @@ require __DIR__ . '/cli-config.php';
$cli = new \Symfony\Components\Console\Application('Doctrine Command Line Interface', Doctrine\Common\Version::VERSION); $cli = new \Symfony\Components\Console\Application('Doctrine Command Line Interface', Doctrine\Common\Version::VERSION);
$cli->setCatchExceptions(true); $cli->setCatchExceptions(true);
$cli->setHelperSet($helperSet); $helperSet = $cli->getHelperSet();
foreach ($helpers as $name => $helper) {
$helperSet->set($helper, $name);
}
$cli->addCommands(array( $cli->addCommands(array(
// DBAL Commands // DBAL Commands
new \Doctrine\DBAL\Tools\Console\Command\RunSqlCommand(), 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