Merge branch '2.1'
* 2.1: [HttpFoundation] changed UploadedFile::move() to use move_uploaded_file() when possible (closes #5878, closes #6185) [HttpFoundation] added a check for the host header value [DoctrineBridge] Improved performance of the EntityType when used with the "query_builder" option [DoctrineBridge] Improved exception message [DoctrineBridge] Fixed: Exception is thrown if the entity class is not known to Doctrine Removed useless branch alias for dev-master in composer.json Conflicts: composer.json src/Symfony/Bridge/Doctrine/composer.json src/Symfony/Bridge/Monolog/composer.json src/Symfony/Bridge/Propel1/composer.json src/Symfony/Bridge/Swiftmailer/composer.json src/Symfony/Bridge/Twig/composer.json src/Symfony/Bundle/FrameworkBundle/composer.json src/Symfony/Bundle/SecurityBundle/composer.json src/Symfony/Bundle/TwigBundle/composer.json src/Symfony/Bundle/WebProfilerBundle/composer.json src/Symfony/Component/BrowserKit/composer.json src/Symfony/Component/ClassLoader/composer.json src/Symfony/Component/Config/composer.json src/Symfony/Component/Console/composer.json src/Symfony/Component/CssSelector/composer.json src/Symfony/Component/DependencyInjection/composer.json src/Symfony/Component/DomCrawler/composer.json src/Symfony/Component/EventDispatcher/composer.json src/Symfony/Component/Filesystem/composer.json src/Symfony/Component/Finder/composer.json src/Symfony/Component/Form/composer.json src/Symfony/Component/HttpFoundation/composer.json src/Symfony/Component/HttpKernel/composer.json src/Symfony/Component/Locale/composer.json src/Symfony/Component/OptionsResolver/composer.json src/Symfony/Component/Process/composer.json src/Symfony/Component/Routing/composer.json src/Symfony/Component/Security/composer.json src/Symfony/Component/Serializer/composer.json src/Symfony/Component/Templating/composer.json src/Symfony/Component/Translation/composer.json src/Symfony/Component/Validator/composer.json src/Symfony/Component/Yaml/composer.json
This commit is contained in:
commit
6e45f1cd78
@ -1,6 +1,11 @@
|
|||||||
CHANGELOG
|
CHANGELOG
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
2.1.5
|
||||||
|
-----
|
||||||
|
|
||||||
|
* fixed caching of choice lists when EntityType is used with the "query_builder" option
|
||||||
|
|
||||||
2.1.0
|
2.1.0
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
@ -392,7 +392,10 @@ class EntityChoiceList extends ObjectChoiceList
|
|||||||
private function getIdentifierValues($entity)
|
private function getIdentifierValues($entity)
|
||||||
{
|
{
|
||||||
if (!$this->em->contains($entity)) {
|
if (!$this->em->contains($entity)) {
|
||||||
throw new FormException('Entities passed to the choice field must be managed');
|
throw new FormException(
|
||||||
|
'Entities passed to the choice field must be managed. Maybe ' .
|
||||||
|
'persist them in the entity manager?'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->em->initializeObject($entity);
|
$this->em->initializeObject($entity);
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
namespace Symfony\Bridge\Doctrine\Form\Type;
|
namespace Symfony\Bridge\Doctrine\Form\Type;
|
||||||
|
|
||||||
use Doctrine\Common\Persistence\ManagerRegistry;
|
use Doctrine\Common\Persistence\ManagerRegistry;
|
||||||
|
use Symfony\Component\Form\Exception\FormException;
|
||||||
use Doctrine\Common\Persistence\ObjectManager;
|
use Doctrine\Common\Persistence\ObjectManager;
|
||||||
use Symfony\Component\Form\FormBuilderInterface;
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
use Symfony\Bridge\Doctrine\Form\ChoiceList\EntityChoiceList;
|
use Symfony\Bridge\Doctrine\Form\ChoiceList\EntityChoiceList;
|
||||||
@ -130,7 +131,17 @@ abstract class DoctrineType extends AbstractType
|
|||||||
return $registry->getManager($em);
|
return $registry->getManager($em);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $registry->getManagerForClass($options['class']);
|
$em = $registry->getManagerForClass($options['class']);
|
||||||
|
|
||||||
|
if (null === $em) {
|
||||||
|
throw new FormException(sprintf(
|
||||||
|
'Class "%s" seems not to be a managed Doctrine entity. ' .
|
||||||
|
'Did you forget to map it?',
|
||||||
|
$options['class']
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $em;
|
||||||
};
|
};
|
||||||
|
|
||||||
$resolver->setDefaults(array(
|
$resolver->setDefaults(array(
|
||||||
|
@ -11,26 +11,53 @@
|
|||||||
|
|
||||||
namespace Symfony\Bridge\Doctrine\Form\Type;
|
namespace Symfony\Bridge\Doctrine\Form\Type;
|
||||||
|
|
||||||
use Doctrine\Common\Persistence\ObjectManager;
|
use Symfony\Component\Form\Exception\UnexpectedTypeException;
|
||||||
use Symfony\Bridge\Doctrine\Form\ChoiceList\ORMQueryBuilderLoader;
|
use Symfony\Bridge\Doctrine\Form\ChoiceList\ORMQueryBuilderLoader;
|
||||||
|
use Doctrine\Common\Persistence\ObjectManager;
|
||||||
|
use Doctrine\ORM\QueryBuilder;
|
||||||
|
|
||||||
class EntityType extends DoctrineType
|
class EntityType extends DoctrineType
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $loaderCache = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the default loader object.
|
* Return the default loader object.
|
||||||
*
|
*
|
||||||
* @param ObjectManager $manager
|
* @param ObjectManager $manager
|
||||||
* @param mixed $queryBuilder
|
* @param QueryBuilder|\Closure $queryBuilder
|
||||||
* @param string $class
|
* @param string $class
|
||||||
|
*
|
||||||
* @return ORMQueryBuilderLoader
|
* @return ORMQueryBuilderLoader
|
||||||
|
*
|
||||||
|
* @throws UnexpectedTypeException If the passed $queryBuilder is no \Closure
|
||||||
|
* and no QueryBuilder or if the closure
|
||||||
|
* does not return a QueryBuilder.
|
||||||
*/
|
*/
|
||||||
public function getLoader(ObjectManager $manager, $queryBuilder, $class)
|
public function getLoader(ObjectManager $manager, $queryBuilder, $class)
|
||||||
{
|
{
|
||||||
return new ORMQueryBuilderLoader(
|
if ($queryBuilder instanceof \Closure) {
|
||||||
$queryBuilder,
|
$queryBuilder = $queryBuilder($manager->getRepository($class));
|
||||||
$manager,
|
|
||||||
$class
|
if (!$queryBuilder instanceof QueryBuilder) {
|
||||||
);
|
throw new UnexpectedTypeException($queryBuilder, 'Doctrine\ORM\QueryBuilder');
|
||||||
|
}
|
||||||
|
} elseif (!$queryBuilder instanceof QueryBuilder) {
|
||||||
|
throw new UnexpectedTypeException($queryBuilder, 'Doctrine\ORM\QueryBuilder or \Closure');
|
||||||
|
}
|
||||||
|
|
||||||
|
// It is important to return the same loader for identical queries,
|
||||||
|
// otherwise the caching mechanism in DoctrineType does not work
|
||||||
|
// (which expects identical loaders for the cache to work)
|
||||||
|
$hash = md5($queryBuilder->getQuery()->getDQL());
|
||||||
|
|
||||||
|
if (!isset($this->loaderCache[$hash])) {
|
||||||
|
$this->loaderCache[$hash] = new ORMQueryBuilderLoader($queryBuilder);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->loaderCache[$hash];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName()
|
public function getName()
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
namespace Symfony\Bridge\Doctrine\Tests\Form\Type;
|
namespace Symfony\Bridge\Doctrine\Tests\Form\Type;
|
||||||
|
|
||||||
use Symfony\Component\Form\Tests\FormPerformanceTestCase;
|
use Symfony\Component\Form\Tests\FormPerformanceTestCase;
|
||||||
|
use Doctrine\ORM\EntityRepository;
|
||||||
use Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIdentEntity;
|
use Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIdentEntity;
|
||||||
use Doctrine\ORM\Tools\SchemaTool;
|
use Doctrine\ORM\Tools\SchemaTool;
|
||||||
use Symfony\Bridge\Doctrine\Tests\DoctrineOrmTestCase;
|
use Symfony\Bridge\Doctrine\Tests\DoctrineOrmTestCase;
|
||||||
@ -36,6 +37,9 @@ class EntityTypePerformanceTest extends FormPerformanceTestCase
|
|||||||
$manager->expects($this->any())
|
$manager->expects($this->any())
|
||||||
->method('getManager')
|
->method('getManager')
|
||||||
->will($this->returnValue($this->em));
|
->will($this->returnValue($this->em));
|
||||||
|
$manager->expects($this->any())
|
||||||
|
->method('getManagerForClass')
|
||||||
|
->will($this->returnValue($this->em));
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
new CoreExtension(),
|
new CoreExtension(),
|
||||||
@ -109,4 +113,21 @@ class EntityTypePerformanceTest extends FormPerformanceTestCase
|
|||||||
$form->createView();
|
$form->createView();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testCollapsedEntityFieldWithQueryBuilder()
|
||||||
|
{
|
||||||
|
$this->setMaxRunningTime(1);
|
||||||
|
|
||||||
|
for ($i = 0; $i < 20; ++$i) {
|
||||||
|
$form = $this->factory->create('entity', null, array(
|
||||||
|
'class' => self::ENTITY_CLASS,
|
||||||
|
'query_builder' => function (EntityRepository $repo) {
|
||||||
|
return $repo->createQueryBuilder('e')->addOrderBy('e.id', 'DESC');
|
||||||
|
}
|
||||||
|
));
|
||||||
|
|
||||||
|
// force loading of the choice list
|
||||||
|
$form->createView();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,6 +106,20 @@ class File extends \SplFileInfo
|
|||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
public function move($directory, $name = null)
|
public function move($directory, $name = null)
|
||||||
|
{
|
||||||
|
$target = $this->getTargetFile($directory, $name);
|
||||||
|
|
||||||
|
if (!@rename($this->getPathname(), $target)) {
|
||||||
|
$error = error_get_last();
|
||||||
|
throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error['message'])));
|
||||||
|
}
|
||||||
|
|
||||||
|
@chmod($target, 0666 & ~umask());
|
||||||
|
|
||||||
|
return $target;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getTargetFile($directory, $name = null)
|
||||||
{
|
{
|
||||||
if (!is_dir($directory)) {
|
if (!is_dir($directory)) {
|
||||||
if (false === @mkdir($directory, 0777, true)) {
|
if (false === @mkdir($directory, 0777, true)) {
|
||||||
@ -117,14 +131,7 @@ class File extends \SplFileInfo
|
|||||||
|
|
||||||
$target = $directory.DIRECTORY_SEPARATOR.(null === $name ? $this->getBasename() : $this->getName($name));
|
$target = $directory.DIRECTORY_SEPARATOR.(null === $name ? $this->getBasename() : $this->getName($name));
|
||||||
|
|
||||||
if (!@rename($this->getPathname(), $target)) {
|
return new File($target, false);
|
||||||
$error = error_get_last();
|
|
||||||
throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error['message'])));
|
|
||||||
}
|
|
||||||
|
|
||||||
@chmod($target, 0666 & ~umask());
|
|
||||||
|
|
||||||
return new File($target);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -202,8 +202,21 @@ class UploadedFile extends File
|
|||||||
*/
|
*/
|
||||||
public function move($directory, $name = null)
|
public function move($directory, $name = null)
|
||||||
{
|
{
|
||||||
if ($this->isValid() && ($this->test || is_uploaded_file($this->getPathname()))) {
|
if ($this->isValid()) {
|
||||||
|
if ($this->test) {
|
||||||
return parent::move($directory, $name);
|
return parent::move($directory, $name);
|
||||||
|
} elseif (is_uploaded_file($this->getPathname())) {
|
||||||
|
$target = $this->getTargetFile($directory, $name);
|
||||||
|
|
||||||
|
if (!@move_uploaded_file($this->getPathname(), $target)) {
|
||||||
|
$error = error_get_last();
|
||||||
|
throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error['message'])));
|
||||||
|
}
|
||||||
|
|
||||||
|
@chmod($target, 0666 & ~umask());
|
||||||
|
|
||||||
|
return $target;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new FileException(sprintf('The file "%s" has not been uploaded via Http', $this->getPathname()));
|
throw new FileException(sprintf('The file "%s" has not been uploaded via Http', $this->getPathname()));
|
||||||
|
@ -989,6 +989,8 @@ class Request
|
|||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*
|
*
|
||||||
|
* @throws \UnexpectedValueException when the host name is invalid
|
||||||
|
*
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
public function getHost()
|
public function getHost()
|
||||||
@ -996,20 +998,24 @@ class Request
|
|||||||
if (self::$trustProxy && self::$trustedHeaders[self::HEADER_CLIENT_HOST] && $host = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_HOST])) {
|
if (self::$trustProxy && self::$trustedHeaders[self::HEADER_CLIENT_HOST] && $host = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_HOST])) {
|
||||||
$elements = explode(',', $host);
|
$elements = explode(',', $host);
|
||||||
|
|
||||||
$host = trim($elements[count($elements) - 1]);
|
$host = $elements[count($elements) - 1];
|
||||||
} else {
|
} elseif (!$host = $this->headers->get('HOST')) {
|
||||||
if (!$host = $this->headers->get('HOST')) {
|
|
||||||
if (!$host = $this->server->get('SERVER_NAME')) {
|
if (!$host = $this->server->get('SERVER_NAME')) {
|
||||||
$host = $this->server->get('SERVER_ADDR', '');
|
$host = $this->server->get('SERVER_ADDR', '');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// trim and remove port number from host
|
||||||
|
// host is lowercase as per RFC 952/2181
|
||||||
|
$host = strtolower(trim(preg_replace('/:\d+$/', '', $host)));
|
||||||
|
|
||||||
|
// as the host can come from the user (HTTP_HOST and depending on the configuration, SERVER_NAME too can come from the user)
|
||||||
|
// check that it does not contain forbidden characters (see RFC 952 and RFC 2181)
|
||||||
|
if ($host && !preg_match('/^\[?(?:[a-zA-Z0-9-:\]_]+\.?)+$/', $host)) {
|
||||||
|
throw new \UnexpectedValueException('Invalid Host');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove port number from host
|
return $host;
|
||||||
$host = preg_replace('/:\d+$/', '', $host);
|
|
||||||
|
|
||||||
// host is lowercase as per RFC 952/2181
|
|
||||||
return trim(strtolower($host));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -609,9 +609,6 @@ class RequestTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertNull($request->getQueryString(), '->getQueryString() returns null for empty query string');
|
$this->assertNull($request->getQueryString(), '->getQueryString() returns null for empty query string');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @covers Symfony\Component\HttpFoundation\Request::getHost
|
|
||||||
*/
|
|
||||||
public function testGetHost()
|
public function testGetHost()
|
||||||
{
|
{
|
||||||
$request = new Request();
|
$request = new Request();
|
||||||
@ -635,6 +632,16 @@ class RequestTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->stopTrustingProxyData();
|
$this->stopTrustingProxyData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException RuntimeException
|
||||||
|
*/
|
||||||
|
public function testGetHostWithFakeHttpHostValue()
|
||||||
|
{
|
||||||
|
$request = new Request();
|
||||||
|
$request->initialize(array(), array(), array(), array(), array(), array('HTTP_HOST' => 'www.host.com?query=string'));
|
||||||
|
$request->getHost();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @covers Symfony\Component\HttpFoundation\Request::setMethod
|
* @covers Symfony\Component\HttpFoundation\Request::setMethod
|
||||||
* @covers Symfony\Component\HttpFoundation\Request::getMethod
|
* @covers Symfony\Component\HttpFoundation\Request::getMethod
|
||||||
|
Reference in New Issue
Block a user