[2.0][DDC-122][DDC-97][DDC-98][DDC-147] Refactored metadata mapping drivers by removing the useless PRELOAD mode. Introduced ClassMetadataFactory#getAllMetadata. Classloader simplifications. Old classloaders deprecated. New Doctrine\Common\ClassLoader is almost the same as the previous IsolatedClassLoader.
This commit is contained in:
parent
371761108d
commit
fe7ef4bbeb
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
|
||||
require 'Doctrine/Common/GlobalClassLoader.php';
|
||||
require 'Doctrine/Common/ClassLoader.php';
|
||||
|
||||
$classLoader = new \Doctrine\Common\GlobalClassLoader();
|
||||
$classLoader = new \Doctrine\Common\ClassLoader();
|
||||
$classLoader->register();
|
||||
|
||||
$cli = new \Doctrine\ORM\Tools\Cli\CliController();
|
||||
|
149
lib/Doctrine/Common/ClassLoader.php
Normal file
149
lib/Doctrine/Common/ClassLoader.php
Normal file
@ -0,0 +1,149 @@
|
||||
<?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\Common;
|
||||
|
||||
/**
|
||||
* A <tt>ClassLoader</tt> is an autoloader for class files that can be
|
||||
* installed on the SPL autoload stack. It is a class loader that loads only classes
|
||||
* of a specific namespace or all namespaces and is suitable for working together
|
||||
* with other autoloaders in the SPL autoload stack.
|
||||
*
|
||||
* If no include path is configured through {@link setIncludePath}, a ClassLoader
|
||||
* relies on the PHP include_path.
|
||||
*
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @since 2.0
|
||||
*/
|
||||
class ClassLoader
|
||||
{
|
||||
private $_fileExtension = '.php';
|
||||
private $_namespace;
|
||||
private $_includePath;
|
||||
private $_namespaceSeparator = '\\';
|
||||
|
||||
/**
|
||||
* Creates a new <tt>ClassLoader</tt> that loads classes of the
|
||||
* specified namespace.
|
||||
*
|
||||
* @param string $ns The namespace to use.
|
||||
*/
|
||||
public function __construct($ns = null, $includePath = null)
|
||||
{
|
||||
$this->_namespace = $ns;
|
||||
$this->_includePath = $includePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the namespace separator used by classes in the namespace of this class loader.
|
||||
*
|
||||
* @param string $sep The separator to use.
|
||||
*/
|
||||
public function setNamespaceSeparator($sep)
|
||||
{
|
||||
$this->_namespaceSeparator = $sep;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the namespace separator used by classes in the namespace of this class loader.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getNamespaceSeparator()
|
||||
{
|
||||
return $this->_namespaceSeparator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the base include path for all class files in the namespace of this class loader.
|
||||
*
|
||||
* @param string $includePath
|
||||
*/
|
||||
public function setIncludePath($includePath)
|
||||
{
|
||||
$this->_includePath = $includePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the base include path for all class files in the namespace of this class loader.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getIncludePath()
|
||||
{
|
||||
return $this->_includePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the file extension of class files in the namespace of this class loader.
|
||||
*
|
||||
* @param string $fileExtension
|
||||
*/
|
||||
public function setFileExtension($fileExtension)
|
||||
{
|
||||
$this->_fileExtension = $fileExtension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the file extension of class files in the namespace of this class loader.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFileExtension()
|
||||
{
|
||||
return $this->_fileExtension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Installs this class loader on the SPL autoload stack.
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
spl_autoload_register(array($this, 'loadClass'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Uninstalls this class loader on the SPL autoload stack.
|
||||
*/
|
||||
public function unregister()
|
||||
{
|
||||
spl_autoload_unregister(array($this, 'loadClass'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the given class or interface.
|
||||
*
|
||||
* @param string $classname The name of the class to load.
|
||||
* @return boolean TRUE if the class has been successfully loaded, FALSE otherwise.
|
||||
*/
|
||||
public function loadClass($className)
|
||||
{
|
||||
if ($this->_namespace !== null && strpos($className, $this->_namespace.$this->_namespaceSeparator) !== 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
require ($this->_includePath !== null ? $this->_includePath . DIRECTORY_SEPARATOR : '')
|
||||
. str_replace($this->_namespaceSeparator, DIRECTORY_SEPARATOR, $className)
|
||||
. $this->_fileExtension;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@ -31,6 +31,7 @@ namespace Doctrine\Common;
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @author Jonathan Wage <jonwage@gmail.com>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @todo Remove
|
||||
*/
|
||||
class DoctrineException extends \Exception
|
||||
{
|
||||
|
@ -46,6 +46,8 @@ namespace Doctrine\Common;
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @author Jonathan Wage <jonwage@gmail.com>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
*
|
||||
* @deprecated Use Doctrine\Common\ClassLoader instead.
|
||||
*/
|
||||
class GlobalClassLoader
|
||||
{
|
||||
|
@ -31,6 +31,8 @@ namespace Doctrine\Common;
|
||||
*
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @since 2.0
|
||||
*
|
||||
* @deprecated Use Doctrine\Common\ClassLoader instead.
|
||||
*/
|
||||
class IsolatedClassLoader
|
||||
{
|
||||
|
@ -36,8 +36,12 @@ namespace Doctrine\Common;
|
||||
interface PropertyChangedListener
|
||||
{
|
||||
/**
|
||||
* @todo Document this function
|
||||
* Notifies the listener of a property change.
|
||||
*
|
||||
* @param object $sender The object on which the property changed.
|
||||
* @param string $propertyName The name of the property that changed.
|
||||
* @param mixed $oldValue The old value of the property that changed.
|
||||
* @param mixed $newValue The new value of the property that changed.
|
||||
*/
|
||||
function propertyChanged($sender, $propertyName, $oldValue, $newValue);
|
||||
}
|
||||
|
@ -179,9 +179,9 @@ class Connection
|
||||
|
||||
$this->_config = $config;
|
||||
$this->_eventManager = $eventManager;
|
||||
if (!isset($params['platform'])) {
|
||||
if ( ! isset($params['platform'])) {
|
||||
$this->_platform = $driver->getDatabasePlatform();
|
||||
} else if($params['platform'] instanceof \Doctrine\DBAL\Platforms\AbstractPlatform) {
|
||||
} else if ($params['platform'] instanceof Platforms\AbstractPlatform) {
|
||||
$this->_platform = $params['platform'];
|
||||
} else {
|
||||
throw DBALException::invalidPlatformSpecified();
|
||||
@ -632,7 +632,7 @@ class Connection
|
||||
/**
|
||||
* Returns the current transaction nesting level.
|
||||
*
|
||||
* @return integer The nesting level. A value of 0 means theres no active transaction.
|
||||
* @return integer The nesting level. A value of 0 means theres no active transaction.
|
||||
*/
|
||||
public function getTransactionNestingLevel()
|
||||
{
|
||||
|
@ -111,6 +111,8 @@ class Configuration extends \Doctrine\DBAL\Configuration
|
||||
* Sets the cache driver implementation that is used for metadata caching.
|
||||
*
|
||||
* @param object $driverImpl
|
||||
* @todo Force parameter to be a Closure to ensure lazy evaluation
|
||||
* (as soon as a metadata cache is in effect, the driver never needs to initialize).
|
||||
*/
|
||||
public function setMetadataDriverImpl($driverImpl)
|
||||
{
|
||||
|
@ -210,7 +210,7 @@ class EntityManager
|
||||
* @internal Performance-sensitive method.
|
||||
*/
|
||||
public function getClassMetadata($className)
|
||||
{
|
||||
{
|
||||
return $this->_metadataFactory->getMetadataFor($className);
|
||||
}
|
||||
|
||||
|
@ -89,6 +89,7 @@ class EntityRepository
|
||||
}
|
||||
|
||||
if ( ! is_array($id) || count($id) <= 1) {
|
||||
//FIXME: Not correct. Relies on specific order.
|
||||
$value = is_array($id) ? array_values($id) : array($id);
|
||||
$id = array_combine($this->_class->identifier, $value);
|
||||
}
|
||||
|
@ -50,6 +50,7 @@ class ClassMetadataFactory
|
||||
/** The used cache driver. */
|
||||
private $_cacheDriver;
|
||||
private $_loadedMetadata = array();
|
||||
private $_initialized = false;
|
||||
|
||||
/**
|
||||
* Creates a new factory instance that uses the given metadata driver implementation.
|
||||
@ -59,24 +60,16 @@ class ClassMetadataFactory
|
||||
public function __construct(\Doctrine\ORM\EntityManager $em)
|
||||
{
|
||||
$this->_em = $em;
|
||||
$this->_driver = $em->getConfiguration()->getMetadataDriverImpl();
|
||||
$this->_targetPlatform = $em->getConnection()->getDatabasePlatform();
|
||||
$this->_evm = $em->getEventManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cache driver used by the factory to cache ClassMetadata instances
|
||||
* and invokes the preload() method of the metadata driver to prepopulate the cache.
|
||||
* Sets the cache driver used by the factory to cache ClassMetadata instances.
|
||||
*
|
||||
* @param Doctrine\Common\Cache\Cache $cacheDriver
|
||||
*/
|
||||
public function setCacheDriver($cacheDriver)
|
||||
{
|
||||
$this->_cacheDriver = $cacheDriver;
|
||||
foreach ($this->_driver->preload() as $className) {
|
||||
$cacheKey = "$className\$CLASSMETADATA";
|
||||
$this->_cacheDriver->save($cacheKey, $this->getMetadataFor($className), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -93,6 +86,38 @@ class ClassMetadataFactory
|
||||
{
|
||||
return $this->_loadedMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces the factory to load the metadata of all classes known to the underlying
|
||||
* mapping driver.
|
||||
*
|
||||
* @return array The ClassMetadata instances of all mapped classes.
|
||||
*/
|
||||
public function getAllMetadata()
|
||||
{
|
||||
if ( ! $this->_initialized) {
|
||||
$this->_initialize();
|
||||
}
|
||||
|
||||
$metadata = array();
|
||||
foreach ($this->_driver->getAllClassNames() as $className) {
|
||||
$metadata[] = $this->getMetadataFor($className);
|
||||
}
|
||||
|
||||
return $metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazy initialization of this stuff, especially the metadata driver,
|
||||
* since these are not needed at all when a metadata cache is active.
|
||||
*/
|
||||
private function _initialize()
|
||||
{
|
||||
$this->_driver = $this->_em->getConfiguration()->getMetadataDriverImpl();
|
||||
$this->_targetPlatform = $this->_em->getConnection()->getDatabasePlatform();
|
||||
$this->_evm = $this->_em->getEventManager();
|
||||
$this->_initialized = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the class metadata descriptor for a class.
|
||||
@ -121,9 +146,10 @@ class ClassMetadataFactory
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the factory has the metadata for a class loaded already.
|
||||
*
|
||||
* @param $className
|
||||
* @return boolean
|
||||
* @param string $className
|
||||
* @return boolean TRUE if the metadata of the class in question is already loaded, FALSE otherwise.
|
||||
*/
|
||||
public function hasMetadataFor($className)
|
||||
{
|
||||
@ -152,6 +178,10 @@ class ClassMetadataFactory
|
||||
*/
|
||||
protected function _loadMetadata($name)
|
||||
{
|
||||
if ( ! $this->_initialized) {
|
||||
$this->_initialize();
|
||||
}
|
||||
|
||||
$loaded = array();
|
||||
|
||||
// Collect parent classes, ignoring transient (not-mapped) classes.
|
||||
|
@ -25,40 +25,21 @@ use Doctrine\ORM\Mapping\MappingException;
|
||||
|
||||
/**
|
||||
* Base driver for file-based metadata drivers.
|
||||
*
|
||||
* A file driver operates in a mode where it loads the mapping files of individual
|
||||
* classes on demand. This requires the user to adhere to the convention of 1 mapping
|
||||
* file per class and the file names of the mapping files must correspond to the full
|
||||
* class name, including namespace, with the namespace delimiters '\', replaced by dots '.'.
|
||||
*
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.doctrine-project.com
|
||||
* @since 2.0
|
||||
* @version $Revision: 1393 $
|
||||
* @author Jonathan H. Wage <jonwage@gmail.com>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
*/
|
||||
abstract class AbstractFileDriver implements Driver
|
||||
{
|
||||
/**
|
||||
* The FILE_PER_CLASS mode is an operating mode of the FileDriver where it loads
|
||||
* the mapping files of individual classes on demand. This requires the user to
|
||||
* adhere to the convention of 1 mapping file per class and the file names of
|
||||
* the mapping files must correspond to the full class name, including namespace,
|
||||
* with the namespace delimiters '\', replaced by dots '.'.
|
||||
* This is the default behavior.
|
||||
*
|
||||
* Example:
|
||||
* Class: My\Project\Model\User
|
||||
* Mapping file: My.Project.Model.User.dcm.xml
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
const FILE_PER_CLASS = 1;
|
||||
|
||||
/**
|
||||
* The PRELOAD mode is an operating mode of the FileDriver where it loads
|
||||
* all mapping files in advance. It does not require a naming convention
|
||||
* or the convention of 1 class per mapping file.
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
const PRELOAD = 2;
|
||||
|
||||
/**
|
||||
* The paths where to look for mapping files.
|
||||
*
|
||||
@ -66,13 +47,6 @@ abstract class AbstractFileDriver implements Driver
|
||||
*/
|
||||
protected $_paths;
|
||||
|
||||
/**
|
||||
* The operating mode. Either FILE_PER_CLASS or PRELOAD.
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
protected $_mode;
|
||||
|
||||
/**
|
||||
* The file extension of mapping documents.
|
||||
*
|
||||
@ -80,24 +54,15 @@ abstract class AbstractFileDriver implements Driver
|
||||
*/
|
||||
protected $_fileExtension;
|
||||
|
||||
/**
|
||||
* Any preloaded elements.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_elements = array();
|
||||
|
||||
/**
|
||||
* Initializes a new FileDriver that looks in the given path(s) for mapping
|
||||
* documents and operates in the specified operating mode.
|
||||
*
|
||||
* @param string|array $paths One or multiple paths where mapping documents can be found.
|
||||
* @param integer $mode The operating mode. Either PRELOAD or FILE_PER_CLASS (default).
|
||||
*/
|
||||
public function __construct($paths, $mode = self::FILE_PER_CLASS)
|
||||
public function __construct($paths)
|
||||
{
|
||||
$this->_paths = (array) $paths;
|
||||
$this->_mode = $mode;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -129,24 +94,8 @@ abstract class AbstractFileDriver implements Driver
|
||||
*/
|
||||
public function getElement($className)
|
||||
{
|
||||
if (isset($this->_elements[$className])) {
|
||||
$element = $this->_elements[$className];
|
||||
unset($this->_elements[$className]);
|
||||
return $element;
|
||||
} else {
|
||||
$result = $this->_loadMappingFile($this->_findMappingFile($className));
|
||||
return $result[$className];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets any preloaded elements.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getPreloadedElements()
|
||||
{
|
||||
return $this->_elements;
|
||||
$result = $this->_loadMappingFile($this->_findMappingFile($className));
|
||||
return $result[$className];
|
||||
}
|
||||
|
||||
/**
|
||||
@ -160,45 +109,37 @@ abstract class AbstractFileDriver implements Driver
|
||||
public function isTransient($className)
|
||||
{
|
||||
$isTransient = true;
|
||||
if ($this->_mode == self::FILE_PER_CLASS) {
|
||||
// check whether file exists
|
||||
foreach ((array)$this->_paths as $path) {
|
||||
if (file_exists($path . DIRECTORY_SEPARATOR . str_replace('\\', '.', $className) . $this->_fileExtension)) {
|
||||
$isTransient = false;
|
||||
break;
|
||||
}
|
||||
// check whether file exists
|
||||
foreach ((array)$this->_paths as $path) {
|
||||
if (file_exists($path . DIRECTORY_SEPARATOR . str_replace('\\', '.', $className) . $this->_fileExtension)) {
|
||||
$isTransient = false;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
$isTransient = isset($this->_elements[$className]);
|
||||
}
|
||||
|
||||
return $isTransient;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Preloads all mapping information found in any documents within the
|
||||
* configured paths and returns a list of class names that have been preloaded.
|
||||
* Gets the names of all mapped classes known to this driver.
|
||||
*
|
||||
* @return array The list of class names that have been preloaded.
|
||||
* @return array The names of all mapped classes known to this driver.
|
||||
*/
|
||||
public function preload($force = false)
|
||||
public function getAllClassNames()
|
||||
{
|
||||
if ($this->_mode != self::PRELOAD && ! $force) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$clasNames = array();
|
||||
foreach ((array)$this->_paths as $path) {
|
||||
if (is_dir($path)) {
|
||||
$files = glob($path . '/*');
|
||||
foreach ($files as $file) {
|
||||
$this->_elements = array_merge($this->_elements, $this->_loadMappingFile($file));
|
||||
$classNames[] = str_replace(array($this->_fileExtension, '.'), array('', '\\'), basename($file));
|
||||
}
|
||||
} else if (is_file($path)) {
|
||||
$this->_elements = array_merge($this->_elements, $this->_loadMappingFile($path));
|
||||
$classNames[] = str_replace(array($this->_fileExtension, '.'), array('', '\\'), basename($file));
|
||||
}
|
||||
}
|
||||
|
||||
return array_keys($this->_elements);
|
||||
return $classNames;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -336,16 +336,19 @@ class AnnotationDriver implements Driver
|
||||
! isset($classAnnotations['Doctrine\ORM\Mapping\MappedSuperclass']);
|
||||
}
|
||||
|
||||
public function preload()
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getAllClassNames()
|
||||
{
|
||||
if ($this->_classDirectory) {
|
||||
$iter = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->_classDirectory),
|
||||
\RecursiveIteratorIterator::LEAVES_ONLY);
|
||||
\RecursiveIteratorIterator::LEAVES_ONLY);
|
||||
|
||||
$declared = get_declared_classes();
|
||||
foreach ($iter as $item) {
|
||||
$info = pathinfo($item->getPathName());
|
||||
if (! isset($info['extension']) || $info['extension'] != 'php') {
|
||||
if ( ! isset($info['extension']) || $info['extension'] != 'php') {
|
||||
continue;
|
||||
}
|
||||
require_once $item->getPathName();
|
||||
@ -363,4 +366,5 @@ class AnnotationDriver implements Driver
|
||||
return array();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -38,7 +38,6 @@ use Doctrine\Common\DoctrineException,
|
||||
* @version $Revision$
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @author Jonathan Wage <jonwage@gmail.com>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
*/
|
||||
class DatabaseDriver implements Driver
|
||||
{
|
||||
@ -170,12 +169,9 @@ class DatabaseDriver implements Driver
|
||||
}
|
||||
|
||||
/**
|
||||
* Preloads all mapping information found in any documents within the
|
||||
* configured paths and returns a list of class names that have been preloaded.
|
||||
*
|
||||
* @return array The list of class names that have been preloaded.
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function preload()
|
||||
public function getAllClassNames()
|
||||
{
|
||||
$tables = array();
|
||||
foreach ($this->_sm->listTables() as $table) {
|
||||
|
@ -40,7 +40,14 @@ interface Driver
|
||||
* @param string $className
|
||||
* @param ClassMetadataInfo $metadata
|
||||
*/
|
||||
public function loadMetadataForClass($className, ClassMetadataInfo $metadata);
|
||||
function loadMetadataForClass($className, ClassMetadataInfo $metadata);
|
||||
|
||||
/**
|
||||
* Gets the names of all mapped classes known to this driver.
|
||||
*
|
||||
* @return array The names of all mapped classes known to this driver.
|
||||
*/
|
||||
function getAllClassNames();
|
||||
|
||||
/**
|
||||
* Whether the class with the specified name should have its metadata loaded.
|
||||
@ -50,5 +57,5 @@ interface Driver
|
||||
* @param string $className
|
||||
* @return boolean
|
||||
*/
|
||||
public function isTransient($className);
|
||||
function isTransient($className);
|
||||
}
|
@ -66,23 +66,20 @@ class PhpDriver implements Driver
|
||||
}
|
||||
|
||||
/**
|
||||
* Preloads all mapping information found in any documents within the
|
||||
* configured paths and returns a list of class names that have been preloaded.
|
||||
*
|
||||
* @return array The list of class names that have been preloaded.
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function preload()
|
||||
public function getAllClassNames()
|
||||
{
|
||||
if ( ! is_dir($this->_directory)) {
|
||||
throw MappingException::phpDriverRequiresConfiguredDirectoryPath();
|
||||
}
|
||||
$iter = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->_directory),
|
||||
\RecursiveIteratorIterator::LEAVES_ONLY);
|
||||
\RecursiveIteratorIterator::LEAVES_ONLY);
|
||||
|
||||
$classes = array();
|
||||
foreach ($iter as $item) {
|
||||
$info = pathinfo($item->getPathName());
|
||||
if (! isset($info['extension']) || $info['extension'] != 'php') {
|
||||
if ( ! isset($info['extension']) || $info['extension'] != 'php') {
|
||||
continue;
|
||||
}
|
||||
$className = $info['filename'];
|
||||
|
@ -225,6 +225,11 @@ class OneToOneMapping extends AssociationMapping
|
||||
if ($inverseField) {
|
||||
$hints['fetched'][$targetClass->rootEntityName][$inverseField] = 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);
|
||||
|
||||
|
@ -21,8 +21,8 @@
|
||||
|
||||
namespace Doctrine\ORM\Persisters;
|
||||
|
||||
use Doctrine\ORM\EntityManager;
|
||||
use Doctrine\ORM\PersistentCollection;
|
||||
use Doctrine\ORM\EntityManager,
|
||||
Doctrine\ORM\PersistentCollection;
|
||||
|
||||
/**
|
||||
* Base class for all collection persisters.
|
||||
|
@ -600,7 +600,7 @@ class StandardEntityPersister
|
||||
* @param $result The SQL result.
|
||||
* @param object $entity The entity object to fill.
|
||||
* @param array $hints Hints for entity creation.
|
||||
* @return object The filled and managed entity object.
|
||||
* @return object The filled and managed entity object or NULL, if the SQL result is empty.
|
||||
*/
|
||||
private function _createEntity($result, $entity = null, array $hints = array())
|
||||
{
|
||||
|
@ -67,14 +67,8 @@ class GenerateProxiesTask extends AbstractTask
|
||||
|
||||
$em = $this->getEntityManager();
|
||||
$cmf = $em->getMetadataFactory();
|
||||
$driver = $em->getConfiguration()->getMetadataDriverImpl();
|
||||
|
||||
$classes = array();
|
||||
$preloadedClasses = $driver->preload(true);
|
||||
|
||||
foreach ($preloadedClasses as $className) {
|
||||
$classes[] = $cmf->getMetadataFor($className);
|
||||
}
|
||||
$classes = $cmf->getAllMetadata();
|
||||
|
||||
$printer = $this->getPrinter();
|
||||
$factory = $em->getProxyFactory();
|
||||
|
@ -158,14 +158,8 @@ class SchemaToolTask extends AbstractTask
|
||||
|
||||
$em = $this->getEntityManager();
|
||||
$cmf = $em->getMetadataFactory();
|
||||
$driver = $em->getConfiguration()->getMetadataDriverImpl();
|
||||
|
||||
$classes = array();
|
||||
$preloadedClasses = $driver->preload(true);
|
||||
|
||||
foreach ($preloadedClasses as $className) {
|
||||
$classes[] = $cmf->getMetadataFor($className);
|
||||
}
|
||||
$classes = $cmf->getAllMetadata();
|
||||
|
||||
$printer = $this->getPrinter();
|
||||
|
||||
|
@ -113,7 +113,7 @@ class ClassMetadataExporter
|
||||
if (is_null($source)) {
|
||||
throw DoctrineException::fileMappingDriversRequireDirectoryPath();
|
||||
}
|
||||
$driver = new $class($source, constant($class . '::PRELOAD'));
|
||||
$driver = new $class($source);
|
||||
} else if ($class == 'Doctrine\ORM\Mapping\Driver\AnnotationDriver') {
|
||||
$reader = new \Doctrine\Common\Annotations\AnnotationReader(new \Doctrine\Common\Cache\ArrayCache);
|
||||
$reader->setDefaultAnnotationNamespace('Doctrine\ORM\Mapping\\');
|
||||
@ -148,8 +148,8 @@ class ClassMetadataExporter
|
||||
foreach ($this->_mappingSources as $d) {
|
||||
list($source, $driver) = $d;
|
||||
|
||||
$preloadedClasses = $driver->preload(true);
|
||||
foreach ($preloadedClasses as $className) {
|
||||
$allClasses = $driver->getAllClassNames();
|
||||
foreach ($allClasses as $className) {
|
||||
if (class_exists($className, false)) {
|
||||
$metadata = new ClassMetadata($className);
|
||||
} else {
|
||||
|
@ -223,6 +223,8 @@ class UnitOfWork implements PropertyChangedListener
|
||||
* @var array
|
||||
*/
|
||||
private $_orphanRemovals = array();
|
||||
|
||||
//private $_readOnlyObjects = array();
|
||||
|
||||
/**
|
||||
* Initializes a new UnitOfWork instance, bound to the given EntityManager.
|
||||
@ -395,7 +397,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
$class = $this->_em->getClassMetadata($className);
|
||||
|
||||
// Skip class if change tracking happens through notification
|
||||
if ($class->isChangeTrackingNotify()) {
|
||||
if ($class->isChangeTrackingNotify() /* || $class->isReadOnly*/) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -405,7 +407,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
|
||||
foreach ($entitiesToProcess as $entity) {
|
||||
// Ignore uninitialized proxy objects
|
||||
if ($entity instanceof Proxy && ! $entity->__isInitialized__()) {
|
||||
if (/* $entity is readOnly || */ $entity instanceof Proxy && ! $entity->__isInitialized__()) {
|
||||
continue;
|
||||
}
|
||||
// Only MANAGED entities that are NOT SCHEDULED FOR INSERTION are processed here.
|
||||
@ -1695,15 +1697,18 @@ class UnitOfWork implements PropertyChangedListener
|
||||
* Creates an entity. Used for reconstitution of entities during hydration.
|
||||
*
|
||||
* @ignore
|
||||
* @param string $className The name of the entity class.
|
||||
* @param array $data The data for the entity.
|
||||
* @return object The created entity instance.
|
||||
* @param string $className The name of the entity class.
|
||||
* @param array $data The data for the entity.
|
||||
* @param array $hints Any hints to account for during reconstitution/lookup of the entity.
|
||||
* @return object The entity instance.
|
||||
* @internal Highly performance-sensitive method.
|
||||
*
|
||||
* @todo Rename: getOrCreateEntity
|
||||
*/
|
||||
public function createEntity($className, array $data, &$hints = array())
|
||||
{
|
||||
$class = $this->_em->getClassMetadata($className);
|
||||
//$isReadOnly = isset($hints[Query::HINT_READ_ONLY]);
|
||||
|
||||
if ($class->isIdentifierComposite) {
|
||||
$id = array();
|
||||
@ -1765,9 +1770,11 @@ class UnitOfWork implements PropertyChangedListener
|
||||
}
|
||||
}
|
||||
if ( ! $associatedId) {
|
||||
// Foreign key is NULL
|
||||
$class->reflFields[$field]->setValue($entity, null);
|
||||
$this->_originalEntityData[$oid][$field] = null;
|
||||
} else {
|
||||
// Foreign key is set
|
||||
// Check identity map first
|
||||
// FIXME: Can break easily with composite keys if join column values are in
|
||||
// wrong order. The correct order is the one in ClassMetadata#identifier.
|
||||
@ -1788,15 +1795,15 @@ class UnitOfWork implements PropertyChangedListener
|
||||
$class->reflFields[$field]->setValue($entity, $newValue);
|
||||
}
|
||||
} else {
|
||||
// Inverse side can never be lazy
|
||||
$targetEntity = $assoc->load($entity, null, $this->_em);
|
||||
$class->reflFields[$field]->setValue($entity, $targetEntity);
|
||||
// Inverse side of x-to-one can never be lazy
|
||||
$class->reflFields[$field]->setValue($entity, $assoc->load($entity, null, $this->_em));
|
||||
}
|
||||
} else {
|
||||
// Inject collection
|
||||
$reflField = $class->reflFields[$field];
|
||||
$pColl = new PersistentCollection(
|
||||
$this->_em, $targetClass,
|
||||
//TODO: getValue might be superfluous once DDC-79 is implemented.
|
||||
$reflField->getValue($entity) ?: new ArrayCollection
|
||||
);
|
||||
$pColl->setOwner($entity, $assoc);
|
||||
|
@ -2,9 +2,9 @@
|
||||
|
||||
namespace Doctrine\Tests\Mocks;
|
||||
|
||||
class MetadataDriverMock
|
||||
class MetadataDriverMock implements \Doctrine\ORM\Mapping\Driver\Driver
|
||||
{
|
||||
public function loadMetadataForClass($className, \Doctrine\ORM\Mapping\ClassMetadata $metadata)
|
||||
public function loadMetadataForClass($className, \Doctrine\ORM\Mapping\ClassMetadataInfo $metadata)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -14,7 +14,7 @@ class MetadataDriverMock
|
||||
return false;
|
||||
}
|
||||
|
||||
public function preload()
|
||||
public function getAllClassNames()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ class MappingDriverTest extends \Doctrine\Tests\OrmTestCase
|
||||
public function testXmlMapping()
|
||||
{
|
||||
$className = 'Doctrine\Tests\ORM\Mapping\User';
|
||||
$xmlDriver = new XmlDriver(__DIR__ . DIRECTORY_SEPARATOR . 'xml', XmlDriver::FILE_PER_CLASS);
|
||||
$xmlDriver = new XmlDriver(__DIR__ . DIRECTORY_SEPARATOR . 'xml');
|
||||
|
||||
$class = new ClassMetadata($className);
|
||||
|
||||
@ -38,36 +38,16 @@ class MappingDriverTest extends \Doctrine\Tests\OrmTestCase
|
||||
$this->_testUserClassMapping($class);
|
||||
}
|
||||
|
||||
public function testXmlPreloadMode()
|
||||
public function testXmlGetAllClassNames()
|
||||
{
|
||||
$className = 'Doctrine\Tests\ORM\Mapping\User';
|
||||
$xmlDriver = new XmlDriver(__DIR__ . DIRECTORY_SEPARATOR . 'xml', XmlDriver::PRELOAD);
|
||||
$xmlDriver = new XmlDriver(__DIR__ . DIRECTORY_SEPARATOR . 'xml');
|
||||
$class = new ClassMetadata($className);
|
||||
|
||||
$classNames = $xmlDriver->preload();
|
||||
$classNames = $xmlDriver->getAllClassNames();
|
||||
|
||||
$this->assertEquals($className, $classNames[0]);
|
||||
$this->assertEquals(1, count($xmlDriver->getPreloadedElements()));
|
||||
|
||||
$xmlDriver->loadMetadataForClass($className, $class);
|
||||
|
||||
$this->assertEquals(0, count($xmlDriver->getPreloadedElements()));
|
||||
}
|
||||
|
||||
public function testYamlPreloadMode()
|
||||
{
|
||||
$className = 'Doctrine\Tests\ORM\Mapping\User';
|
||||
$yamlDriver = new YamlDriver(__DIR__ . DIRECTORY_SEPARATOR . 'yaml', YamlDriver::PRELOAD);
|
||||
$class = new ClassMetadata($className);
|
||||
|
||||
$classNames = $yamlDriver->preload();
|
||||
|
||||
$this->assertEquals($className, $classNames[0]);
|
||||
$this->assertEquals(1, count($yamlDriver->getPreloadedElements()));
|
||||
|
||||
$yamlDriver->loadMetadataForClass($className, $class);
|
||||
|
||||
$this->assertEquals(0, count($yamlDriver->getPreloadedElements()));
|
||||
$this->assertEquals(1, count($classNames));
|
||||
}
|
||||
|
||||
private function _testUserClassMapping($class)
|
||||
|
@ -8,9 +8,9 @@ error_reporting(E_ALL | E_STRICT);
|
||||
|
||||
require_once 'PHPUnit/Framework.php';
|
||||
require_once 'PHPUnit/TextUI/TestRunner.php';
|
||||
require_once __DIR__ . '/../../../lib/Doctrine/Common/IsolatedClassLoader.php';
|
||||
require_once __DIR__ . '/../../../lib/Doctrine/Common/ClassLoader.php';
|
||||
|
||||
$classLoader = new \Doctrine\Common\IsolatedClassLoader('Doctrine');
|
||||
$classLoader = new \Doctrine\Common\ClassLoader('Doctrine');
|
||||
$classLoader->register();
|
||||
|
||||
set_include_path(
|
||||
|
@ -14,14 +14,12 @@
|
||||
# named "cli-config.php" (this one) in the same directory and uses that by default.
|
||||
#
|
||||
|
||||
require_once __DIR__ . '/../../lib/Doctrine/Common/IsolatedClassLoader.php';
|
||||
require_once __DIR__ . '/../../lib/Doctrine/Common/ClassLoader.php';
|
||||
|
||||
$classLoader = new \Doctrine\Common\IsolatedClassLoader('Entities');
|
||||
$classLoader->setBasePath(__DIR__);
|
||||
$classLoader = new \Doctrine\Common\ClassLoader('Entities', __DIR__);
|
||||
$classLoader->register();
|
||||
|
||||
$classLoader = new \Doctrine\Common\IsolatedClassLoader('Proxies');
|
||||
$classLoader->setBasePath(__DIR__);
|
||||
$classLoader = new \Doctrine\Common\ClassLoader('Proxies', __DIR__);
|
||||
$classLoader->register();
|
||||
|
||||
$config = new \Doctrine\ORM\Configuration();
|
||||
|
@ -1,9 +1,8 @@
|
||||
<?php
|
||||
|
||||
require __DIR__ . '/../../lib/Doctrine/Common/IsolatedClassLoader.php';
|
||||
require __DIR__ . '/../../lib/Doctrine/Common/ClassLoader.php';
|
||||
|
||||
$classLoader = new \Doctrine\Common\IsolatedClassLoader('Doctrine');
|
||||
$classLoader->setBasePath(__DIR__ . '/../../lib');
|
||||
$classLoader = new \Doctrine\Common\ClassLoader('Doctrine', __DIR__ . '/../../lib');
|
||||
$classLoader->register();
|
||||
|
||||
$cli = new \Doctrine\ORM\Tools\Cli\CliController();
|
||||
|
@ -9,20 +9,22 @@
|
||||
|
||||
namespace Sandbox;
|
||||
|
||||
use Doctrine\ORM\Configuration,
|
||||
use Doctrine\Common\ClassLoader,
|
||||
Doctrine\ORM\Configuration,
|
||||
Doctrine\ORM\EntityManager,
|
||||
Doctrine\Common\Cache\ApcCache,
|
||||
Entities\User, Entities\Address;
|
||||
|
||||
require '../../lib/Doctrine/Common/GlobalClassLoader.php';
|
||||
require '../../lib/Doctrine/Common/ClassLoader.php';
|
||||
|
||||
// Set up class loading, we could alternatively use several IsolatedClassLoaders.
|
||||
// You could also use different autoloaders, provided by your favorite framework.
|
||||
$classLoader = new \Doctrine\Common\GlobalClassLoader();
|
||||
$classLoader->registerNamespace('Doctrine', realpath(__DIR__ . '/../../lib'));
|
||||
$classLoader->registerNamespace('Entities', __DIR__);
|
||||
$classLoader->registerNamespace('Proxies', __DIR__);
|
||||
$classLoader->register();
|
||||
// Set up class loading. You could use different autoloaders, provided by your favorite framework,
|
||||
// if you want to.
|
||||
$doctrineClassLoader = new ClassLoader('Doctrine', realpath(__DIR__ . '/../../lib'));
|
||||
$doctrineClassLoader->register();
|
||||
$entitiesClassLoader = new ClassLoader('Entities', __DIR__);
|
||||
$entitiesClassLoader->register();
|
||||
$proxiesClassLoader = new ClassLoader('Proxies', __DIR__);
|
||||
$proxiesClassLoader->register();
|
||||
|
||||
// Set up caches
|
||||
$config = new Configuration;
|
||||
|
Loading…
Reference in New Issue
Block a user