-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #6 from webfactory/feature/4-automatically-determi…
…ne-and-setup-dependencies Automatically determine and setup dependencies
- Loading branch information
Showing
13 changed files
with
753 additions
and
53 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
69 changes: 69 additions & 0 deletions
69
src/Webfactory/Doctrine/ORMTestInfrastructure/ConfigurationFactory.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
<?php | ||
|
||
/* | ||
* (c) webfactory GmbH <info@webfactory.de> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace Webfactory\Doctrine\ORMTestInfrastructure; | ||
|
||
use Doctrine\Common\Cache\ArrayCache; | ||
use Doctrine\ORM\Tools\Setup; | ||
|
||
/** | ||
* Creates ORM configurations for a set of entities. | ||
* | ||
* These configurations are meant for testing only. | ||
*/ | ||
class ConfigurationFactory | ||
{ | ||
/** | ||
* Creates the ORM configuration for the given set of entities. | ||
* | ||
* @param string[] $entityClasses | ||
* @return \Doctrine\ORM\Configuration | ||
*/ | ||
public function createFor(array $entityClasses) | ||
{ | ||
$config = Setup::createAnnotationMetadataConfiguration( | ||
$this->getFilePathsForClassNames($entityClasses), | ||
// Activate development mode. | ||
true, | ||
// Store proxies in the default temp directory. | ||
null, | ||
// Avoid Doctrine auto-detection of cache and use an isolated cache. | ||
new ArrayCache(), | ||
false | ||
); | ||
return $config; | ||
} | ||
|
||
/** | ||
* Returns a list of file paths for the provided class names. | ||
* | ||
* @param string[] $classNames | ||
* @return string[] | ||
*/ | ||
protected function getFilePathsForClassNames(array $classNames) | ||
{ | ||
$paths = array(); | ||
foreach ($classNames as $className) { | ||
$paths[] = $this->getFilePathForClassName($className); | ||
} | ||
return array_unique($paths); | ||
} | ||
|
||
/** | ||
* Returns the path to the directory that contains the given class. | ||
* | ||
* @param string $className | ||
* @return string | ||
*/ | ||
protected function getFilePathForClassName($className) | ||
{ | ||
$info = new \ReflectionClass($className); | ||
return dirname($info->getFileName()); | ||
} | ||
} |
128 changes: 128 additions & 0 deletions
128
src/Webfactory/Doctrine/ORMTestInfrastructure/EntityDependencyResolver.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
<?php | ||
|
||
/* | ||
* (c) webfactory GmbH <info@webfactory.de> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace Webfactory\Doctrine\ORMTestInfrastructure; | ||
|
||
use Doctrine\Common\Persistence\Mapping\ReflectionService; | ||
use Doctrine\Common\Persistence\Mapping\RuntimeReflectionService; | ||
use Doctrine\ORM\Configuration; | ||
use Doctrine\ORM\Mapping\ClassMetadata; | ||
|
||
/** | ||
* Takes a set of entity classes and resolves to a set that contains all entities | ||
* that are referenced by the provided entity classes (via associations). | ||
* | ||
* The resolved set also includes the original entity classes. | ||
*/ | ||
class EntityDependencyResolver implements \IteratorAggregate | ||
{ | ||
/** | ||
* Contains the names of the entity classes that were initially provided. | ||
* | ||
* @var string[] | ||
*/ | ||
protected $initialEntitySet = null; | ||
|
||
/** | ||
* Service that is used to inspect entity classes. | ||
* | ||
* @var ReflectionService | ||
*/ | ||
protected $reflectionService = null; | ||
|
||
/** | ||
* Factory that is used to create ORM configurations. | ||
* | ||
* @var ConfigurationFactory | ||
*/ | ||
protected $configFactory = null; | ||
|
||
/** | ||
* Creates a resolver for the given entity classes. | ||
* | ||
* @param string[] $entityClasses | ||
*/ | ||
public function __construct(array $entityClasses) | ||
{ | ||
$this->initialEntitySet = $this->normalizeClassNames($entityClasses); | ||
$this->reflectionService = new RuntimeReflectionService(); | ||
$this->configFactory = new ConfigurationFactory(); | ||
} | ||
|
||
/** | ||
* Allows iterating over the set of resolved entities. | ||
* | ||
* @return \Traversable | ||
* @link http://php.net/manual/en/iteratoraggregate.getiterator.php | ||
*/ | ||
public function getIterator() | ||
{ | ||
return new \ArrayIterator($this->resolve($this->initialEntitySet)); | ||
} | ||
|
||
/** | ||
* Resolves the dependencies for the given entities. | ||
* | ||
* @param string[] $entityClasses | ||
* @return string[] | ||
*/ | ||
protected function resolve(array $entityClasses) | ||
{ | ||
$entitiesToCheck = $entityClasses; | ||
$config = $this->configFactory->createFor($entitiesToCheck); | ||
while (count($associatedEntities = $this->getDirectlyAssociatedEntities($config, $entitiesToCheck)) > 0) { | ||
$newAssociations = array_diff($associatedEntities, $entityClasses); | ||
$entityClasses = array_merge($entityClasses, $newAssociations); | ||
$config = $this->configFactory->createFor($entityClasses); | ||
$entitiesToCheck = $newAssociations; | ||
} | ||
return $entityClasses; | ||
} | ||
|
||
/** | ||
* Returns the class names of additional entities that are directly associated with | ||
* one of the entities that is explicitly mentioned in the given configuration. | ||
* | ||
* @param Configuration $config | ||
* @param string[] $entityClasses Classes whose associations are checked. | ||
* @return string[] Associated entity classes. | ||
*/ | ||
protected function getDirectlyAssociatedEntities(Configuration $config, $entityClasses) | ||
{ | ||
if (count($entityClasses) === 0) { | ||
return array(); | ||
} | ||
$associatedEntities = array(); | ||
foreach ($entityClasses as $entityClass) { | ||
/* @var $entityClass string */ | ||
$metadata = new ClassMetadata($entityClass); | ||
$metadata->initializeReflection($this->reflectionService); | ||
$config->getMetadataDriverImpl()->loadMetadataForClass($entityClass, $metadata); | ||
foreach ($metadata->getAssociationNames() as $name) { | ||
/* @var $name string */ | ||
$associatedEntity = $metadata->getAssociationTargetClass($name); | ||
$associatedEntities[] = $metadata->fullyQualifiedClassName($associatedEntity); | ||
} | ||
} | ||
return array_unique($associatedEntities); | ||
} | ||
|
||
/** | ||
* Removes leading slashes from the given class names. | ||
* | ||
* @param string[] $entityClasses | ||
* @return string[] | ||
*/ | ||
protected function normalizeClassNames(array $entityClasses) | ||
{ | ||
return array_map(function ($class) { | ||
return ltrim($class, '\\'); | ||
}, $entityClasses); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.