Skip to content
Closed
Original file line number Diff line number Diff line change
Expand Up @@ -328,20 +328,19 @@ protected function loadOrmEntityManagerBundlesMappingInformation(array $entityMa
// configure metadata driver for each bundle based on the type of mapping files found
$mappingDriverDef = new Definition('%doctrine.orm.metadata.driver_chain_class%');
$bundleEntityMappings = array();
$bundleDirs = $container->getParameter('kernel.bundle_dirs');
$aliasMap = array();
foreach ($container->getParameter('kernel.bundles') as $className) {
$tmp = dirname(str_replace('\\', '/', $className));
$namespace = str_replace('/', '\\', dirname($tmp));
$class = basename($tmp);

if (!isset($bundleDirs[$namespace])) {
if (! $bundleDir = $this->findBundleDirForNamespace($namespace, $container)) {
continue;
}

$type = $this->detectMetadataDriver($bundleDirs[$namespace].'/'.$class, $container);
$type = $this->detectMetadataDriver($bundleDir.'/'.$class, $container);

if (is_dir($dir = $bundleDirs[$namespace].'/'.$class.'/Entity')) {
if (is_dir($dir = $bundleDir.'/'.$class.'/Entity')) {
if ($type === null) {
$type = 'annotation';
}
Expand Down Expand Up @@ -443,6 +442,31 @@ protected function getEntityManagerCacheDefinition(array $entityManager, $cacheD
return $cacheDef;
}

/**
* Finds the bundle directory for a namespace.
*
* If the namespace does not yield a direct match, this method will attempt
* to match parent namespaces exhaustively.
*
* @param string $namespace A bundle namespace omitting the bundle name part
* @param ContainerBuilder $container A ContainerBuilder instance
*
* @return string|false The bundle directory if found, false otherwise
*/
protected function findBundleDirForNamespace($namespace, ContainerBuilder $container)
{
$bundleDirs = $container->getParameter('kernel.bundle_dirs');
$segment = $namespace;

do {
if (isset($bundleDirs[$segment])) {
return $bundleDirs[$segment] . str_replace('\\', '/', substr($namespace, strlen($segment)));
}
} while ($segment = substr($segment, 0, ($pos = strrpos($segment, '\\'))));

return false;
}

/**
* Finds existing bundle subpaths.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,24 @@ public function testAnnotationsBundleMappingDetection()
$this->assertEquals('DoctrineBundle\Tests\DependencyInjection\Fixtures\Bundles\AnnotationsBundle\Entity', $calls[0][1][1]);
}

public function testAnnotationsBundleMappingDetectionWithVendorNamespace()
{
$container = $this->getContainer('AnnotationsBundle', 'Vendor');
$loader = new DoctrineExtension();

$loader->dbalLoad(array(), $container);
$loader->ormLoad(array(), $container);

$this->assertEquals(array(), $container->getParameter('doctrine.orm.metadata_driver.mapping_dirs'));
$this->assertEquals('%doctrine.orm.metadata_driver.mapping_dirs%', $container->getParameter('doctrine.orm.xml_mapping_dirs'));
$this->assertEquals('%doctrine.orm.metadata_driver.mapping_dirs%', $container->getParameter('doctrine.orm.yml_mapping_dirs'));
$this->assertEquals(array(__DIR__.'/Fixtures/Bundles/Vendor/AnnotationsBundle/Entity'), $container->getParameter('doctrine.orm.metadata_driver.entity_dirs'));

$calls = $container->getDefinition('doctrine.orm.metadata_driver')->getMethodCalls();
$this->assertEquals('doctrine.orm.metadata_driver.annotation', (string) $calls[0][1][0]);
$this->assertEquals('DoctrineBundle\Tests\DependencyInjection\Fixtures\Bundles\Vendor\AnnotationsBundle\Entity', $calls[0][1][1]);
}

public function testEntityManagerMetadataCacheDriverConfiguration()
{
$container = $this->getContainer();
Expand Down Expand Up @@ -442,13 +460,13 @@ public function testDependencyInjectionImportsOverrideDefaults()
$this->assertTrue($container->getParameter('doctrine.orm.auto_generate_proxy_classes'));
}

protected function getContainer($bundle = 'YamlBundle')
protected function getContainer($bundle = 'YamlBundle', $vendor = null)
{
require_once __DIR__.'/Fixtures/Bundles/'.$bundle.'/'.$bundle.'.php';
require_once __DIR__.'/Fixtures/Bundles/'.($vendor ? $vendor.'/' : '').$bundle.'/'.$bundle.'.php';

return new ContainerBuilder(new ParameterBag(array(
'kernel.bundle_dirs' => array('DoctrineBundle\\Tests\\DependencyInjection\\Fixtures\\Bundles' => __DIR__.'/Fixtures/Bundles'),
'kernel.bundles' => array('DoctrineBundle\\Tests\DependencyInjection\\Fixtures\\Bundles\\'.$bundle.'\\'.$bundle),
'kernel.bundles' => array('DoctrineBundle\\Tests\DependencyInjection\\Fixtures\\Bundles\\'.($vendor ? $vendor.'\\' : '').$bundle.'\\'.$bundle),
'kernel.cache_dir' => sys_get_temp_dir(),
)));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

namespace DoctrineBundle\Tests\DependencyInjection\Fixtures\Bundles\Vendor\AnnotationsBundle;

use Symfony\Component\HttpKernel\Bundle\Bundle;

class AnnotationsBundle extends Bundle
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

namespace DoctrineBundle\Tests\DependencyInjection\Fixtures\Bundles\Vendor\AnnotationsBundle\Entity;

class Test
{
}
Original file line number Diff line number Diff line change
Expand Up @@ -188,20 +188,19 @@ protected function loadDocumentManagerBundlesMappingInformation(array $documentM
// configure metadata driver for each bundle based on the type of mapping files found
$mappingDriverDef = new Definition('%doctrine.odm.mongodb.metadata.driver_chain_class%');
$bundleDocumentMappings = array();
$bundleDirs = $container->getParameter('kernel.bundle_dirs');
$aliasMap = array();
foreach ($container->getParameter('kernel.bundles') as $className) {
$tmp = dirname(str_replace('\\', '/', $className));
$namespace = str_replace('/', '\\', dirname($tmp));
$class = basename($tmp);

if (!isset($bundleDirs[$namespace])) {
if (! $bundleDir = $this->findBundleDirForNamespace($namespace, $container)) {
continue;
}

$type = $this->detectMetadataDriver($bundleDirs[$namespace].'/'.$class, $container);
$type = $this->detectMetadataDriver($bundleDir.'/'.$class, $container);

if (is_dir($dir = $bundleDirs[$namespace].'/'.$class.'/Document')) {
if (is_dir($dir = $bundleDir.'/'.$class.'/Document')) {
if ($type === null) {
$type = 'annotation';
}
Expand Down Expand Up @@ -294,6 +293,31 @@ protected function getConnections(array $config, ContainerBuilder $container)
return $connections;
}

/**
* Finds the bundle directory for a namespace.
*
* If the namespace does not yield a direct match, this method will attempt
* to match parent namespaces exhaustively.
*
* @param string $namespace A bundle namespace omitting the bundle name part
* @param ContainerBuilder $container A ContainerBuilder instance
*
* @return string|false The bundle directory if found, false otherwise
*/
protected function findBundleDirForNamespace($namespace, ContainerBuilder $container)
{
$bundleDirs = $container->getParameter('kernel.bundle_dirs');
$segment = $namespace;

do {
if (isset($bundleDirs[$segment])) {
return $bundleDirs[$segment] . str_replace('\\', '/', substr($namespace, strlen($segment)));
}
} while ($segment = substr($segment, 0, ($pos = strrpos($segment, '\\'))));

return false;
}

/**
* Finds existing bundle subpaths.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
<div class="count"><?php echo $data->getQueryCount() ?></div>
<img style="margin: 0 5px 0 0; vertical-align: middle; width: 32px" width="32" height="32" alt="Mongo" src="<?php echo $view->get('assets')->getUrl('bundles/webprofiler/images/db.png') ?>" />
Doctrine MongoDB
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,23 @@ public function testAnnotationsBundleMappingDetection()
$this->assertEquals('DoctrineMongoDBBundle\Tests\DependencyInjection\Fixtures\Bundles\AnnotationsBundle\Document', $calls[0][1][1]);
}

public function testAnnotationsBundleMappingDetectionWithVendorNamespace()
{
$container = $this->getContainer('AnnotationsBundle', 'Vendor');
$loader = new DoctrineMongoDBExtension();

$loader->mongodbLoad(array(), $container);

$this->assertEquals(array(), $container->getParameter('doctrine.odm.mongodb.mapping_dirs'));
$this->assertEquals('%doctrine.odm.mongodb.mapping_dirs%', $container->getParameter('doctrine.odm.mongodb.xml_mapping_dirs'));
$this->assertEquals('%doctrine.odm.mongodb.mapping_dirs%', $container->getParameter('doctrine.odm.mongodb.yml_mapping_dirs'));
$this->assertEquals(array(__DIR__.'/Fixtures/Bundles/Vendor/AnnotationsBundle/Document'), $container->getParameter('doctrine.odm.mongodb.document_dirs'));

$calls = $container->getDefinition('doctrine.odm.mongodb.metadata')->getMethodCalls();
$this->assertEquals('doctrine.odm.mongodb.metadata.annotation', (string) $calls[0][1][0]);
$this->assertEquals('DoctrineMongoDBBundle\Tests\DependencyInjection\Fixtures\Bundles\Vendor\AnnotationsBundle\Document', $calls[0][1][1]);
}

public function testDocumentManagerMetadataCacheDriverConfiguration()
{
$container = $this->getContainer();
Expand Down Expand Up @@ -316,13 +333,13 @@ public function testDependencyInjectionImportsOverrideDefaults()
$this->assertTrue($container->getParameter('doctrine.odm.mongodb.auto_generate_proxy_classes'));
}

protected function getContainer($bundle = 'YamlBundle')
protected function getContainer($bundle = 'YamlBundle', $vendor = null)
{
require_once __DIR__.'/Fixtures/Bundles/'.$bundle.'/'.$bundle.'.php';
require_once __DIR__.'/Fixtures/Bundles/'.($vendor ? $vendor.'/' : '').$bundle.'/'.$bundle.'.php';

return new ContainerBuilder(new ParameterBag(array(
'kernel.bundle_dirs' => array('DoctrineMongoDBBundle\\Tests\\DependencyInjection\\Fixtures\\Bundles' => __DIR__.'/Fixtures/Bundles'),
'kernel.bundles' => array('DoctrineMongoDBBundle\\Tests\\DependencyInjection\\Fixtures\\Bundles\\'.$bundle.'\\'.$bundle),
'kernel.bundles' => array('DoctrineMongoDBBundle\\Tests\\DependencyInjection\\Fixtures\\Bundles\\'.($vendor ? $vendor.'\\' : '').$bundle.'\\'.$bundle),
'kernel.cache_dir' => sys_get_temp_dir(),
)));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

namespace DoctrineMongoDBBundle\Tests\DependencyInjection\Fixtures\Bundles\Vendor\AnnotationsBundle;

use Symfony\Component\HttpKernel\Bundle\Bundle;

class AnnotationsBundle extends Bundle
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

namespace DoctrineMongoDBBundle\Tests\DependencyInjection\Fixtures\Bundles\Vendor\AnnotationsBundle\Document;

class Test
{
}
4 changes: 4 additions & 0 deletions src/Symfony/Component/HttpFoundation/UniversalClassLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@ public function register()
*/
public function loadClass($class)
{
if ('\\' === $class[0]) {
$class = substr($class, 1);
}

if (false !== ($pos = strripos($class, '\\'))) {
// namespaced class name
$namespace = substr($class, 0, $pos);
Expand Down
14 changes: 8 additions & 6 deletions src/Symfony/Component/Validator/Constraints/ValidValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,23 @@ public function isValid($value, Constraint $constraint)
$propertyPath = $this->context->getPropertyPath();
$factory = $this->context->getClassMetadataFactory();

if (is_array($value)) {
foreach ($value as $key => $element) {
$walker->walkConstraint($constraint, $element, $group, $propertyPath.'['.$key.']');
}
} else if (!is_object($value)) {
if (!is_array($value) && !is_object($value)) {
throw new UnexpectedTypeException($value, 'object or array');
} else if ($constraint->class && !$value instanceof $constraint->class) {
$this->setMessage($constraint->message, array('class' => $constraint->class));

return false;
} else {
} else if (!is_array($value)) {
$metadata = $factory->getClassMetadata(get_class($value));
$walker->walkClass($metadata, $value, $group, $propertyPath);
}

if (is_array($value) || $value instanceof \Traversable) {
foreach ($value as $key => $element) {
$walker->walkConstraint($constraint, $element, $group, $propertyPath.'['.$key.']');
}
}

return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

namespace Namespaced;

class Bar {
public static $loaded = true;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

namespace Namespaced;

class Foo {
public static $loaded = true;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?php

class Pearlike_Bar {
public static $loaded = true;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?php

class Pearlike_Foo {
public static $loaded = true;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Tests\Component\HttpFoundation;

use Symfony\Component\HttpFoundation\UniversalClassLoader;

class UniversalClassLoaderTest extends \PHPUnit_Framework_TestCase
{
/**
* @covers Symfony\Component\HttpFoundation\UniversalClassLoader::loadClass
* @dataProvider testClassProvider
*/
public function testLoadClass($className, $testClassName, $message)
{
$loader = new UniversalClassLoader();
$loader->registerNamespace('Namespaced', __DIR__ . DIRECTORY_SEPARATOR . 'Fixtures');
$loader->registerPrefix('Pearlike_', __DIR__ . DIRECTORY_SEPARATOR . 'Fixtures');
$loader->loadClass($testClassName);
$this->assertTrue(class_exists($className), $message);
}

public static function testClassProvider()
{
return array(
array('\\Namespaced\\Foo', 'Namespaced\\Foo', '->loadClass() loads Namespaced\Foo class'),
array('\\Pearlike_Foo', 'Pearlike_Foo', '->loadClass() loads Pearlike_Foo class'),
array('\\Namespaced\\Bar', '\\Namespaced\\Bar', '->loadClass() loads Namespaced\Bar class with a leading slash'),
array('\\Pearlike_Bar', '\\Pearlike_Bar', '->loadClass() loads Pearlike_Bar class with a leading slash'),
);
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,35 @@ public function testWalkArray()
$this->assertTrue($this->validator->isValid($array, $constraint));
}

public function testWalkTraversable()
{
$this->context->setGroup('MyGroup');
$this->context->setPropertyPath('foo');

$constraint = new Valid();
$metadata = $this->createClassMetadata();
$entity = new Entity();
// can only test for one object due to PHPUnit's mocking limitations
$traversable = new \ArrayObject( array('key' => $entity));

$this->walker->expects($this->once())
->method('walkConstraint')
->with($this->equalTo($constraint), $this->equalTo($entity), 'MyGroup', 'foo[key]');

$this->factory->expects($this->once())
->method('getClassMetadata')
->with($this->equalTo(get_class($traversable)))
->will($this->returnValue($metadata));


$this->walker->expects($this->once())
->method('walkClass')
->with($this->equalTo($metadata), $this->equalTo($traversable), 'MyGroup', 'foo');


$this->assertTrue($this->validator->isValid($traversable, $constraint));
}

public function testValidateClass_Succeeds()
{
$metadata = $this->createClassMetadata();
Expand Down