Skip to content

Commit

Permalink
Merge branch 'master' into assignid
Browse files Browse the repository at this point in the history
  • Loading branch information
asm89 committed Oct 15, 2011
2 parents fdb9fb1 + 73101be commit c5e51e6
Show file tree
Hide file tree
Showing 29 changed files with 1,196 additions and 80 deletions.
2 changes: 1 addition & 1 deletion README.markdown
@@ -1,6 +1,6 @@
# Doctrine 2 ORM

Doctrine 2 is an object-relational mapper (ORM) for PHP 5.3.0+ that provides transparent persistence
Doctrine 2 is an object-relational mapper (ORM) for PHP 5.3.2+ that provides transparent persistence
for PHP objects. It sits on top of a powerful database abstraction layer (DBAL). One of its key features
is the option to write database queries in a proprietary object oriented SQL dialect called Doctrine Query Language (DQL),
inspired by Hibernates HQL. This provides developers with a powerful alternative to SQL that maintains flexibility
Expand Down
11 changes: 11 additions & 0 deletions UPGRADE_TO_2_2
@@ -1,3 +1,14 @@
# EntityManager#getPartialReference() creates read-only entity

Entities returned from EntityManager#getPartialReference() are now marked as read-only if they
haven't been in the identity map before. This means objects of this kind never lead to changes
in the UnitOfWork.

# Fields omitted in a partial DQL query or a native query are never updated

Fields of an entity that are not returned from a partial DQL Query or native SQL query
will never be updated through an UPDATE statement.

# Removed support for onUpdate in @JoinColumn

The onUpdate foreign key handling makes absolutly no sense in an ORM. Additionally Oracle doesn't even support it. Support for it is removed.
Expand Down
20 changes: 20 additions & 0 deletions composer.json
@@ -0,0 +1,20 @@
{
"name": "doctrine/orm",
"type": "library",
"description": "Object-Relational-Mapper for PHP",
"keywords": ["orm", "database"],
"homepage": "http://www.doctrine-project.org",
"license": "LGPL",
"authors": [
{"name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com"},
{"name": "Roman Borschel", "email": "roman@code-factory.org"},
{"name": "Benjamin Eberlei", "email": "kontakt@beberlei.de"},
{"name": "Jonathan Wage", "email": "jonwage@gmail.com"}
],
"require": {
"php": ">=5.3.2",
"ext-pdo": "*",
"doctrine/common": "master-dev",
"doctrine/dbal": "master-dev"
}
}
1 change: 1 addition & 0 deletions lib/Doctrine/ORM/EntityManager.php
Expand Up @@ -413,6 +413,7 @@ public function getPartialReference($entityName, $identifier)
$entity = $class->newInstance();
$class->setIdentifierValues($entity, $identifier);
$this->unitOfWork->registerManaged($entity, $identifier, array());
$this->unitOfWork->markReadOnly($entity);

return $entity;
}
Expand Down
110 changes: 110 additions & 0 deletions lib/Doctrine/ORM/Event/EntityEventDelegator.php
@@ -0,0 +1,110 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/

namespace Doctrine\ORM\Event;

use \Doctrine\Common\EventSubscriber;
use \LogicException;

/**
* Delegate events only for certain entities they are registered for.
*
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @since 2.2
*/
class EntityEventDelegator implements EventSubscriber
{
/**
* Keeps track of all the event listeners.
*
* @var array
*/
private $listeners = array();

/**
* If frozen no new event listeners can be added.
*
* @var bool
*/
private $frozen = false;

/**
* Adds an event listener that listens on the specified events.
*
* @param string|array $events The event(s) to listen on.
* @param string|array $entities The entities to trigger this listener for
* @param object $listener The listener object.
*/
public function addEventListener($events, $entities, $listener)
{
if ($this->frozen) {
throw new LogicException("Cannot add event listeners after EntityEventDelegator::getSubscribedEvents() " .
"is called once. This happens when you register the delegator with the event manager.");
}

// Picks the hash code related to that listener
$hash = spl_object_hash($listener);

foreach ((array) $events as $event) {
// Overrides listener if a previous one was associated already
// Prevents duplicate listeners on same event (same instance only)
$this->listeners[$event][$hash] = array('listener' => $listener, 'entities' => array_flip((array)$entities));
}
}

/**
* Adds an EventSubscriber. The subscriber is asked for all the events he is
* interested in and added as a listener for these events.
*
* @param Doctrine\Common\EventSubscriber $subscriber The subscriber.
*/
public function addEventSubscriber(EventSubscriber $subscriber, $entities)
{
$this->addEventListener($subscriber->getSubscribedEvents(), $entities, $subscriber);
}

/**
* Returns an array of events this subscriber wants to listen to.
*
* @return array
*/
public function getSubscribedEvents()
{
$this->frozen = true;
return array_keys($this->listeners);
}

/**
* Delegate the event to an appropriate listener
*
* @param $eventName
* @param $event
* @return void
*/
public function __call($eventName, $args)
{
$event = $args[0];
foreach ($this->listeners[$eventName] AS $listenerData) {
$class = get_class($event->getEntity());
if (isset($listenerData['entities'][$class])) {
$listenerData['listener']->$eventName($event);
}
}
}
}
2 changes: 1 addition & 1 deletion lib/Doctrine/ORM/Event/PreUpdateEventArgs.php
Expand Up @@ -90,7 +90,7 @@ private function _assertValidField($field)
if (!isset($this->_entityChangeSet[$field])) {
throw new \InvalidArgumentException(
"Field '".$field."' is not a valid field of the entity ".
"'".get_class($this->getEntity())."' in PreInsertUpdateEventArgs."
"'".get_class($this->getEntity())."' in PreUpdateEventArgs."
);
}
}
Expand Down
176 changes: 176 additions & 0 deletions lib/Doctrine/ORM/Mapping/Driver/SimplifiedXmlDriver.php
@@ -0,0 +1,176 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/

namespace Doctrine\ORM\Mapping\Driver;

use Doctrine\ORM\Mapping\MappingException;

/**
* XmlDriver that additionally looks for mapping information in a global file.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @license MIT
*/
class SimplifiedXmlDriver extends XmlDriver
{
protected $_prefixes = array();
protected $_globalBasename;
protected $_classCache;
protected $_fileExtension = '.orm.xml';

public function __construct($prefixes)
{
$this->addNamespacePrefixes($prefixes);
}

public function setGlobalBasename($file)
{
$this->_globalBasename = $file;
}

public function getGlobalBasename()
{
return $this->_globalBasename;
}

public function addNamespacePrefixes($prefixes)
{
$this->_prefixes = array_merge($this->_prefixes, $prefixes);
$this->addPaths(array_flip($prefixes));
}

public function getNamespacePrefixes()
{
return $this->_prefixes;
}

public function isTransient($className)
{
if (null === $this->_classCache) {
$this->initialize();
}

// The mapping is defined in the global mapping file
if (isset($this->_classCache[$className])) {
return false;
}

try {
$this->_findMappingFile($className);

return false;
} catch (MappingException $e) {
return true;
}
}

public function getAllClassNames()
{
if (null === $this->_classCache) {
$this->initialize();
}

$classes = array();

if ($this->_paths) {
foreach ((array) $this->_paths as $path) {
if (!is_dir($path)) {
throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath($path);
}

$iterator = new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator($path),
\RecursiveIteratorIterator::LEAVES_ONLY
);

foreach ($iterator as $file) {
$fileName = $file->getBasename($this->_fileExtension);

if ($fileName == $file->getBasename() || $fileName == $this->_globalBasename) {
continue;
}

// NOTE: All files found here means classes are not transient!
if (isset($this->_prefixes[$path])) {
$classes[] = $this->_prefixes[$path].'\\'.str_replace('.', '\\', $fileName);
} else {
$classes[] = str_replace('.', '\\', $fileName);
}
}
}
}

return array_merge($classes, array_keys($this->_classCache));
}

public function getElement($className)
{
if (null === $this->_classCache) {
$this->initialize();
}

if (!isset($this->_classCache[$className])) {
$this->_classCache[$className] = parent::getElement($className);
}

return $this->_classCache[$className];
}

protected function initialize()
{
$this->_classCache = array();
if (null !== $this->_globalBasename) {
foreach ($this->_paths as $path) {
if (is_file($file = $path.'/'.$this->_globalBasename.$this->_fileExtension)) {
$this->_classCache = array_merge($this->_classCache, $this->_loadMappingFile($file));
}
}
}
}

protected function _findMappingFile($className)
{
$defaultFileName = str_replace('\\', '.', $className).$this->_fileExtension;
foreach ($this->_paths as $path) {
if (!isset($this->_prefixes[$path])) {
if (is_file($path.DIRECTORY_SEPARATOR.$defaultFileName)) {
return $path.DIRECTORY_SEPARATOR.$defaultFileName;
}

continue;
}

$prefix = $this->_prefixes[$path];

if (0 !== strpos($className, $prefix.'\\')) {
continue;
}

$filename = $path.'/'.strtr(substr($className, strlen($prefix)+1), '\\', '.').$this->_fileExtension;
if (is_file($filename)) {
return $filename;
}

throw MappingException::mappingFileNotFound($className, $filename);
}

throw MappingException::mappingFileNotFound($className, substr($className, strrpos($className, '\\') + 1).$this->_fileExtension);
}
}

0 comments on commit c5e51e6

Please sign in to comment.