diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000000000..b03e61ef338c1 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,11 @@ +| Q | A +| ------------- | --- +| Branch | master for features and deprecations / lowest applicable and maintained version otherwise +| Bug fix? | yes/no +| New feature? | yes/no +| BC breaks? | yes/no +| Deprecations? | yes/no +| Tests pass? | yes/no +| Fixed tickets | comma-separated list of tickets fixed by the PR, if any +| License | MIT +| Doc PR | reference to the documentation PR, if any diff --git a/.travis.yml b/.travis.yml index 6da2fb04da51c..50427f628e1f2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,9 @@ language: php sudo: false +git: + depth: 1 + addons: apt_packages: - parallel @@ -29,7 +32,9 @@ cache: services: mongodb before_install: + # Matrix lines for intermediate PHP versions are skipped for pull requests - if [[ ! $deps && ! $TRAVIS_PHP_VERSION = ${MIN_PHP%.*} && $TRAVIS_PHP_VERSION != hhvm && $TRAVIS_PULL_REQUEST != false ]]; then deps=skip; fi; + # A sigchild-enabled-PHP is used to test the Process component on the lowest PHP matrix line - if [[ ! $deps && $TRAVIS_PHP_VERSION = ${MIN_PHP%.*} && ! -d php-$MIN_PHP/sapi ]]; then wget http://museum.php.net/php5/php-$MIN_PHP.tar.bz2 -O - | tar -xj; (cd php-$MIN_PHP; ./configure --enable-sigchild --enable-pcntl; make -j2); fi; - if [[ $TRAVIS_PHP_VERSION != hhvm ]]; then INI_FILE=~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini; else INI_FILE=/etc/hhvm/php.ini; fi; - echo memory_limit = -1 >> $INI_FILE @@ -49,9 +54,12 @@ before_install: install: - if [[ $deps != skip ]]; then COMPONENTS=$(find src/Symfony -mindepth 3 -type f -name phpunit.xml.dist -printf '%h\n'); fi; + # Create local composer packages for each patched components and reference them in composer.json files when cross-testing components - if [[ $deps != skip && $deps ]]; then php .travis.php $TRAVIS_COMMIT_RANGE $TRAVIS_BRANCH $COMPONENTS; fi; + # For the master branch when deps=high, the version before master is checked out and tested with the locally patched components - if [[ $deps = high && $TRAVIS_BRANCH = master ]]; then SYMFONY_VERSION=$(git ls-remote --heads | grep -o '/[1-9].*' | tail -n 1 | sed s/.//); else SYMFONY_VERSION=$(cat composer.json | grep '^ *"dev-master". *"[1-9]' | grep -o '[0-9.]*'); fi; - if [[ $deps = high && $TRAVIS_BRANCH = master ]]; then git fetch origin $SYMFONY_VERSION; git checkout -m FETCH_HEAD; COMPONENTS=$(find src/Symfony -mindepth 3 -type f -name phpunit.xml.dist -printf '%h\n'); fi; + # Legacy tests are skipped when deps=high and when the current branch version has not the same major version number than the next one - if [[ $deps = high && ${SYMFONY_VERSION%.*} != $(git show $(git ls-remote --heads | grep -FA1 /$SYMFONY_VERSION | tail -n 1):composer.json | grep '^ *"dev-master". *"[1-9]' | grep -o '[0-9]*' | head -n 1) ]]; then LEGACY=,legacy; fi; - export COMPOSER_ROOT_VERSION=$SYMFONY_VERSION.x-dev; - if [[ ! $deps ]]; then composer update --prefer-dist; else export SYMFONY_DEPRECATIONS_HELPER=weak; fi; diff --git a/CHANGELOG-3.0.md b/CHANGELOG-3.0.md index 4f119cb3603da..0679502162dc1 100644 --- a/CHANGELOG-3.0.md +++ b/CHANGELOG-3.0.md @@ -7,6 +7,49 @@ in 3.0 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v3.0.0...v3.0.1 +* 3.0.3 (2016-02-28) + + * bug #17919 #17676 - making the proxy instantiation compatible with ProxyManager 2.x by detecting proxy features (Ocramius) + * bug #17947 Fix - #17676 (backport #17919 to 2.3) (Ocramius) + * bug #17942 Fix bug when using an private aliased factory service (WouterJ) + * bug #17798 [Form] Fix BC break by allowing 'choice_label' option to be 'false' in ChoiceType (HeahDude) + * bug #17542 ChoiceFormField of type "select" could be "disabled" (bouland) + * bug #17602 [HttpFoundation] Fix BinaryFileResponse incorrect behavior with if-range header (bburnichon) + * bug #17760 [Form] fix choice value "false" in ChoiceType (HeahDude) + * bug #17914 [Console] Fix escaping of trailing backslashes (nicolas-grekas) + * bug #17074 Fix constraint validator alias being required (Triiistan) + * bug #17866 [DependencyInjection] replace alias in factories (xabbuh) + * bug #17867 [DependencyInjection] replace alias in factory services (xabbuh) + * bug #17865 [FrameworkBundle] disable the assets helper when assets are disabled (xabbuh) + * bug #17860 Fixed the antialiasing of the toolbar text (javiereguiluz) + * bug #17569 [FrameworkBundle] read commands from bundles when accessing list (havvg) + * bug #16987 [FileSystem] Windows fix (flip111) + * bug #17787 [Form] Fix choice placeholder edge cases (Tobion) + * bug #17835 [Yaml] fix default timezone to be UTC (xabbuh) + * bug #17823 [DependencyInjection] fix dumped YAML string (xabbuh) + * bug #17818 [Console] InvalidArgumentException is thrown under wrong condition (robinkanters) + * bug #17819 [HttpKernel] Prevent a fatal error when DebugHandlersListener is used with a kernel with no terminateWithException() method (jakzal) + * bug #17814 [DependencyInjection] fix dumped YAML snytax (xabbuh) + * bug #17099 [Form] Fixed violation mapping if multiple forms are using the same (or part of the same) property path (alekitto) + * bug #17694 [DoctrineBridge] [Form] fix choice_value in EntityType (HeahDude) + * bug #17790 [Config] Fix EnumNodeDefinition to allow building enum nodes with one element (ogizanagi) + * bug #17729 [Yaml] properly parse lists in object maps (xabbuh) + * bug #17719 [DependencyInjection] fixed exceptions thrown by get method of ContainerBuilder (lukaszmakuch) + * bug #17742 [DependencyInjection] Fix #16461 Container::set() replace aliases (mnapoli) + * bug #17745 Added more exceptions to singularify method (javiereguiluz) + * bug #17691 Fixed (string) catchable fatal error for PHP Incomplete Class instances (yceruto) + * bug #17766 Fixed (string) catchable fatal error for PHP Incomplete Class instances (yceruto) + * bug #17757 [HttpFoundation] BinaryFileResponse sendContent return as parent. (2.3) (SpacePossum) + * bug #17748 [DomCrawler] Remove the overridden getHash() method to prevent problems when cloning the crawler (jakzal) + * bug #17725 [WebProfilerBundle] Add width attribute on SVG - Fix toolbar profiler on microsoft edge (AlexandrePavy) + * bug #17703 [FrameworkBundle] Support autowiring for TranslationInterface (dunglas) + * bug #17613 [WebProfiler] Fixed logo and menu profiler for Microsoft Edge (WhiteEagle88) + * bug #17702 [TwigBridge] forward compatibility with Yaml 3.1 (xabbuh) + * bug #17673 [Routing] add files used in FileResource objects (xabbuh) + * bug #17672 [DependencyInjection][Routing] add files used in FileResource objects (xabbuh) + * bug #17669 [Console] remove readline support (xabbuh) + * bug #17600 Fixed the Bootstrap form theme for inlined checkbox/radio (javiereguiluz) + * 3.0.2 (2016-02-03) * bug #17658 [FrameworkBundle] fix assets and templating tests (xabbuh) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 123d5aa755911..ae18925cb6e20 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,29 +5,20 @@ Symfony is an open source, community-driven project. If you'd like to contribute, please read the following documents: -* [Contributing Code][1]: The document index related to contributions; - -* [Submitting a Patch][2]: Guidelines for submitting a pull request; - -* [Pull Request Template][3]: Template header to use in your pull request - description; - -```markdown -| Q | A -| ------------- | --- -| Bug fix? | yes/no -| New feature? | yes/no -| BC breaks? | no -| Deprecations? | no -| Tests pass? | yes -| Fixed tickets | #1234 -| License | MIT -| Doc PR | symfony/symfony-docs#1234 -``` - -* [Backwards Compatibility][4]: Backward compatibility rules. - -[1]: https://symfony.com/doc/current/contributing/code/index.html -[2]: https://symfony.com/doc/current/contributing/code/patches.html#check-list -[3]: https://symfony.com/doc/current/contributing/code/patches.html#make-a-pull-request -[4]: https://symfony.com/doc/current/contributing/code/bc.html#working-on-symfony-code +* [Reporting a Bug][1] +* [Submitting a Patch][2] +* [Symfony Core Team][3] +* [Security Issues][4] +* [Running Symfony Tests][5] +* [Our Backwards Compatibility Promise][6] +* [Coding Standards][7] +* [Conventions][8] + +[1]: https://symfony.com/doc/current/contributing/code/bugs.html +[2]: https://symfony.com/doc/current/contributing/code/patches.html +[3]: https://symfony.com/doc/current/contributing/code/core_team.html +[4]: https://symfony.com/doc/current/contributing/code/security.html +[5]: https://symfony.com/doc/current/contributing/code/tests.html +[6]: https://symfony.com/doc/current/contributing/code/bc.html +[7]: https://symfony.com/doc/current/contributing/code/standards.html +[8]: https://symfony.com/doc/current/contributing/code/conventions.html diff --git a/appveyor.yml b/appveyor.yml index 6456c27916d13..ee7373076a745 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,6 +1,5 @@ build: false -shallow_clone: true -platform: x86 +clone_depth: 1 clone_folder: c:\projects\symfony cache: diff --git a/composer.json b/composer.json index 7fe4d1436a671..46f82d5990262 100644 --- a/composer.json +++ b/composer.json @@ -78,7 +78,7 @@ "doctrine/orm": "~2.4,>=2.4.5", "doctrine/doctrine-bundle": "~1.4", "monolog/monolog": "~1.11", - "ocramius/proxy-manager": "~0.4|~1.0", + "ocramius/proxy-manager": "~0.4|~1.0|~2.0", "egulias/email-validator": "~1.2", "symfony/polyfill-apcu": "~1.1", "symfony/security-acl": "~2.8|~3.0", diff --git a/phpunit b/phpunit index dba1222189066..9cf03f071ecbf 100755 --- a/phpunit +++ b/phpunit @@ -160,8 +160,8 @@ if (isset($argv[1]) && 'symfony' === $argv[1]) { unlink($file); } - // Fail on any individual component failures but ignore STATUS_STACK_BUFFER_OVERRUN (-1073740791) on Windows when APCu is enabled - if ($procStatus && ('\\' !== DIRECTORY_SEPARATOR || !extension_loaded('apcu') || !ini_get('apc.enable_cli') || -1073740791 !== $procStatus)) { + // Fail on any individual component failures but ignore STATUS_STACK_BUFFER_OVERRUN (-1073740791/0xC0000409) and STATUS_ACCESS_VIOLATION (-1073741819/0xC0000005) on Windows when APCu is enabled + if ($procStatus && ('\\' !== DIRECTORY_SEPARATOR || !extension_loaded('apcu') || !ini_get('apc.enable_cli') || (-1073740791 !== $procStatus && -1073741819 !== $procStatus))) { $exit = $procStatus; echo "\033[41mKO\033[0m $component\n\n"; } else { diff --git a/src/Symfony/Bridge/Doctrine/Form/ChoiceList/DoctrineChoiceLoader.php b/src/Symfony/Bridge/Doctrine/Form/ChoiceList/DoctrineChoiceLoader.php index 1a09609b28556..2dc8c2cb2b28d 100644 --- a/src/Symfony/Bridge/Doctrine/Form/ChoiceList/DoctrineChoiceLoader.php +++ b/src/Symfony/Bridge/Doctrine/Form/ChoiceList/DoctrineChoiceLoader.php @@ -146,7 +146,7 @@ public function loadChoicesForValues(array $values, $value = null) // Optimize performance in case we have an object loader and // a single-field identifier - if (!$this->choiceList && $this->objectLoader && $this->idReader->isSingleId()) { + if (null === $value && !$this->choiceList && $this->objectLoader && $this->idReader->isSingleId()) { $unorderedObjects = $this->objectLoader->getEntitiesByIds($this->idReader->getIdField(), $values); $objectsById = array(); $objects = array(); diff --git a/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php b/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php index 0303c355c055b..5b12c5bdcacab 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php @@ -753,6 +753,55 @@ public function testOverrideChoices() $this->assertSame('2', $field->getViewData()); } + public function testOverrideChoicesValues() + { + $entity1 = new SingleIntIdEntity(1, 'Foo'); + $entity2 = new SingleIntIdEntity(2, 'Bar'); + + $this->persist(array($entity1, $entity2)); + + $field = $this->factory->createNamed('name', 'Symfony\Bridge\Doctrine\Form\Type\EntityType', null, array( + 'em' => 'default', + 'class' => self::SINGLE_IDENT_CLASS, + 'choice_label' => 'name', + 'choice_value' => 'name', + )); + + $field->submit('Bar'); + + $this->assertEquals(array('Foo' => new ChoiceView($entity1, 'Foo', 'Foo'), 'Bar' => new ChoiceView($entity2, 'Bar', 'Bar')), $field->createView()->vars['choices']); + $this->assertTrue($field->isSynchronized(), 'Field should be synchronized.'); + $this->assertSame($entity2, $field->getData(), 'Entity should be loaded by custom value.'); + $this->assertSame('Bar', $field->getViewData()); + } + + public function testOverrideChoicesValuesWithCallable() + { + $entity1 = new GroupableEntity(1, 'Foo', 'BazGroup'); + $entity2 = new GroupableEntity(2, 'Bar', 'BooGroup'); + + $this->persist(array($entity1, $entity2)); + + $field = $this->factory->createNamed('name', 'Symfony\Bridge\Doctrine\Form\Type\EntityType', null, array( + 'em' => 'default', + 'class' => self::ITEM_GROUP_CLASS, + 'choice_label' => 'name', + 'choice_value' => function (GroupableEntity $entity) { + return $entity->groupName.'/'.$entity->name; + }, + )); + + $field->submit('BooGroup/Bar'); + + $this->assertEquals(array( + 'BazGroup/Foo' => new ChoiceView($entity1, 'BazGroup/Foo', 'Foo'), + 'BooGroup/Bar' => new ChoiceView($entity2, 'BooGroup/Bar', 'Bar'), + ), $field->createView()->vars['choices']); + $this->assertTrue($field->isSynchronized(), 'Field should be synchronized.'); + $this->assertSame($entity2, $field->getData(), 'Entity should be loaded by custom value.'); + $this->assertSame('BooGroup/Bar', $field->getViewData()); + } + public function testGroupByChoices() { $item1 = new GroupableEntity(1, 'Foo', 'Group1'); diff --git a/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php b/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php index 550786d5d716a..cf2520a371549 100644 --- a/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php +++ b/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php @@ -74,10 +74,16 @@ public function getProxyFactoryCode(Definition $definition, $id) $methodName = 'get'.Container::camelize($id).'Service'; $proxyClass = $this->getProxyClassName($definition); + $generatedClass = $this->generateProxyClass($definition); + + $constructorCall = $generatedClass->hasMethod('staticProxyConstructor') + ? $proxyClass.'::staticProxyConstructor' + : 'new '.$proxyClass; + return <<$methodName(false); @@ -97,11 +103,7 @@ function (&\$wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface \$proxy) */ public function getProxyCode(Definition $definition) { - $generatedClass = new ClassGenerator($this->getProxyClassName($definition)); - - $this->proxyGenerator->generate(new \ReflectionClass($definition->getClass()), $generatedClass); - - return $this->classGenerator->generate($generatedClass); + return $this->classGenerator->generate($this->generateProxyClass($definition)); } /** @@ -115,4 +117,16 @@ private function getProxyClassName(Definition $definition) { return str_replace('\\', '', $definition->getClass()).'_'.spl_object_hash($definition).$this->salt; } + + /** + * @return ClassGenerator + */ + private function generateProxyClass(Definition $definition) + { + $generatedClass = new ClassGenerator($this->getProxyClassName($definition)); + + $this->proxyGenerator->generate(new \ReflectionClass($definition->getClass()), $generatedClass); + + return $generatedClass; + } } diff --git a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Dumper/PhpDumperTest.php b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Dumper/PhpDumperTest.php index 412674ee3f680..789799bce6e19 100644 --- a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Dumper/PhpDumperTest.php +++ b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Dumper/PhpDumperTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bridge\ProxyManager\Tests\LazyProxy\Dumper; +use ProxyManager\ProxyGenerator\LazyLoading\MethodGenerator\StaticProxyConstructor; use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Dumper\PhpDumper; @@ -49,7 +50,11 @@ public function testDumpContainerWithProxyService() */ public function testDumpContainerWithProxyServiceWillShareProxies() { - require_once __DIR__.'/../Fixtures/php/lazy_service.php'; + if (class_exists(StaticProxyConstructor::class)) { // detecting ProxyManager v2 + require_once __DIR__.'/../Fixtures/php/lazy_service_with_hints.php'; + } else { + require_once __DIR__.'/../Fixtures/php/lazy_service.php'; + } $container = new \LazyServiceProjectServiceContainer(); diff --git a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/php/lazy_service_structure.txt b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/php/lazy_service_structure.txt index 7bd36c13ef6a2..9b73cdeb70ca2 100644 --- a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/php/lazy_service_structure.txt +++ b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/php/lazy_service_structure.txt @@ -7,7 +7,7 @@ class ProjectServiceContainer extends Container { if ($lazyLoad) { - return $this->services['foo'] = new stdClass_%s( + return $this->services['foo'] =%sstdClass_%s( function (&$wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface $proxy) { $wrappedInstance = $this->getFooService(false); @@ -22,5 +22,5 @@ class ProjectServiceContainer extends Container } } -class stdClass_%s extends \stdClass implements \ProxyManager\Proxy\VirtualProxyInterface +class stdClass_%s extends \stdClass implements \ProxyManager\%s {%a}%A diff --git a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/php/lazy_service_with_hints.php b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/php/lazy_service_with_hints.php new file mode 100644 index 0000000000000..e786523121b8e --- /dev/null +++ b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/php/lazy_service_with_hints.php @@ -0,0 +1,187 @@ +services = array(); + } + + /** + * Gets the 'foo' service. + * + * This service is shared. + * This method always returns the same instance of the service. + * + * @param bool $lazyLoad whether to try lazy-loading the service with a proxy + * + * @return stdClass A stdClass instance. + */ + public function getFooService($lazyLoad = true) + { + if ($lazyLoad) { + return $this->services['foo'] = new stdClass_c1d194250ee2e2b7d2eab8b8212368a8( + function (&$wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface $proxy) { + $wrappedInstance = $this->getFooService(false); + + $proxy->setProxyInitializer(null); + + return true; + } + ); + } + + return new \stdClass(); + } +} + +class stdClass_c1d194250ee2e2b7d2eab8b8212368a8 extends \stdClass implements \ProxyManager\Proxy\LazyLoadingInterface, \ProxyManager\Proxy\ValueHolderInterface +{ + /** + * @var \Closure|null initializer responsible for generating the wrapped object + */ + private $valueHolder5157dd96e88c0 = null; + + /** + * @var \Closure|null initializer responsible for generating the wrapped object + */ + private $initializer5157dd96e8924 = null; + + /** + * @override constructor for lazy initialization + * + * @param \Closure|null $initializer + */ + public function __construct($initializer) + { + $this->initializer5157dd96e8924 = $initializer; + } + + /** + * @param string $name + */ + public function __get($name) + { + $this->initializer5157dd96e8924 && $this->initializer5157dd96e8924->__invoke($this->valueHolder5157dd96e88c0, $this, '__get', array('name' => $name)); + + return $this->valueHolder5157dd96e88c0->$name; + } + + /** + * @param string $name + * @param mixed $value + */ + public function __set($name, $value) + { + $this->initializer5157dd96e8924 && $this->initializer5157dd96e8924->__invoke($this->valueHolder5157dd96e88c0, $this, '__set', array('name' => $name, 'value' => $value)); + + $this->valueHolder5157dd96e88c0->$name = $value; + } + + /** + * @param string $name + * + * @return bool + */ + public function __isset($name) + { + $this->initializer5157dd96e8924 && $this->initializer5157dd96e8924->__invoke($this->valueHolder5157dd96e88c0, $this, '__isset', array('name' => $name)); + + return isset($this->valueHolder5157dd96e88c0->$name); + } + + /** + * @param string $name + */ + public function __unset($name) + { + $this->initializer5157dd96e8924 && $this->initializer5157dd96e8924->__invoke($this->valueHolder5157dd96e88c0, $this, '__unset', array('name' => $name)); + + unset($this->valueHolder5157dd96e88c0->$name); + } + + /** + * + */ + public function __clone() + { + $this->initializer5157dd96e8924 && $this->initializer5157dd96e8924->__invoke($this->valueHolder5157dd96e88c0, $this, '__clone', array()); + + $this->valueHolder5157dd96e88c0 = clone $this->valueHolder5157dd96e88c0; + } + + /** + * + */ + public function __sleep() + { + $this->initializer5157dd96e8924 && $this->initializer5157dd96e8924->__invoke($this->valueHolder5157dd96e88c0, $this, '__sleep', array()); + + return array('valueHolder5157dd96e88c0'); + } + + /** + * + */ + public function __wakeup() + { + } + + /** + * {@inheritdoc} + */ + public function setProxyInitializer(\Closure $initializer = null) + { + $this->initializer5157dd96e8924 = $initializer; + } + + /** + * {@inheritdoc} + */ + public function getProxyInitializer() + { + return $this->initializer5157dd96e8924; + } + + /** + * {@inheritdoc} + */ + public function initializeProxy() : bool + { + return $this->initializer5157dd96e8924 && $this->initializer5157dd96e8924->__invoke($this->valueHolder5157dd96e88c0, $this, 'initializeProxy', array()); + } + + /** + * {@inheritdoc} + */ + public function isProxyInitialized() : bool + { + return null !== $this->valueHolder5157dd96e88c0; + } + + /** + * {@inheritdoc} + */ + public function getWrappedValueHolderValue() + { + return $this->valueHolder5157dd96e88c0; + } +} diff --git a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php index 52f83e8db4c90..de7f9ea221a7e 100644 --- a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php +++ b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php @@ -69,7 +69,7 @@ public function testGetProxyFactoryCode() $code = $this->dumper->getProxyFactoryCode($definition, 'foo'); $this->assertStringMatchesFormat( - '%wif ($lazyLoad) {%wreturn $this->services[\'foo\'] = new ' + '%wif ($lazyLoad) {%wreturn $this->services[\'foo\'] =%s' .'SymfonyBridgeProxyManagerTestsLazyProxyPhpDumperProxyDumperTest_%s(%wfunction ' .'(&$wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface $proxy) {' .'%w$wrappedInstance = $this->getFooService(false);%w$proxy->setProxyInitializer(null);' diff --git a/src/Symfony/Bridge/ProxyManager/composer.json b/src/Symfony/Bridge/ProxyManager/composer.json index e91f237825ad4..b9020dc30c3ea 100644 --- a/src/Symfony/Bridge/ProxyManager/composer.json +++ b/src/Symfony/Bridge/ProxyManager/composer.json @@ -18,7 +18,7 @@ "require": { "php": ">=5.5.9", "symfony/dependency-injection": "~2.8|~3.0", - "ocramius/proxy-manager": "~0.4|~1.0" + "ocramius/proxy-manager": "~0.4|~1.0|~2.0" }, "require-dev": { "symfony/config": "~2.8|~3.0" diff --git a/src/Symfony/Bridge/Twig/Extension/YamlExtension.php b/src/Symfony/Bridge/Twig/Extension/YamlExtension.php index fc9bf0e9e3308..2d46795b4a81e 100644 --- a/src/Symfony/Bridge/Twig/Extension/YamlExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/YamlExtension.php @@ -12,6 +12,7 @@ namespace Symfony\Bridge\Twig\Extension; use Symfony\Component\Yaml\Dumper as YamlDumper; +use Symfony\Component\Yaml\Yaml; /** * Provides integration of the Yaml component with Twig. @@ -39,6 +40,10 @@ public function encode($input, $inline = 0, $dumpObjects = false) $dumper = new YamlDumper(); } + if (defined('Symfony\Component\Yaml\Yaml::DUMP_OBJECT')) { + return $dumper->dump($input, $inline, 0, is_bool($dumpObjects) ? Yaml::DUMP_OBJECT : 0); + } + return $dumper->dump($input, $inline, 0, false, $dumpObjects); } diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig index 5affc7a6a1b92..dfb1965ca1048 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig @@ -115,7 +115,7 @@ {%- endblock choice_widget_expanded %} {% block checkbox_widget -%} - {% set parent_label_class = parent_label_class|default('') -%} + {%- set parent_label_class = parent_label_class|default(label_attr.class|default('')) -%} {% if 'checkbox-inline' in parent_label_class %} {{- form_label(form, null, { widget: parent() }) -}} {% else -%} @@ -126,7 +126,7 @@ {%- endblock checkbox_widget %} {% block radio_widget -%} - {%- set parent_label_class = parent_label_class|default('') -%} + {%- set parent_label_class = parent_label_class|default(label_attr.class|default('')) -%} {% if 'radio-inline' in parent_label_class %} {{- form_label(form, null, { widget: parent() }) -}} {% else -%} diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig index 20c6e02c7ec01..63104def7d3eb 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig @@ -52,7 +52,7 @@ {%- endblock choice_widget_expanded -%} {%- block choice_widget_collapsed -%} - {%- if required and placeholder is none and not placeholder_in_choices and not multiple -%} + {%- if required and placeholder is none and not placeholder_in_choices and not multiple and (attr.size is not defined or attr.size <= 1) -%} {% set required = false %} {%- endif -%} block($form, 'widget_attributes', array( @@ -7,7 +7,7 @@ )) ?> multiple="multiple" > - + 0): ?> block($form, 'choice_widget_options', array('choices' => $preferred_choices)) ?> 0 && null !== $separator): ?> diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/ApplicationTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/ApplicationTest.php index 612d6325dd26d..fc0e7654db2ca 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/ApplicationTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/ApplicationTest.php @@ -11,8 +11,9 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Console; -use Symfony\Bundle\FrameworkBundle\Tests\TestCase; use Symfony\Bundle\FrameworkBundle\Console\Application; +use Symfony\Bundle\FrameworkBundle\Tests\TestCase; +use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Output\NullOutput; use Symfony\Component\Console\Tester\ApplicationTester; @@ -23,7 +24,7 @@ public function testBundleInterfaceImplementation() { $bundle = $this->getMock('Symfony\Component\HttpKernel\Bundle\BundleInterface'); - $kernel = $this->getKernel(array($bundle)); + $kernel = $this->getKernel(array($bundle), true); $application = new Application($kernel); $application->doRun(new ArrayInput(array('list')), new NullOutput()); @@ -34,10 +35,73 @@ public function testBundleCommandsAreRegistered() $bundle = $this->getMock('Symfony\Component\HttpKernel\Bundle\Bundle'); $bundle->expects($this->once())->method('registerCommands'); - $kernel = $this->getKernel(array($bundle)); + $kernel = $this->getKernel(array($bundle), true); $application = new Application($kernel); $application->doRun(new ArrayInput(array('list')), new NullOutput()); + + // Calling twice: registration should only be done once. + $application->doRun(new ArrayInput(array('list')), new NullOutput()); + } + + public function testBundleCommandsAreRetrievable() + { + $bundle = $this->getMock('Symfony\Component\HttpKernel\Bundle\Bundle'); + $bundle->expects($this->once())->method('registerCommands'); + + $kernel = $this->getKernel(array($bundle)); + + $application = new Application($kernel); + $application->all(); + + // Calling twice: registration should only be done once. + $application->all(); + } + + public function testBundleSingleCommandIsRetrievable() + { + $bundle = $this->getMock('Symfony\Component\HttpKernel\Bundle\Bundle'); + $bundle->expects($this->once())->method('registerCommands'); + + $kernel = $this->getKernel(array($bundle)); + + $application = new Application($kernel); + + $command = new Command('example'); + $application->add($command); + + $this->assertSame($command, $application->get('example')); + } + + public function testBundleCommandCanBeFound() + { + $bundle = $this->getMock('Symfony\Component\HttpKernel\Bundle\Bundle'); + $bundle->expects($this->once())->method('registerCommands'); + + $kernel = $this->getKernel(array($bundle)); + + $application = new Application($kernel); + + $command = new Command('example'); + $application->add($command); + + $this->assertSame($command, $application->find('example')); + } + + public function testBundleCommandCanBeFoundByAlias() + { + $bundle = $this->getMock('Symfony\Component\HttpKernel\Bundle\Bundle'); + $bundle->expects($this->once())->method('registerCommands'); + + $kernel = $this->getKernel(array($bundle)); + + $application = new Application($kernel); + + $command = new Command('example'); + $command->setAliases(array('alias')); + $application->add($command); + + $this->assertSame($command, $application->find('alias')); } public function testBundleCommandsHaveRightContainer() @@ -46,7 +110,7 @@ public function testBundleCommandsHaveRightContainer() $command->setCode(function () {}); $command->expects($this->exactly(2))->method('setContainer'); - $application = new Application($this->getKernel(array())); + $application = new Application($this->getKernel(array(), true)); $application->setAutoExit(false); $application->setCatchExceptions(false); $application->add($command); @@ -59,21 +123,23 @@ public function testBundleCommandsHaveRightContainer() $tester->run(array('command' => 'foo')); } - private function getKernel(array $bundles) + private function getKernel(array $bundles, $useDispatcher = false) { - $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); - $dispatcher - ->expects($this->atLeastOnce()) - ->method('dispatch') - ; - $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface'); - $container - ->expects($this->atLeastOnce()) - ->method('get') - ->with($this->equalTo('event_dispatcher')) - ->will($this->returnValue($dispatcher)) - ; + + if ($useDispatcher) { + $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); + $dispatcher + ->expects($this->atLeastOnce()) + ->method('dispatch') + ; + $container + ->expects($this->atLeastOnce()) + ->method('get') + ->with($this->equalTo('event_dispatcher')) + ->will($this->returnValue($dispatcher)); + } + $container ->expects($this->once()) ->method('hasParameter') diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddConstraintValidatorsPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddConstraintValidatorsPassTest.php new file mode 100644 index 0000000000000..0629d1ebafd1f --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddConstraintValidatorsPassTest.php @@ -0,0 +1,87 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddConstraintValidatorsPass; + +class AddConstraintValidatorsPassTest extends \PHPUnit_Framework_TestCase +{ + public function testThatConstraintValidatorServicesAreProcessed() + { + $services = array( + 'my_constraint_validator_service1' => array(0 => array('alias' => 'my_constraint_validator_alias1')), + 'my_constraint_validator_service2' => array(), + ); + + $validatorFactoryDefinition = $this->getMock('Symfony\Component\DependencyInjection\Definition'); + $container = $this->getMock( + 'Symfony\Component\DependencyInjection\ContainerBuilder', + array('findTaggedServiceIds', 'getDefinition', 'hasDefinition') + ); + + $validatorDefinition1 = $this->getMock('Symfony\Component\DependencyInjection\Definition', array('getClass')); + $validatorDefinition2 = $this->getMock('Symfony\Component\DependencyInjection\Definition', array('getClass')); + + $validatorDefinition1->expects($this->atLeastOnce()) + ->method('getClass') + ->willReturn('My\Fully\Qualified\Class\Named\Validator1'); + $validatorDefinition2->expects($this->atLeastOnce()) + ->method('getClass') + ->willReturn('My\Fully\Qualified\Class\Named\Validator2'); + + $container->expects($this->any()) + ->method('getDefinition') + ->with($this->anything()) + ->will($this->returnValueMap(array( + array('my_constraint_validator_service1', $validatorDefinition1), + array('my_constraint_validator_service2', $validatorDefinition2), + array('validator.validator_factory', $validatorFactoryDefinition), + ))); + + $container->expects($this->atLeastOnce()) + ->method('findTaggedServiceIds') + ->will($this->returnValue($services)); + $container->expects($this->atLeastOnce()) + ->method('hasDefinition') + ->with('validator.validator_factory') + ->will($this->returnValue(true)); + + $validatorFactoryDefinition->expects($this->once()) + ->method('replaceArgument') + ->with(1, array( + 'My\Fully\Qualified\Class\Named\Validator1' => 'my_constraint_validator_service1', + 'my_constraint_validator_alias1' => 'my_constraint_validator_service1', + 'My\Fully\Qualified\Class\Named\Validator2' => 'my_constraint_validator_service2', + )); + + $addConstraintValidatorsPass = new AddConstraintValidatorsPass(); + $addConstraintValidatorsPass->process($container); + } + + public function testThatCompilerPassIsIgnoredIfThereIsNoConstraintValidatorFactoryDefinition() + { + $definition = $this->getMock('Symfony\Component\DependencyInjection\Definition'); + $container = $this->getMock( + 'Symfony\Component\DependencyInjection\ContainerBuilder', + array('hasDefinition', 'findTaggedServiceIds', 'getDefinition') + ); + + $container->expects($this->never())->method('findTaggedServiceIds'); + $container->expects($this->never())->method('getDefinition'); + $container->expects($this->atLeastOnce()) + ->method('hasDefinition') + ->with('validator.validator_factory') + ->will($this->returnValue(false)); + $definition->expects($this->never())->method('replaceArgument'); + + $addConstraintValidatorsPass = new AddConstraintValidatorsPass(); + $addConstraintValidatorsPass->process($container); + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/templating_no_assets.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/templating_no_assets.php new file mode 100644 index 0000000000000..bf12a8bc47e5f --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/templating_no_assets.php @@ -0,0 +1,7 @@ +loadFromExtension('framework', array( + 'templating' => array( + 'engines' => array('php', 'twig'), + ), +)); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/templating_php_assets_disabled.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/templating_php_assets_disabled.php new file mode 100644 index 0000000000000..535a9a2e99c96 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/templating_php_assets_disabled.php @@ -0,0 +1,8 @@ +loadFromExtension('framework', array( + 'assets' => false, + 'templating' => array( + 'engines' => array('php'), + ), +)); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/templating_no_assets.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/templating_no_assets.xml new file mode 100644 index 0000000000000..d579ed4c0a181 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/templating_no_assets.xml @@ -0,0 +1,14 @@ + + + + + + php + twig + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/assets.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/assets.yml index d3285ff58102c..ba87d98b42ba6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/assets.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/assets.yml @@ -1,7 +1,7 @@ framework: assets: version: SomeVersionScheme - version_format: %%s?version=%%s + version_format: '%%s?version=%%s' base_urls: http://cdn.example.com packages: images_path: @@ -11,7 +11,7 @@ framework: base_urls: ["http://images1.example.com", "http://images2.example.com"] foo: version: 1.0.0 - version_format: %%s-%%s + version_format: '%%s-%%s' bar: base_urls: ["https://bar2.example.com"] bar_null_version: diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml index 1c49d145f1c14..64bb38cb44682 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml @@ -13,7 +13,7 @@ framework: only_exceptions: true enabled: false router: - resource: %kernel.root_dir%/config/routing.xml + resource: '%kernel.root_dir%/config/routing.xml' type: xml session: storage_id: session.storage.native @@ -48,7 +48,7 @@ framework: annotations: cache: file debug: true - file_cache_dir: %kernel.cache_dir%/annotations + file_cache_dir: '%kernel.cache_dir%/annotations' serializer: enabled: true enable_annotations: true diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/templating_no_assets.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/templating_no_assets.yml new file mode 100644 index 0000000000000..393477aeb49ac --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/templating_no_assets.yml @@ -0,0 +1,3 @@ +framework: + templating: + engines: [php, twig] diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/templating_php_assets_disabled.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/templating_php_assets_disabled.yml new file mode 100644 index 0000000000000..7ef6b3e57c292 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/templating_php_assets_disabled.yml @@ -0,0 +1,4 @@ +framework: + assets: false + templating: + engines: [php] diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index e655b52654d2c..a8aced55dd7fa 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -436,14 +436,21 @@ public function testAssetHelperWhenAssetsAreEnabled() $this->assertSame('assets.packages', (string) $packages); } - public function testAssetHelperWhenTemplatesAreEnabledAndAssetsAreDisabled() + public function testAssetHelperWhenTemplatesAreEnabledAndNoAssetsConfiguration() { - $container = $this->createContainerFromFile('full'); + $container = $this->createContainerFromFile('templating_no_assets'); $packages = $container->getDefinition('templating.helper.assets')->getArgument(0); $this->assertSame('assets.packages', (string) $packages); } + public function testAssetsHelperIsRemovedWhenPhpTemplatingEngineIsEnabledAndAssetsAreDisabled() + { + $container = $this->createContainerFromFile('templating_php_assets_disabled'); + + $this->assertTrue(!$container->has('templating.helper.assets'), 'The templating.helper.assets helper service is removed when assets are disabled.'); + } + public function testAssetHelperWhenAssetsAndTemplatesAreDisabled() { $container = $this->createContainerFromFile('default_config'); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/XmlFrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/XmlFrameworkExtensionTest.php index 2c27eb0325112..03401e2482942 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/XmlFrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/XmlFrameworkExtensionTest.php @@ -22,4 +22,9 @@ protected function loadFromFile(ContainerBuilder $container, $file) $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/Fixtures/xml')); $loader->load($file.'.xml'); } + + public function testAssetsHelperIsRemovedWhenPhpTemplatingEngineIsEnabledAndAssetsAreDisabled() + { + $this->markTestSkipped('The assets key cannot be set to false using the XML configuration format.'); + } } diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/icon.svg b/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/icon.svg index 02033fdc7f5e9..5bd2f3b8f3799 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/icon.svg +++ b/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/icon.svg @@ -1,3 +1,3 @@ - + diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/config/twig.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/config/twig.yml index 861b1e709fd13..61c1a54d99ba5 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/config/twig.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/config/twig.yml @@ -3,5 +3,5 @@ framework: # Twig Configuration twig: - debug: %kernel.debug% - strict_variables: %kernel.debug% + debug: '%kernel.debug%' + strict_variables: '%kernel.debug%' diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/ajax.svg b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/ajax.svg index d8cad847d4710..bd878c3c6c21f 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/ajax.svg +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/ajax.svg @@ -1,4 +1,4 @@ - + + diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/config.svg b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/config.svg index 9bafe3830175f..a407719e8c761 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/config.svg +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/config.svg @@ -1,3 +1,3 @@ - + diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/event.svg b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/event.svg index 7d15a66f01033..898117ef94558 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/event.svg +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/event.svg @@ -1,4 +1,4 @@ - + + + + + diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/menu.svg b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/menu.svg index 856ea09ff85cb..51870801cf284 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/menu.svg +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/menu.svg @@ -1,3 +1,3 @@ - + diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/no.svg b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/no.svg index 02eb4e9c6abbb..c0bb768d40433 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/no.svg +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/no.svg @@ -1,4 +1,4 @@ - + diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/request.svg b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/request.svg index d74a72850dc04..68b092c6b8809 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/request.svg +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/request.svg @@ -1,4 +1,4 @@ - + + + + + diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/translation.svg b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/translation.svg index 93d42327ed859..b7aa1249304b2 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/translation.svg +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/translation.svg @@ -1,4 +1,4 @@ - + + diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/yes.svg b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/yes.svg index 0f129bffc21b0..da650231d520d 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/yes.svg +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/yes.svg @@ -1,4 +1,4 @@ - + diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/profiler.css.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/profiler.css.twig index 77db944870255..6e07edeb3f2a0 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/profiler.css.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/profiler.css.twig @@ -588,6 +588,7 @@ tr.status-warning td { #menu-profiler { margin: 0; padding: 0; + list-style-type: none; } #menu-profiler li { position: relative; diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig index cade19d0b4c1a..5dd26a41eb9fa 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig @@ -47,6 +47,10 @@ text-align: left; text-transform: none; z-index: 99999; + + /* neutralize the aliasing defined by external CSS styles */ + -webkit-font-smoothing: subpixel-antialiased; + -moz-osx-font-smoothing: auto; } .sf-toolbarreset abbr { border: dashed #777; diff --git a/src/Symfony/Component/Config/Definition/Builder/EnumNodeDefinition.php b/src/Symfony/Component/Config/Definition/Builder/EnumNodeDefinition.php index dc25fcbd26f26..5d3ff014f1823 100644 --- a/src/Symfony/Component/Config/Definition/Builder/EnumNodeDefinition.php +++ b/src/Symfony/Component/Config/Definition/Builder/EnumNodeDefinition.php @@ -31,8 +31,8 @@ public function values(array $values) { $values = array_unique($values); - if (count($values) <= 1) { - throw new \InvalidArgumentException('->values() must be called with at least two distinct values.'); + if (empty($values)) { + throw new \InvalidArgumentException('->values() must be called with at least one value.'); } $this->values = $values; diff --git a/src/Symfony/Component/Config/Tests/Definition/Builder/EnumNodeDefinitionTest.php b/src/Symfony/Component/Config/Tests/Definition/Builder/EnumNodeDefinitionTest.php index 69f7fcfb22e9a..8d7ab2f7f03e9 100644 --- a/src/Symfony/Component/Config/Tests/Definition/Builder/EnumNodeDefinitionTest.php +++ b/src/Symfony/Component/Config/Tests/Definition/Builder/EnumNodeDefinitionTest.php @@ -15,14 +15,22 @@ class EnumNodeDefinitionTest extends \PHPUnit_Framework_TestCase { - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage ->values() must be called with at least two distinct values. - */ - public function testNoDistinctValues() + public function testWithOneValue() + { + $def = new EnumNodeDefinition('foo'); + $def->values(array('foo')); + + $node = $def->getNode(); + $this->assertEquals(array('foo'), $node->getValues()); + } + + public function testWithOneDistinctValue() { $def = new EnumNodeDefinition('foo'); $def->values(array('foo', 'foo')); + + $node = $def->getNode(); + $this->assertEquals(array('foo'), $node->getValues()); } /** @@ -35,6 +43,16 @@ public function testNoValuesPassed() $def->getNode(); } + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage ->values() must be called with at least one value. + */ + public function testWithNoValues() + { + $def = new EnumNodeDefinition('foo'); + $def->values(array()); + } + public function testGetNode() { $def = new EnumNodeDefinition('foo'); diff --git a/src/Symfony/Component/Config/Tests/Definition/Builder/TreeBuilderTest.php b/src/Symfony/Component/Config/Tests/Definition/Builder/TreeBuilderTest.php index 00e27c630a1dc..a146e89c32ae8 100644 --- a/src/Symfony/Component/Config/Tests/Definition/Builder/TreeBuilderTest.php +++ b/src/Symfony/Component/Config/Tests/Definition/Builder/TreeBuilderTest.php @@ -120,7 +120,7 @@ public function testDefinitionExampleGetsTransferredToNode() $tree = $builder->buildTree(); $children = $tree->getChildren(); - $this->assertTrue(is_array($tree->getExample())); + $this->assertInternalType('array', $tree->getExample()); $this->assertEquals('example', $children['child']->getExample()); } } diff --git a/src/Symfony/Component/Config/Tests/Resource/DirectoryResourceTest.php b/src/Symfony/Component/Config/Tests/Resource/DirectoryResourceTest.php index 2bbaadc3a721e..0e64b4ce80917 100644 --- a/src/Symfony/Component/Config/Tests/Resource/DirectoryResourceTest.php +++ b/src/Symfony/Component/Config/Tests/Resource/DirectoryResourceTest.php @@ -19,7 +19,7 @@ class DirectoryResourceTest extends \PHPUnit_Framework_TestCase protected function setUp() { - $this->directory = sys_get_temp_dir().'/symfonyDirectoryIterator'; + $this->directory = sys_get_temp_dir().DIRECTORY_SEPARATOR.'symfonyDirectoryIterator'; if (!file_exists($this->directory)) { mkdir($this->directory); } diff --git a/src/Symfony/Component/Config/composer.json b/src/Symfony/Component/Config/composer.json index d686929699913..81edb12fd00f3 100644 --- a/src/Symfony/Component/Config/composer.json +++ b/src/Symfony/Component/Config/composer.json @@ -19,6 +19,9 @@ "php": ">=5.5.9", "symfony/filesystem": "~2.8|~3.0" }, + "suggest": { + "symfony/yaml": "To use the yaml reference dumper" + }, "autoload": { "psr-4": { "Symfony\\Component\\Config\\": "" }, "exclude-from-classmap": [ diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index 41c6657e0862a..a01d66952e3ef 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -424,7 +424,7 @@ public function has($name) public function getNamespaces() { $namespaces = array(); - foreach ($this->commands as $command) { + foreach ($this->all() as $command) { $namespaces = array_merge($namespaces, $this->extractAllNamespaces($command->getName())); foreach ($command->getAliases() as $alias) { diff --git a/src/Symfony/Component/Console/CHANGELOG.md b/src/Symfony/Component/Console/CHANGELOG.md index 4e29d2ed4517d..8021068edfb13 100644 --- a/src/Symfony/Component/Console/CHANGELOG.md +++ b/src/Symfony/Component/Console/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +2.8.3 +----- + + * remove readline support from the question helper as it caused issues + 2.8.0 ----- diff --git a/src/Symfony/Component/Console/Command/Command.php b/src/Symfony/Component/Console/Command/Command.php index cb870939b1cf3..c8429845a2634 100644 --- a/src/Symfony/Component/Console/Command/Command.php +++ b/src/Symfony/Component/Console/Command/Command.php @@ -383,7 +383,7 @@ public function addArgument($name, $mode = null, $description = '', $default = n * @param string $shortcut The shortcut (can be null) * @param int $mode The option mode: One of the InputOption::VALUE_* constants * @param string $description A description text - * @param mixed $default The default value (must be null for InputOption::VALUE_REQUIRED or InputOption::VALUE_NONE) + * @param mixed $default The default value (must be null for InputOption::VALUE_NONE) * * @return Command The current instance */ diff --git a/src/Symfony/Component/Console/Formatter/OutputFormatter.php b/src/Symfony/Component/Console/Formatter/OutputFormatter.php index 244e25c61fbb6..56cd5e568f16d 100644 --- a/src/Symfony/Component/Console/Formatter/OutputFormatter.php +++ b/src/Symfony/Component/Console/Formatter/OutputFormatter.php @@ -33,7 +33,15 @@ class OutputFormatter implements OutputFormatterInterface */ public static function escape($text) { - return preg_replace('/([^\\\\]?)#ix", $message, $matches, PREG_OFFSET_CAPTURE); foreach ($matches[0] as $i => $match) { $pos = $match[1]; @@ -166,6 +174,10 @@ public function format($message) $output .= $this->applyCurrentStyle(substr($message, $offset)); + if (false !== strpos($output, '<<')) { + return strtr($output, array('\\<' => '<', '<<' => '\\')); + } + return str_replace('\\<', '<', $output); } diff --git a/src/Symfony/Component/Console/Helper/QuestionHelper.php b/src/Symfony/Component/Console/Helper/QuestionHelper.php index 15b7cd6891e7c..c6f5a409c3dc8 100644 --- a/src/Symfony/Component/Console/Helper/QuestionHelper.php +++ b/src/Symfony/Component/Console/Helper/QuestionHelper.php @@ -130,7 +130,11 @@ private function doAsk(OutputInterface $output, Question $question) } if (false === $ret) { - $ret = $this->readFromInput($inputStream); + $ret = fgets($inputStream, 4096); + if (false === $ret) { + throw new \RuntimeException('Aborted'); + } + $ret = trim($ret); } } else { $ret = trim($this->autocomplete($output, $question, $inputStream)); @@ -423,30 +427,6 @@ private function getShell() return self::$shell; } - /** - * Reads user input. - * - * @param resource $stream The input stream - * - * @return string User input - * - * @throws RuntimeException - */ - private function readFromInput($stream) - { - if (STDIN === $stream && function_exists('readline')) { - $ret = readline(''); - } else { - $ret = fgets($stream, 4096); - } - - if (false === $ret) { - throw new RuntimeException('Aborted'); - } - - return trim($ret); - } - /** * Returns whether Stty is available or not. * diff --git a/src/Symfony/Component/Console/Input/InputOption.php b/src/Symfony/Component/Console/Input/InputOption.php index 3a752cb700dbe..f08c5f26c104a 100644 --- a/src/Symfony/Component/Console/Input/InputOption.php +++ b/src/Symfony/Component/Console/Input/InputOption.php @@ -39,7 +39,7 @@ class InputOption * @param string|array $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts * @param int $mode The option mode: One of the VALUE_* constants * @param string $description A description text - * @param mixed $default The default value (must be null for self::VALUE_REQUIRED or self::VALUE_NONE) + * @param mixed $default The default value (must be null for self::VALUE_NONE) * * @throws InvalidArgumentException If option mode is invalid or incompatible */ diff --git a/src/Symfony/Component/Console/Question/Question.php b/src/Symfony/Component/Console/Question/Question.php index 71cb8f5c8b5a3..310a2bfed5274 100644 --- a/src/Symfony/Component/Console/Question/Question.php +++ b/src/Symfony/Component/Console/Question/Question.php @@ -143,7 +143,7 @@ public function setAutocompleterValues($values) } if (null !== $values && !is_array($values)) { - if (!$values instanceof \Traversable || $values instanceof \Countable) { + if (!$values instanceof \Traversable || !$values instanceof \Countable) { throw new InvalidArgumentException('Autocompleter values can be either an array, `null` or an object implementing both `Countable` and `Traversable` interfaces.'); } } diff --git a/src/Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.php b/src/Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.php index 46d5fe1580faf..b8d5ca6d9bebb 100644 --- a/src/Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.php +++ b/src/Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.php @@ -98,8 +98,8 @@ public function testStyleEscaping() $formatter = new OutputFormatter(true); $this->assertEquals( - "(\033[32mz>=2.0,format('('.$formatter->escape('z>=2.0,)') + "(\033[32mz>=2.0,<<format('('.$formatter->escape('z>=2.0,<\\<)') ); $this->assertEquals( diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php index ec7880be89b95..67b9008423bb2 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php @@ -148,45 +148,17 @@ private function populateAvailableType($id, Definition $definition) $this->types[$type] = $id; } - // Cannot use reflection if the class isn't set - if (!$definition->getClass()) { + if (!$reflectionClass = $this->getReflectionClass($id, $definition)) { return; } - if ($reflectionClass = $this->getReflectionClass($id, $definition)) { - $this->extractInterfaces($id, $reflectionClass); - $this->extractAncestors($id, $reflectionClass); - } - } - - /** - * Extracts the list of all interfaces implemented by a class. - * - * @param string $id - * @param \ReflectionClass $reflectionClass - */ - private function extractInterfaces($id, \ReflectionClass $reflectionClass) - { - foreach ($reflectionClass->getInterfaces() as $interfaceName => $reflectionInterface) { - $this->set($interfaceName, $id); - - $this->extractInterfaces($id, $reflectionInterface); + foreach ($reflectionClass->getInterfaces() as $reflectionInterface) { + $this->set($reflectionInterface->name, $id); } - } - - /** - * Extracts all inherited types of a class. - * - * @param string $id - * @param \ReflectionClass $reflectionClass - */ - private function extractAncestors($id, \ReflectionClass $reflectionClass) - { - $this->set($reflectionClass->name, $id); - if ($reflectionParentClass = $reflectionClass->getParentClass()) { - $this->extractAncestors($id, $reflectionParentClass); - } + do { + $this->set($reflectionClass->name, $id); + } while ($reflectionClass = $reflectionClass->getParentClass()); } /** @@ -256,6 +228,7 @@ private function getReflectionClass($id, Definition $definition) return $this->reflectionClasses[$id]; } + // Cannot use reflection if the class isn't set if (!$class = $definition->getClass()) { return; } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ReplaceAliasByActualDefinitionPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ReplaceAliasByActualDefinitionPass.php index 8308937d4a512..cb79c111afc41 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ReplaceAliasByActualDefinitionPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ReplaceAliasByActualDefinitionPass.php @@ -95,6 +95,8 @@ private function updateReferences($container, $currentId, $newId) $definition->setProperties( $this->updateArgumentReferences($definition->getProperties(), $currentId, $newId) ); + + $definition->setFactory($this->updateFactoryReference($definition->getFactory(), $currentId, $newId)); } } @@ -122,4 +124,17 @@ private function updateArgumentReferences(array $arguments, $currentId, $newId) return $arguments; } + + private function updateFactoryReference($factory, $currentId, $newId) + { + if (null === $factory || !is_array($factory) || !$factory[0] instanceof Reference) { + return $factory; + } + + if ($currentId === (string) $factory[0]) { + $factory[0] = new Reference($newId, $factory[0]->getInvalidBehavior()); + } + + return $factory; + } } diff --git a/src/Symfony/Component/DependencyInjection/Container.php b/src/Symfony/Component/DependencyInjection/Container.php index f383744f2121b..3a144de90d1e0 100644 --- a/src/Symfony/Component/DependencyInjection/Container.php +++ b/src/Symfony/Component/DependencyInjection/Container.php @@ -169,6 +169,10 @@ public function set($id, $service) throw new InvalidArgumentException('You cannot set service "service_container".'); } + if (isset($this->aliases[$id])) { + unset($this->aliases[$id]); + } + $this->services[$id] = $service; if (null === $service) { diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index cd0b64c731c38..aae5460ace603 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -18,6 +18,8 @@ use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Exception\LogicException; use Symfony\Component\DependencyInjection\Exception\RuntimeException; +use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; +use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\Config\Resource\ResourceInterface; @@ -259,7 +261,9 @@ public function addClassResource(\ReflectionClass $class) } do { - $this->addResource(new FileResource($class->getFileName())); + if (is_file($class->getFileName())) { + $this->addResource(new FileResource($class->getFileName())); + } } while ($class = $class->getParentClass()); return $this; @@ -396,8 +400,9 @@ public function has($id) * * @return object The associated service * - * @throws InvalidArgumentException when no definitions are available - * @throws LogicException when a circular dependency is detected + * @throws InvalidArgumentException when no definitions are available + * @throws ServiceCircularReferenceException When a circular reference is detected + * @throws ServiceNotFoundException When the service is not defined * @throws \Exception * * @see Reference @@ -416,7 +421,7 @@ public function get($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INV try { $definition = $this->getDefinition($id); - } catch (InvalidArgumentException $e) { + } catch (ServiceNotFoundException $e) { if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) { return; } @@ -756,14 +761,14 @@ public function hasDefinition($id) * * @return Definition A Definition instance * - * @throws InvalidArgumentException if the service definition does not exist + * @throws ServiceNotFoundException if the service definition does not exist */ public function getDefinition($id) { $id = strtolower($id); if (!array_key_exists($id, $this->definitions)) { - throw new InvalidArgumentException(sprintf('The service definition "%s" does not exist.', $id)); + throw new ServiceNotFoundException($id); } return $this->definitions[$id]; @@ -778,7 +783,7 @@ public function getDefinition($id) * * @return Definition A Definition instance * - * @throws InvalidArgumentException if the service definition does not exist + * @throws ServiceNotFoundException if the service definition does not exist */ public function findDefinition($id) { diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 8f9192f356c0e..32b261cd96adf 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -315,7 +315,7 @@ private function addServiceInlinedDefinitions($id, $definition) throw new ServiceCircularReferenceException($id, array($id)); } - $code .= $this->addNewInstance($id, $sDefinition, '$'.$name, ' = '); + $code .= $this->addNewInstance($sDefinition, '$'.$name, ' = '); if (!$this->hasReference($id, $sDefinition->getMethodCalls(), true) && !$this->hasReference($id, $sDefinition->getProperties(), true)) { $code .= $this->addServiceMethodCalls(null, $sDefinition, $name); @@ -389,7 +389,7 @@ private function addServiceInstance($id, $definition) $instantiation .= ' = '; } - $code = $this->addNewInstance($id, $definition, $return, $instantiation); + $code = $this->addNewInstance($definition, $return, $instantiation); if (!$simple) { $code .= "\n"; @@ -676,7 +676,7 @@ private function addServices() return $publicServices.$privateServices; } - private function addNewInstance($id, Definition $definition, $return, $instantiation) + private function addNewInstance(Definition $definition, $return, $instantiation) { $class = $this->dumpValue($definition->getClass()); diff --git a/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php index 14c7022cfb226..24ec562a403c7 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php @@ -65,7 +65,7 @@ private function addService($id, $definition) $class = substr($class, 1); } - $code .= sprintf(" class: %s\n", $class); + $code .= sprintf(" class: %s\n", $this->dumper->dump($class)); } if (!$definition->isPublic()) { @@ -89,7 +89,7 @@ private function addService($id, $definition) } if ($definition->getFile()) { - $code .= sprintf(" file: %s\n", $definition->getFile()); + $code .= sprintf(" file: %s\n", $this->dumper->dump($definition->getFile())); } if ($definition->isSynthetic()) { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php index f1ed72e94a4cd..28d6ab6339eea 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php @@ -61,9 +61,10 @@ public function testProcessAutowireInterface() $pass = new AutowirePass(); $pass->process($container); - $this->assertCount(2, $container->getDefinition('g')->getArguments()); + $this->assertCount(3, $container->getDefinition('g')->getArguments()); $this->assertEquals('f', (string) $container->getDefinition('g')->getArgument(0)); $this->assertEquals('f', (string) $container->getDefinition('g')->getArgument(1)); + $this->assertEquals('f', (string) $container->getDefinition('g')->getArgument(2)); } public function testCompleteExistingDefinition() @@ -317,13 +318,21 @@ interface EInterface extends DInterface { } -class F implements EInterface +interface IInterface +{ +} + +class I implements IInterface +{ +} + +class F extends I implements EInterface { } class G { - public function __construct(DInterface $d, EInterface $e) + public function __construct(DInterface $d, EInterface $e, IInterface $i) { } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ReplaceAliasByActualDefinitionPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ReplaceAliasByActualDefinitionPassTest.php index e4d22401d3cdd..474c0eb9c726e 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ReplaceAliasByActualDefinitionPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ReplaceAliasByActualDefinitionPassTest.php @@ -14,6 +14,9 @@ use Symfony\Component\DependencyInjection\Compiler\ReplaceAliasByActualDefinitionPass; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; + +require_once __DIR__.'/../Fixtures/includes/foo.php'; class ReplaceAliasByActualDefinitionPassTest extends \PHPUnit_Framework_TestCase { @@ -21,7 +24,8 @@ public function testProcess() { $container = new ContainerBuilder(); - $container->register('a', '\stdClass'); + $aDefinition = $container->register('a', '\stdClass'); + $aDefinition->setFactory(array(new Reference('b'), 'createA')); $bDefinition = new Definition('\stdClass'); $bDefinition->setPublic(false); @@ -39,6 +43,9 @@ public function testProcess() $container->has('b_alias') && !$container->hasAlias('b_alias'), '->process() replaces alias to actual.' ); + + $resolvedFactory = $aDefinition->getFactory(false); + $this->assertSame('b_alias', (string) $resolvedFactory[0]); } /** diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php index f252b56b13b64..87bfd012b33f7 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -20,6 +20,9 @@ use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Exception\RuntimeException; +use Symfony\Component\DependencyInjection\Exception\InactiveScopeException; +use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; +use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; use Symfony\Component\DependencyInjection\Loader\ClosureLoader; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; @@ -49,9 +52,9 @@ public function testDefinitions() try { $builder->getDefinition('baz'); - $this->fail('->getDefinition() throws an InvalidArgumentException if the service definition does not exist'); - } catch (\InvalidArgumentException $e) { - $this->assertEquals('The service definition "baz" does not exist.', $e->getMessage(), '->getDefinition() throws an InvalidArgumentException if the service definition does not exist'); + $this->fail('->getDefinition() throws a ServiceNotFoundException if the service definition does not exist'); + } catch (ServiceNotFoundException $e) { + $this->assertEquals('You have requested a non-existent service "baz".', $e->getMessage(), '->getDefinition() throws a ServiceNotFoundException if the service definition does not exist'); } } @@ -101,9 +104,9 @@ public function testGet() $builder = new ContainerBuilder(); try { $builder->get('foo'); - $this->fail('->get() throws an InvalidArgumentException if the service does not exist'); - } catch (\InvalidArgumentException $e) { - $this->assertEquals('The service definition "foo" does not exist.', $e->getMessage(), '->get() throws an InvalidArgumentException if the service does not exist'); + $this->fail('->get() throws a ServiceNotFoundException if the service does not exist'); + } catch (ServiceNotFoundException $e) { + $this->assertEquals('You have requested a non-existent service "foo".', $e->getMessage(), '->get() throws a ServiceNotFoundException if the service does not exist'); } $this->assertNull($builder->get('foo', ContainerInterface::NULL_ON_INVALID_REFERENCE), '->get() returns null if the service does not exist and NULL_ON_INVALID_REFERENCE is passed as a second argument'); @@ -231,6 +234,16 @@ public function testAddAliases() $this->assertTrue(isset($aliases['foobar'])); } + public function testSetReplacesAlias() + { + $builder = new ContainerBuilder(); + $builder->setAlias('alias', 'aliased'); + $builder->set('aliased', new \stdClass()); + + $builder->set('alias', $foo = new \stdClass()); + $this->assertSame($foo, $builder->get('alias'), '->set() replaces an existing alias'); + } + public function testAddGetCompilerPass() { $builder = new ContainerBuilder(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php index 17b6ee6e9c79a..a9f41c56a22bb 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php @@ -142,6 +142,14 @@ public function testSetWithNullResetTheService() $this->assertFalse($sc->has('foo'), '->set() with null service resets the service'); } + public function testSetReplacesAlias() + { + $c = new ProjectServiceContainer(); + + $c->set('alias', $foo = new \stdClass()); + $this->assertSame($foo, $c->get('alias'), '->set() replaces an existing alias'); + } + public function testGet() { $sc = new ProjectServiceContainer(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.php index a2ed68cd0b0f9..cd403c6d43104 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.php @@ -13,6 +13,7 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Dumper\YamlDumper; +use Symfony\Component\Yaml\Yaml; class YamlDumperTest extends \PHPUnit_Framework_TestCase { @@ -27,24 +28,21 @@ public function testDump() { $dumper = new YamlDumper($container = new ContainerBuilder()); - $this->assertStringEqualsFile(self::$fixturesPath.'/yaml/services1.yml', $dumper->dump(), '->dump() dumps an empty container as an empty YAML file'); - - $container = new ContainerBuilder(); - $dumper = new YamlDumper($container); + $this->assertEqualYamlStructure(file_get_contents(self::$fixturesPath.'/yaml/services1.yml'), $dumper->dump(), '->dump() dumps an empty container as an empty YAML file'); } public function testAddParameters() { $container = include self::$fixturesPath.'/containers/container8.php'; $dumper = new YamlDumper($container); - $this->assertStringEqualsFile(self::$fixturesPath.'/yaml/services8.yml', $dumper->dump(), '->dump() dumps parameters'); + $this->assertEqualYamlStructure(file_get_contents(self::$fixturesPath.'/yaml/services8.yml'), $dumper->dump(), '->dump() dumps parameters'); } public function testAddService() { $container = include self::$fixturesPath.'/containers/container9.php'; $dumper = new YamlDumper($container); - $this->assertEquals(str_replace('%path%', self::$fixturesPath.DIRECTORY_SEPARATOR.'includes'.DIRECTORY_SEPARATOR, file_get_contents(self::$fixturesPath.'/yaml/services9.yml')), $dumper->dump(), '->dump() dumps services'); + $this->assertEqualYamlStructure(str_replace('%path%', self::$fixturesPath.DIRECTORY_SEPARATOR.'includes'.DIRECTORY_SEPARATOR, file_get_contents(self::$fixturesPath.'/yaml/services9.yml')), $dumper->dump(), '->dump() dumps services'); $dumper = new YamlDumper($container = new ContainerBuilder()); $container->register('foo', 'FooClass')->addArgument(new \stdClass()); @@ -63,4 +61,9 @@ public function testDumpAutowireData() $dumper = new YamlDumper($container); $this->assertStringEqualsFile(self::$fixturesPath.'/yaml/services24.yml', $dumper->dump()); } + + private function assertEqualYamlStructure($yaml, $expected, $message = '') + { + $this->assertEquals(Yaml::parse($expected), Yaml::parse($yaml), $message); + } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services10.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services10.yml index f2f8d953d57a3..c66084cdbe8e6 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services10.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services10.yml @@ -6,4 +6,4 @@ services: class: BAR project: - test: %project.parameter.foo% + test: '%project.parameter.foo%' diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services6.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services6.yml index db554d7f5feb3..08a1df1e6bfcc 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services6.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services6.yml @@ -2,7 +2,7 @@ services: foo: { class: FooClass } baz: { class: BazClass } not_shared: { class: FooClass, shared: false } - file: { class: FooClass, file: %path%/foo.php } + file: { class: FooClass, file: '%path%/foo.php' } arguments: { class: FooClass, arguments: [foo, '@foo', [true, false]] } configurator1: { class: FooClass, configurator: sc_configure } configurator2: { class: FooClass, configurator: ['@baz', configure] } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml index 37f7e1951631e..6efeb37e747d4 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml @@ -18,7 +18,7 @@ services: factory: [Bar\FooClass, getInstance] configurator: sc_configure foo.baz: - class: %baz_class% + class: '%baz_class%' factory: ['%baz_class%', getInstance] configurator: ['%baz_class%', configureStatic1] bar: @@ -26,11 +26,11 @@ services: arguments: [foo, '@foo.baz', '%foo_bar%'] configurator: ['@foo.baz', configure] foo_bar: - class: %foo_class% + class: '%foo_class%' shared: false method_call1: class: Bar\FooClass - file: %path%foo.php + file: '%path%foo.php' calls: - [setBar, ['@foo']] - [setBar, ['@?foo2']] diff --git a/src/Symfony/Component/DomCrawler/Field/ChoiceFormField.php b/src/Symfony/Component/DomCrawler/Field/ChoiceFormField.php index fcf510c370a06..3e05015873588 100644 --- a/src/Symfony/Component/DomCrawler/Field/ChoiceFormField.php +++ b/src/Symfony/Component/DomCrawler/Field/ChoiceFormField.php @@ -59,6 +59,10 @@ public function hasValue() */ public function isDisabled() { + if (parent::isDisabled() && 'select' === $this->type) { + return true; + } + foreach ($this->options as $option) { if ($option['value'] == $this->value && $option['disabled']) { return true; diff --git a/src/Symfony/Component/DomCrawler/Form.php b/src/Symfony/Component/DomCrawler/Form.php index 0c7a3b2ec5c6c..c9c3c139b112b 100644 --- a/src/Symfony/Component/DomCrawler/Form.php +++ b/src/Symfony/Component/DomCrawler/Form.php @@ -157,8 +157,12 @@ public function getPhpValues() * * This method converts fields with the array notation * (like foo[bar] to arrays) like PHP does. + * The returned array is consistent with the array for field values + * (@see getPhpValues), rather than uploaded files found in $_FILES. + * For a compound file field foo[bar] it will create foo[bar][name], + * instead of foo[name][bar] which would be found in $_FILES. * - * @return array An array of field values. + * @return array An array of file field values. */ public function getPhpFiles() { diff --git a/src/Symfony/Component/DomCrawler/Tests/Field/ChoiceFormFieldTest.php b/src/Symfony/Component/DomCrawler/Tests/Field/ChoiceFormFieldTest.php index 9b31945b237f8..8b35cc9ac5ba0 100644 --- a/src/Symfony/Component/DomCrawler/Tests/Field/ChoiceFormFieldTest.php +++ b/src/Symfony/Component/DomCrawler/Tests/Field/ChoiceFormFieldTest.php @@ -120,6 +120,14 @@ public function testSelectWithEmptyBooleanAttribute() $this->assertEquals('bar', $field->getValue()); } + public function testSelectIsDisabled() + { + $node = $this->createSelectNode(array('foo' => false, 'bar' => true), array('disabled' => 'disabled')); + $field = new ChoiceFormField($node); + + $this->assertTrue($field->isDisabled(), '->isDisabled() returns true for selects with a disabled attribute'); + } + public function testMultipleSelects() { $node = $this->createSelectNode(array('foo' => false, 'bar' => false), array('multiple' => 'multiple')); diff --git a/src/Symfony/Component/Filesystem/Filesystem.php b/src/Symfony/Component/Filesystem/Filesystem.php index 8e96f1a87da8b..604568565ee93 100644 --- a/src/Symfony/Component/Filesystem/Filesystem.php +++ b/src/Symfony/Component/Filesystem/Filesystem.php @@ -115,6 +115,10 @@ public function mkdir($dirs, $mode = 0777) public function exists($files) { foreach ($this->toIterator($files) as $file) { + if ('\\' === DIRECTORY_SEPARATOR && strlen($file) > 258) { + throw new IOException('Could not check if file exist because path length exceeds 258 characters.', 0, null, $file); + } + if (!file_exists($file)) { return false; } @@ -154,7 +158,7 @@ public function remove($files) $files = iterator_to_array($this->toIterator($files)); $files = array_reverse($files); foreach ($files as $file) { - if (!file_exists($file) && !is_link($file)) { + if (!$this->exists($file) && !is_link($file)) { continue; } @@ -268,7 +272,7 @@ public function chgrp($files, $group, $recursive = false) public function rename($origin, $target, $overwrite = false) { // we check that target does not exist - if (!$overwrite && is_readable($target)) { + if (!$overwrite && $this->isReadable($target)) { throw new IOException(sprintf('Cannot rename because the target "%s" already exists.', $target), 0, null, $target); } @@ -277,6 +281,22 @@ public function rename($origin, $target, $overwrite = false) } } + /** + * Tells whether a file exists and is readable. + * + * @param string $filename Path to the file. + * + * @throws IOException When windows path is longer than 258 characters + */ + private function isReadable($filename) + { + if ('\\' === DIRECTORY_SEPARATOR && strlen($filename) > 258) { + throw new IOException('Could not check if file is readable because path length exceeds 258 characters.', 0, null, $filename); + } + + return is_readable($filename); + } + /** * Creates a symbolic link or copy a directory. * diff --git a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php index 847694a5054ce..a5d234d3b7da2 100644 --- a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php +++ b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php @@ -358,6 +358,28 @@ public function testFilesExists() $this->assertTrue($this->filesystem->exists($basePath.'folder')); } + /** + * @expectedException \Symfony\Component\Filesystem\Exception\IOException + */ + public function testFilesExistsFails() + { + if ('\\' !== DIRECTORY_SEPARATOR) { + $this->markTestSkipped('Test covers edge case on Windows only.'); + } + + $basePath = $this->workspace.'\\directory\\'; + + $oldPath = getcwd(); + mkdir($basePath); + chdir($basePath); + $file = str_repeat('T', 259 - strlen($basePath)); + $path = $basePath.$file; + exec('TYPE NUL >>'.$file); // equivalent of touch, we can not use the php touch() here because it suffers from the same limitation + self::$longPathNamesWindows[] = $path; // save this so we can clean up later + chdir($oldPath); + $this->filesystem->exists($path); + } + public function testFilesExistsTraversableObjectOfFilesAndDirectories() { $basePath = $this->workspace.DIRECTORY_SEPARATOR; diff --git a/src/Symfony/Component/Filesystem/Tests/FilesystemTestCase.php b/src/Symfony/Component/Filesystem/Tests/FilesystemTestCase.php index 1df8c078a6b6e..e1955c38b733c 100644 --- a/src/Symfony/Component/Filesystem/Tests/FilesystemTestCase.php +++ b/src/Symfony/Component/Filesystem/Tests/FilesystemTestCase.php @@ -17,6 +17,8 @@ class FilesystemTestCase extends \PHPUnit_Framework_TestCase { private $umask; + static protected $longPathNamesWindows = array(); + /** * @var \Symfony\Component\Filesystem\Filesystem */ @@ -31,6 +33,12 @@ class FilesystemTestCase extends \PHPUnit_Framework_TestCase public static function setUpBeforeClass() { + if (!empty(self::$longPathNamesWindows)) { + foreach (self::$longPathNamesWindows as $path) { + exec('DEL '.$path); + } + } + if ('\\' === DIRECTORY_SEPARATOR && null === self::$symlinkOnWindows) { $target = tempnam(sys_get_temp_dir(), 'sl'); $link = sys_get_temp_dir().'/sl'.microtime(true).mt_rand(); diff --git a/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php b/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php index b8bb200b54919..80cb6a39dd8d6 100644 --- a/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php +++ b/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php @@ -70,7 +70,7 @@ public function __construct($choices, callable $value = null) if (null === $value && $this->castableToString($choices)) { $value = function ($choice) { - return (string) $choice; + return false === $choice ? '0' : (string) $choice; }; } @@ -229,11 +229,11 @@ private function castableToString(array $choices, array &$cache = array()) continue; } elseif (!is_scalar($choice)) { return false; - } elseif (isset($cache[(string) $choice])) { + } elseif (isset($cache[$choice])) { return false; } - $cache[(string) $choice] = true; + $cache[$choice] = true; } return true; diff --git a/src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php b/src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php index e632c1238c861..3398c98edd742 100644 --- a/src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php +++ b/src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php @@ -120,11 +120,21 @@ private static function addChoiceView($choice, $value, $label, $keys, &$index, $ $key = $keys[$value]; $nextIndex = is_int($index) ? $index++ : call_user_func($index, $choice, $key, $value); + // BC normalize label to accept a false value + if (null === $label) { + // If the labels are null, use the original choice key by default + $label = (string) $key; + } elseif (false !== $label) { + // If "choice_label" is set to false and "expanded" is true, the value false + // should be passed on to the "label" option of the checkboxes/radio buttons + $dynamicLabel = call_user_func($label, $choice, $key, $value); + $label = false === $dynamicLabel ? false : (string) $dynamicLabel; + } + $view = new ChoiceView( $choice, $value, - // If the labels are null, use the original choice key by default - null === $label ? (string) $key : (string) call_user_func($label, $choice, $key, $value), + $label, // The attributes may be a callable or a mapping from choice indices // to nested arrays is_callable($attr) ? call_user_func($attr, $choice, $key, $value) : (isset($attr[$key]) ? $attr[$key] : array()) @@ -211,7 +221,7 @@ private static function addChoiceViewGroupedBy($groupBy, $choice, $value, $label $groupLabel = (string) $groupLabel; - // Initialize the group views if necessary. Unnnecessarily built group + // Initialize the group views if necessary. Unnecessarily built group // views will be cleaned up at the end of createView() if (!isset($preferredViews[$groupLabel])) { $preferredViews[$groupLabel] = new ChoiceGroupView($groupLabel); diff --git a/src/Symfony/Component/Form/ChoiceList/View/ChoiceListView.php b/src/Symfony/Component/Form/ChoiceList/View/ChoiceListView.php index 9641f4b1d9435..99308b826f7a5 100644 --- a/src/Symfony/Component/Form/ChoiceList/View/ChoiceListView.php +++ b/src/Symfony/Component/Form/ChoiceList/View/ChoiceListView.php @@ -48,4 +48,24 @@ public function __construct(array $choices = array(), array $preferredChoices = $this->choices = $choices; $this->preferredChoices = $preferredChoices; } + + /** + * Returns whether a placeholder is in the choices. + * + * A placeholder must be the first child element, not be in a group and have an empty value. + * + * @return bool + */ + public function hasPlaceholder() + { + if ($this->preferredChoices) { + $firstChoice = reset($this->preferredChoices); + + return $firstChoice instanceof ChoiceView && '' === $firstChoice->value; + } + + $firstChoice = reset($this->choices); + + return $firstChoice instanceof ChoiceView && '' === $firstChoice->value; + } } diff --git a/src/Symfony/Component/Form/Extension/Core/DataMapper/RadioListMapper.php b/src/Symfony/Component/Form/Extension/Core/DataMapper/RadioListMapper.php index 19db183a28394..d08a603b5c90e 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataMapper/RadioListMapper.php +++ b/src/Symfony/Component/Form/Extension/Core/DataMapper/RadioListMapper.php @@ -38,13 +38,11 @@ public function __construct(ChoiceListInterface $choiceList) /** * {@inheritdoc} */ - public function mapDataToForms($choice, $radios) + public function mapDataToForms($data, $radios) { - $valueMap = array_flip($this->choiceList->getValuesForChoices(array($choice))); - foreach ($radios as $radio) { $value = $radio->getConfig()->getOption('value'); - $radio->setData(isset($valueMap[$value]) ? true : false); + $radio->setData($value === $data ? true : false); } } diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToValueTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToValueTransformer.php index ffffddedc3bef..c7a6655b4e65a 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToValueTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToValueTransformer.php @@ -39,8 +39,8 @@ public function transform($choice) public function reverseTransform($value) { - if (null !== $value && !is_scalar($value)) { - throw new TransformationFailedException('Expected a scalar.'); + if (null !== $value && !is_string($value)) { + throw new TransformationFailedException('Expected a string or null.'); } $choices = $this->choiceList->getChoicesForValues(array((string) $value)); diff --git a/src/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php b/src/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php index 197f556308f25..d8369abfd4889 100644 --- a/src/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php +++ b/src/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php @@ -102,10 +102,6 @@ public function preSubmit(FormEvent $event) $form = $event->getForm(); $data = $event->getData(); - if (null === $data || '' === $data) { - $data = array(); - } - if (!is_array($data) && !($data instanceof \Traversable && $data instanceof \ArrayAccess)) { $data = array(); } diff --git a/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php b/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php index dfe4ffb092d56..65d607077bf59 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php @@ -144,6 +144,14 @@ public function buildForm(FormBuilderInterface $builder, array $options) $event->setData(null); } }); + // For radio lists, pre selection of the choice needs to pre set data + // with the string value so it can be matched in + // {@link \Symfony\Component\Form\Extension\Core\DataMapper\RadioListMapper::mapDataToForms()} + $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) { + $choiceList = $event->getForm()->getConfig()->getAttribute('choice_list'); + $value = current($choiceList->getValuesForChoices(array($event->getData()))); + $event->setData((string) $value); + }); } } elseif ($options['multiple']) { // An authentication exception occurred. - En autentiserings feil har skjedd. + En autentiseringsfeil har skjedd. Authentication credentials could not be found. @@ -24,7 +24,7 @@ Not privileged to request the resource. - Ingen tilgang til å be om gitt kilde. + Ingen tilgang til å be om gitt ressurs. Invalid CSRF token. diff --git a/src/Symfony/Component/Security/Core/Tests/Resources/TranslationFilesTest.php b/src/Symfony/Component/Security/Core/Tests/Resources/TranslationFilesTest.php new file mode 100644 index 0000000000000..dc38e4a776f07 --- /dev/null +++ b/src/Symfony/Component/Security/Core/Tests/Resources/TranslationFilesTest.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Security\Core\Tests\Resources; + +class TranslationFilesTest extends \PHPUnit_Framework_TestCase +{ + /** + * @dataProvider provideTranslationFiles + */ + public function testTranslationFileIsValid($filePath) + { + \PHPUnit_Util_XML::loadfile($filePath, false, false, true); + } + + public function provideTranslationFiles() + { + return array_map( + function ($filePath) { return (array) $filePath; }, + glob(dirname(dirname(__DIR__)).'/Resources/translations/*.xlf') + ); + } +} diff --git a/src/Symfony/Component/Validator/ConstraintValidatorFactory.php b/src/Symfony/Component/Validator/ConstraintValidatorFactory.php index cc6981b9461ce..86e44e2a5580f 100644 --- a/src/Symfony/Component/Validator/ConstraintValidatorFactory.php +++ b/src/Symfony/Component/Validator/ConstraintValidatorFactory.php @@ -26,11 +26,8 @@ class ConstraintValidatorFactory implements ConstraintValidatorFactoryInterface { protected $validators = array(); - private $propertyAccessor; - - public function __construct($propertyAccessor = null) + public function __construct() { - $this->propertyAccessor = $propertyAccessor; } /** @@ -42,7 +39,7 @@ public function getInstance(Constraint $constraint) if (!isset($this->validators[$className])) { $this->validators[$className] = 'validator.expression' === $className - ? new ExpressionValidator($this->propertyAccessor) + ? new ExpressionValidator() : new $className(); } diff --git a/src/Symfony/Component/Validator/Constraints/ExpressionValidator.php b/src/Symfony/Component/Validator/Constraints/ExpressionValidator.php index 46ddceece0276..e2f3139af73b8 100644 --- a/src/Symfony/Component/Validator/Constraints/ExpressionValidator.php +++ b/src/Symfony/Component/Validator/Constraints/ExpressionValidator.php @@ -12,12 +12,8 @@ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\ExpressionLanguage\ExpressionLanguage; -use Symfony\Component\PropertyAccess\PropertyAccess; -use Symfony\Component\PropertyAccess\PropertyAccessorInterface; -use Symfony\Component\PropertyAccess\PropertyPath; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; -use Symfony\Component\Validator\Context\ExecutionContextInterface; use Symfony\Component\Validator\Exception\RuntimeException; use Symfony\Component\Validator\Exception\UnexpectedTypeException; @@ -27,19 +23,13 @@ */ class ExpressionValidator extends ConstraintValidator { - /** - * @var PropertyAccessorInterface - */ - private $propertyAccessor; - /** * @var ExpressionLanguage */ private $expressionLanguage; - public function __construct(PropertyAccessorInterface $propertyAccessor = null, ExpressionLanguage $expressionLanguage = null) + public function __construct($propertyAccessor = null, ExpressionLanguage $expressionLanguage = null) { - $this->propertyAccessor = $propertyAccessor; $this->expressionLanguage = $expressionLanguage; } @@ -53,28 +43,8 @@ public function validate($value, Constraint $constraint) } $variables = array(); - - // Symfony 2.5+ - if ($this->context instanceof ExecutionContextInterface) { - $variables['value'] = $value; - $variables['this'] = $this->context->getObject(); - } elseif (null === $this->context->getPropertyName()) { - $variables['value'] = $value; - $variables['this'] = $value; - } else { - $root = $this->context->getRoot(); - $variables['value'] = $value; - - if (is_object($root)) { - // Extract the object that the property belongs to from the object - // graph - $path = new PropertyPath($this->context->getPropertyPath()); - $parentPath = $path->getParent(); - $variables['this'] = $parentPath ? $this->getPropertyAccessor()->getValue($root, $parentPath) : $root; - } else { - $variables['this'] = null; - } - } + $variables['value'] = $value; + $variables['this'] = $this->context->getObject(); if (!$this->getExpressionLanguage()->evaluate($constraint->expression, $variables)) { $this->context->buildViolation($constraint->message) @@ -95,16 +65,4 @@ private function getExpressionLanguage() return $this->expressionLanguage; } - - private function getPropertyAccessor() - { - if (null === $this->propertyAccessor) { - if (!class_exists('Symfony\Component\PropertyAccess\PropertyAccess')) { - throw new RuntimeException('Unable to use expressions as the Symfony PropertyAccess component is not installed.'); - } - $this->propertyAccessor = PropertyAccess::createPropertyAccessor(); - } - - return $this->propertyAccessor; - } } diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf index b50ecbc63a1b5..72d4d92973fdc 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf @@ -310,6 +310,10 @@ This value does not match the expected {{ charset }} charset. Cette valeur ne correspond pas au jeu de caractères {{ charset }} attendu. + + This is not a valid Business Identifier Code (BIC). + Ce n'est pas un code universel d'identification des banques (BIC) valide. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.nb.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.nb.xlf deleted file mode 100644 index a8b790c7d8640..0000000000000 --- a/src/Symfony/Component/Validator/Resources/translations/validators.nb.xlf +++ /dev/null @@ -1,155 +0,0 @@ - - - - - - This value should be false. - Verdien skal være falsk. - - - This value should be true. - Verdien skal være sann. - - - This value should be of type {{ type }}. - Verdien skal være av typen {{ type }}. - - - This value should be blank. - Verdien skal være blank. - - - The value you selected is not a valid choice. - Verdien skal være en av de gitte valg. - - - You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. - Du skal velge minst {{ limit }} valg. - - - You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. - Du kan maks velge {{ limit }} valg. - - - One or more of the given values is invalid. - En eller flere av de oppgitte verdier er ugyldige. - - - This field was not expected. - Dette feltet ikke var forventet. - - - This field is missing. - Dette feltet mangler. - - - This value is not a valid date. - Verdien er ikke en gyldig dato. - - - This value is not a valid datetime. - Verdien er ikke en gyldig dato og tid. - - - This value is not a valid email address. - Verdien er ikke en gyldig e-mail adresse. - - - The file could not be found. - Filen kunne ikke finnes. - - - The file is not readable. - Filen kan ikke leses. - - - The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. - Filen er for stor ({{ size }} {{ suffix }}). Tilatte maksimale størrelse {{ limit }} {{ suffix }}. - - - The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. - Mimetypen av filen er ugyldig ({{ type }}). Tilatte mimetyper er {{ types }}. - - - This value should be {{ limit }} or less. - Verdien skal være {{ limit }} eller mindre. - - - This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. - Verdien er for lang. Den skal ha {{ limit }} bokstaver eller mindre. - - - This value should be {{ limit }} or more. - Verdien skal være {{ limit }} eller mer. - - - This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. - Verdien er for kort. Den skal ha {{ limit }} tegn eller flere. - - - This value should not be blank. - Verdien må ikke være blank. - - - This value should not be null. - Verdien må ikke være tom (null). - - - This value should be null. - Verdien skal være tom (null). - - - This value is not valid. - Verdien er ikke gyldig. - - - This value is not a valid time. - Verdien er ikke en gyldig tid. - - - This value is not a valid URL. - Verdien er ikke en gyldig URL. - - - The two values should be equal. - De to verdier skal være ens. - - - The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. - Filen er for stor. Den maksimale størrelse er {{ limit }} {{ suffix }}. - - - The file is too large. - Filen er for stor. - - - The file could not be uploaded. - Filen kunne ikke lastes opp. - - - This value should be a valid number. - Denne verdi skal være et gyldig tall. - - - This file is not a valid image. - Denne filen er ikke et gyldig bilde. - - - This is not a valid IP address. - Dette er ikke en gyldig IP adresse. - - - This value is not a valid language. - Denne verdi er ikke et gyldig språk. - - - This value is not a valid locale. - Denne verdi er ikke en gyldig lokalitet. - - - This value is not a valid country. - Denne verdi er ikke et gyldig land. - - - - diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.nn.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.nn.xlf new file mode 100644 index 0000000000000..ea01c63ee4aa4 --- /dev/null +++ b/src/Symfony/Component/Validator/Resources/translations/validators.nn.xlf @@ -0,0 +1,227 @@ + + + + + + This value should be false. + Verdien skulle ha vore tom/nei. + + + This value should be true. + Verdien skulla ha vore satt/ja. + + + This value should be of type {{ type }}. + Verdien må vere av typen {{ type }}. + + + This value should be blank. + Verdien skal vere blank. + + + The value you selected is not a valid choice. + Verdien du valgte er ikkje gyldig. + + + You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. + Du må velge minst {{ limit }} valg. + + + You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. + Du kan maksimalt gjere {{ limit }} valg. + + + One or more of the given values is invalid. + Ein eller fleire av dei opplyste verdiane er ugyldige. + + + This field was not expected. + Dette feltet var ikke forventet. + + + This field is missing. + Dette feltet mangler. + + + This value is not a valid date. + Verdien er ikkje ein gyldig dato. + + + This value is not a valid datetime. + Verdien er ikkje ein gyldig dato og tid. + + + This value is not a valid email address. + Verdien er ikkje ei gyldig e-postadresse. + + + The file could not be found. + Fila kunne ikkje finnes. + + + The file is not readable. + Fila kan ikkje lesast. + + + The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. + Fila er for stor ({{ size }} {{ suffix }}). Tillatt maksimal størrelse er {{ limit }} {{ suffix }}. + + + The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. + Mime-typen av fila er ugyldig ({{ type }}). Tillatte mime-typar er {{ types }}. + + + This value should be {{ limit }} or less. + Verdien må vere {{ limit }} eller mindre. + + + This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. + Verdien er for lang. Den må vere {{ limit }} bokstavar eller mindre. + + + This value should be {{ limit }} or more. + Verdien må vere {{ limit }} eller meir. + + + This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. + Verdien er for kort. Den må ha {{ limit }} teikn eller fleire. + + + This value should not be blank. + Verdien må ikkje vere blank. + + + This value should not be null. + Verdien må ikkje vere tom (null). + + + This value should be null. + Verdien må vere tom (null). + + + This value is not valid. + Verdien er ikkje gyldig. + + + This value is not a valid time. + Verdien er ikkje gyldig tidseining. + + + This value is not a valid URL. + Verdien er ikkje ein gyldig URL. + + + The two values should be equal. + Dei to verdiane må vere like. + + + The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. + Fila er for stor. Den maksimale storleik er {{ limit }} {{ suffix }}. + + + The file is too large. + Fila er for stor. + + + The file could not be uploaded. + Fila kunne ikkje bli lasta opp. + + + This value should be a valid number. + Verdien må vere eit gyldig tal. + + + This file is not a valid image. + Fila er ikkje eit gyldig bilete. + + + This is not a valid IP address. + Dette er ikkje ei gyldig IP-adresse. + + + This value is not a valid language. + Verdien er ikkje eit gyldig språk. + + + This value is not a valid locale. + Verdien er ikkje ein gyldig lokalitet (språk/region). + + + This value is not a valid country. + Verdien er ikkje eit gyldig land. + + + This value is already used. + Verdien er allereie i bruk. + + + The size of the image could not be detected. + Storleiken på biletet kunne ikkje oppdagast. + + + The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. + Biletbreidda er for stor, ({{ width }} pikslar). Tillatt maksimumsbreidde er {{ max_width }} pikslar. + + + The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. + Biletbreidda er for liten, ({{ width }} pikslar). Forventa minimumsbreidde er {{ min_width }} pikslar. + + + The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. + Bilethøgda er for stor, ({{ height }} pikslar). Tillatt maksimumshøgde er {{ max_height }} pikslar. + + + The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. + Billethøgda er for låg, ({{ height }} pikslar). Forventa minimumshøgde er {{ min_height }} pikslar. + + + This value should be the user's current password. + Verdien må vere brukaren sitt noverande passord. + + + This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. + Verdien må vere nøyaktig {{ limit }} teikn. + + + The file was only partially uploaded. + Fila vart kun delvis opplasta. + + + No file was uploaded. + Inga fil vart lasta opp. + + + No temporary folder was configured in php.ini. + Førebels mappe (tmp) er ikkje konfigurert i php.ini. + + + Cannot write temporary file to disk. + Kan ikkje skrive førebels fil til disk. + + + A PHP extension caused the upload to fail. + Ei PHP-udviding forårsaka feil under opplasting. + + + This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. + Denne samlinga må innehalde {{ limit }} element eller meir.|Denne samlinga må innehalde {{ limit }} element eller meir. + + + This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. + Denne samlinga må innehalde {{ limit }} element eller færre.|Denne samlinga må innehalde {{ limit }} element eller færre. + + + This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. + Denne samlinga må innehalde nøyaktig {{ limit }} element.|Denne samlinga må innehalde nøyaktig {{ limit }} element. + + + Invalid card number. + Ugyldig kortnummer. + + + Unsupported card type or invalid card number. + Korttypen er ikkje støtta eller ugyldig kortnummer. + + + + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.no.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.no.xlf index ea01c63ee4aa4..5a9347652a911 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.no.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.no.xlf @@ -4,23 +4,23 @@ This value should be false. - Verdien skulle ha vore tom/nei. + Verdien må være usann. This value should be true. - Verdien skulla ha vore satt/ja. + Verdien må være sann. This value should be of type {{ type }}. - Verdien må vere av typen {{ type }}. + Verdien må være av typen {{ type }}. This value should be blank. - Verdien skal vere blank. + Verdien må være blank. The value you selected is not a valid choice. - Verdien du valgte er ikkje gyldig. + Den valgte verdien er ikke gyldig. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. @@ -28,11 +28,11 @@ You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. - Du kan maksimalt gjere {{ limit }} valg. + Du kan maks velge {{ limit }} valg. One or more of the given values is invalid. - Ein eller fleire av dei opplyste verdiane er ugyldige. + En eller flere av de oppgitte verdiene er ugyldige. This field was not expected. @@ -44,175 +44,175 @@ This value is not a valid date. - Verdien er ikkje ein gyldig dato. + Verdien er ikke en gyldig dato. This value is not a valid datetime. - Verdien er ikkje ein gyldig dato og tid. + Verdien er ikke en gyldig dato/tid. This value is not a valid email address. - Verdien er ikkje ei gyldig e-postadresse. + Verdien er ikke en gyldig e-postadresse. The file could not be found. - Fila kunne ikkje finnes. + Filen kunne ikke finnes. The file is not readable. - Fila kan ikkje lesast. + Filen er ikke lesbar. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. - Fila er for stor ({{ size }} {{ suffix }}). Tillatt maksimal størrelse er {{ limit }} {{ suffix }}. + Filen er for stor ({{ size }} {{ suffix }}). Tilatte maksimale størrelse {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. - Mime-typen av fila er ugyldig ({{ type }}). Tillatte mime-typar er {{ types }}. + Mimetypen av filen er ugyldig ({{ type }}). Tilatte mimetyper er {{ types }}. This value should be {{ limit }} or less. - Verdien må vere {{ limit }} eller mindre. + Verdien må være {{ limit }} tegn lang eller mindre. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. - Verdien er for lang. Den må vere {{ limit }} bokstavar eller mindre. + Verdien er for lang. Den må ha {{ limit }} tegn eller mindre. This value should be {{ limit }} or more. - Verdien må vere {{ limit }} eller meir. + Verdien må være {{ limit }} eller mer. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. - Verdien er for kort. Den må ha {{ limit }} teikn eller fleire. + Verdien er for kort. Den må ha {{ limit }} tegn eller flere. This value should not be blank. - Verdien må ikkje vere blank. + Verdien må ikke være blank. This value should not be null. - Verdien må ikkje vere tom (null). + Verdien må ikke være tom (null). This value should be null. - Verdien må vere tom (null). + Verdien må være tom (null). This value is not valid. - Verdien er ikkje gyldig. + Verdien er ikke gyldig. This value is not a valid time. - Verdien er ikkje gyldig tidseining. + Verdien er ikke en gyldig tid. This value is not a valid URL. - Verdien er ikkje ein gyldig URL. + Verdien er ikke en gyldig URL. The two values should be equal. - Dei to verdiane må vere like. + Verdiene må være identiske. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. - Fila er for stor. Den maksimale storleik er {{ limit }} {{ suffix }}. + Filen er for stor. Den maksimale størrelsen er {{ limit }} {{ suffix }}. The file is too large. - Fila er for stor. + Filen er for stor. The file could not be uploaded. - Fila kunne ikkje bli lasta opp. + Filen kunne ikke lastes opp. This value should be a valid number. - Verdien må vere eit gyldig tal. + Verdien må være et gyldig tall. This file is not a valid image. - Fila er ikkje eit gyldig bilete. + Denne filen er ikke et gyldig bilde. This is not a valid IP address. - Dette er ikkje ei gyldig IP-adresse. + Dette er ikke en gyldig IP adresse. This value is not a valid language. - Verdien er ikkje eit gyldig språk. + Verdien er ikke et gyldig språk. This value is not a valid locale. - Verdien er ikkje ein gyldig lokalitet (språk/region). + Verdien er ikke en gyldig lokalitet. This value is not a valid country. - Verdien er ikkje eit gyldig land. + Verdien er ikke et gyldig navn på land. This value is already used. - Verdien er allereie i bruk. + Verdien er allerede brukt. The size of the image could not be detected. - Storleiken på biletet kunne ikkje oppdagast. + Bildestørrelsen kunne ikke oppdages. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. - Biletbreidda er for stor, ({{ width }} pikslar). Tillatt maksimumsbreidde er {{ max_width }} pikslar. + Bildebredden er for stor ({{ width }} piksler). Tillatt maksimumsbredde er {{ max_width }} piksler. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. - Biletbreidda er for liten, ({{ width }} pikslar). Forventa minimumsbreidde er {{ min_width }} pikslar. + Bildebredden er for liten ({{ width }} piksler). Forventet minimumsbredde er {{ min_width }} piksler. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. - Bilethøgda er for stor, ({{ height }} pikslar). Tillatt maksimumshøgde er {{ max_height }} pikslar. + Bildehøyden er for stor ({{ height }} piksler). Tillatt maksimumshøyde er {{ max_height }} piksler. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. - Billethøgda er for låg, ({{ height }} pikslar). Forventa minimumshøgde er {{ min_height }} pikslar. + Bildehøyden er for liten ({{ height }} piksler). Forventet minimumshøyde er {{ min_height }} piksler. This value should be the user's current password. - Verdien må vere brukaren sitt noverande passord. + Verdien må være brukerens sitt nåværende passord. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. - Verdien må vere nøyaktig {{ limit }} teikn. + Verdien må være nøyaktig {{ limit }} tegn. The file was only partially uploaded. - Fila vart kun delvis opplasta. + Filen var kun delvis opplastet. No file was uploaded. - Inga fil vart lasta opp. + Ingen fil var lastet opp. No temporary folder was configured in php.ini. - Førebels mappe (tmp) er ikkje konfigurert i php.ini. + Den midlertidige mappen (tmp) er ikke konfigurert i php.ini. Cannot write temporary file to disk. - Kan ikkje skrive førebels fil til disk. + Kan ikke skrive midlertidig fil til disk. A PHP extension caused the upload to fail. - Ei PHP-udviding forårsaka feil under opplasting. + En PHP-utvidelse forårsaket en feil under opplasting. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. - Denne samlinga må innehalde {{ limit }} element eller meir.|Denne samlinga må innehalde {{ limit }} element eller meir. + Denne samlingen må inneholde {{ limit }} element eller flere.|Denne samlingen må inneholde {{ limit }} elementer eller flere. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. - Denne samlinga må innehalde {{ limit }} element eller færre.|Denne samlinga må innehalde {{ limit }} element eller færre. + Denne samlingen må inneholde {{ limit }} element eller færre.|Denne samlingen må inneholde {{ limit }} elementer eller færre. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. - Denne samlinga må innehalde nøyaktig {{ limit }} element.|Denne samlinga må innehalde nøyaktig {{ limit }} element. + Denne samlingen må inneholde nøyaktig {{ limit }} element.|Denne samlingen må inneholde nøyaktig {{ limit }} elementer. Invalid card number. @@ -220,7 +220,99 @@ Unsupported card type or invalid card number. - Korttypen er ikkje støtta eller ugyldig kortnummer. + Korttypen er ikke støttet eller ugyldig kortnummer. + + + This is not a valid International Bank Account Number (IBAN). + Dette er ikke en gyldig IBAN. + + + This value is not a valid ISBN-10. + Verdien er ikke en gyldig ISBN-10. + + + This value is not a valid ISBN-13. + Verdien er ikke en gyldig ISBN-13. + + + This value is neither a valid ISBN-10 nor a valid ISBN-13. + Verdien er hverken en gyldig ISBN-10 eller ISBN-13. + + + This value is not a valid ISSN. + Verdien er ikke en gyldig ISSN. + + + This value is not a valid currency. + Verdien er ikke gyldig valuta. + + + This value should be equal to {{ compared_value }}. + Verdien må være lik {{ compared_value }}. + + + This value should be greater than {{ compared_value }}. + Verdien må være større enn {{ compared_value }}. + + + This value should be greater than or equal to {{ compared_value }}. + Verdien må være større enn eller lik {{ compared_value }}. + + + This value should be identical to {{ compared_value_type }} {{ compared_value }}. + Verdien må være identisk med {{ compared_value_type }} {{ compared_value }}. + + + This value should be less than {{ compared_value }}. + Verdien må være mindre enn {{ compared_value }}. + + + This value should be less than or equal to {{ compared_value }}. + Verdien må være mindre enn eller lik {{ compared_value }}. + + + This value should not be equal to {{ compared_value }}. + Verdien må ikke være lik {{ compared_value }}. + + + This value should not be identical to {{ compared_value_type }} {{ compared_value }}. + Verdien må ikke være identisk med {{ compared_value_type }} {{ compared_value }}. + + + The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. + Bildeforholdet er for stort ({{ ratio }}). Tillatt maksimumsbildeforhold er {{ max_ratio }}. + + + The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. + Bildeforholdet er for lite ({{ ratio }}). Forventet maksimumsbildeforhold er {{ min_ratio }}. + + + The image is square ({{ width }}x{{ height }}px). Square images are not allowed. + Bildet er en kvadrat ({{ width }}x{{ height }}px). Kvadratiske bilder er ikke tillatt. + + + The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed. + Bildet er i liggende retning ({{ width }}x{{ height }}px). Bilder i liggende retning er ikke tillatt. + + + The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. + Bildet er i stående retning ({{ width }}x{{ height }}px). Bilder i stående retning er ikke tillatt. + + + An empty file is not allowed. + Tomme filer er ikke tilatt. + + + The host could not be resolved. + Vertsnavn kunne ikke løses. + + + This value does not match the expected {{ charset }} charset. + Verdien samsvarer ikke med forventet tegnsett {{ charset }}. + + + This is not a valid Business Identifier Code (BIC). + Dette er ikke en gyldig BIC. diff --git a/src/Symfony/Component/Validator/Tests/Constraints/ExpressionValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/ExpressionValidatorTest.php index 03f998f8109ff..c76920fbb20d4 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/ExpressionValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/ExpressionValidatorTest.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Validator\Tests\Constraints; -use Symfony\Component\PropertyAccess\PropertyAccess; use Symfony\Component\Validator\Constraints\Expression; use Symfony\Component\Validator\Constraints\ExpressionValidator; use Symfony\Component\Validator\Tests\Fixtures\Entity; @@ -20,7 +19,7 @@ class ExpressionValidatorTest extends AbstractConstraintValidatorTest { protected function createValidator() { - return new ExpressionValidator(PropertyAccess::createPropertyAccessor()); + return new ExpressionValidator(); } public function testExpressionIsEvaluatedWithNullValue() diff --git a/src/Symfony/Component/Validator/Tests/Resources/TranslationFilesTest.php b/src/Symfony/Component/Validator/Tests/Resources/TranslationFilesTest.php new file mode 100644 index 0000000000000..8a766611cd4f9 --- /dev/null +++ b/src/Symfony/Component/Validator/Tests/Resources/TranslationFilesTest.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Validator\Tests\Resources; + +class TranslationFilesTest extends \PHPUnit_Framework_TestCase +{ + /** + * @dataProvider provideTranslationFiles + */ + public function testTranslationFileIsValid($filePath) + { + \PHPUnit_Util_XML::loadfile($filePath, false, false, true); + } + + public function provideTranslationFiles() + { + return array_map( + function ($filePath) { return (array) $filePath; }, + glob(dirname(dirname(__DIR__)).'/Resources/translations/*.xlf') + ); + } +} diff --git a/src/Symfony/Component/Validator/ValidatorBuilder.php b/src/Symfony/Component/Validator/ValidatorBuilder.php index fc3abd342355f..d82aca5612cdd 100644 --- a/src/Symfony/Component/Validator/ValidatorBuilder.php +++ b/src/Symfony/Component/Validator/ValidatorBuilder.php @@ -15,7 +15,6 @@ use Doctrine\Common\Annotations\CachedReader; use Doctrine\Common\Annotations\Reader; use Doctrine\Common\Cache\ArrayCache; -use Symfony\Component\PropertyAccess\PropertyAccessorInterface; use Symfony\Component\Translation\IdentityTranslator; use Symfony\Component\Translation\TranslatorInterface; use Symfony\Component\Validator\Context\ExecutionContextFactory; @@ -89,11 +88,6 @@ class ValidatorBuilder implements ValidatorBuilderInterface */ private $translationDomain; - /** - * @var PropertyAccessorInterface|null - */ - private $propertyAccessor; - /** * {@inheritdoc} */ @@ -263,10 +257,6 @@ public function setMetadataCache(CacheInterface $cache) */ public function setConstraintValidatorFactory(ConstraintValidatorFactoryInterface $validatorFactory) { - if (null !== $this->propertyAccessor) { - throw new ValidatorException('You cannot set a validator factory after setting a custom property accessor. Remove the call to setPropertyAccessor() if you want to call setConstraintValidatorFactory().'); - } - $this->validatorFactory = $validatorFactory; return $this; @@ -333,7 +323,7 @@ public function getValidator() $metadataFactory = new LazyLoadingMetadataFactory($loader, $this->metadataCache); } - $validatorFactory = $this->validatorFactory ?: new ConstraintValidatorFactory($this->propertyAccessor); + $validatorFactory = $this->validatorFactory ?: new ConstraintValidatorFactory(); $translator = $this->translator; if (null === $translator) { diff --git a/src/Symfony/Component/Validator/composer.json b/src/Symfony/Component/Validator/composer.json index 7365981fd6750..48d431cc79a54 100644 --- a/src/Symfony/Component/Validator/composer.json +++ b/src/Symfony/Component/Validator/composer.json @@ -24,7 +24,6 @@ "symfony/intl": "~2.8|~3.0", "symfony/yaml": "~2.8|~3.0", "symfony/config": "~2.8|~3.0", - "symfony/property-access": "~2.8|~3.0", "symfony/expression-language": "~2.8|~3.0", "doctrine/annotations": "~1.0", "doctrine/cache": "~1.0", diff --git a/src/Symfony/Component/VarDumper/Tests/CliDumperTest.php b/src/Symfony/Component/VarDumper/Tests/CliDumperTest.php index cd6d64d1c0368..e6de7371b2760 100644 --- a/src/Symfony/Component/VarDumper/Tests/CliDumperTest.php +++ b/src/Symfony/Component/VarDumper/Tests/CliDumperTest.php @@ -62,15 +62,12 @@ public function testGet() 7 => b"é\\x00" "[]" => [] "res" => stream resource {@{$res} - wrapper_type: "plainfile" +%A wrapper_type: "plainfile" stream_type: "STDIO" mode: "r" unread_bytes: 0 seekable: true - timed_out: false - blocked: true - eof: false - options: [] +%A options: [] } "obj" => Symfony\Component\VarDumper\Tests\Fixture\DumbFoo {#%d +foo: "foo" @@ -211,16 +208,13 @@ public function testThrowingCaster() $this->assertStringMatchesFormat( <<7 => b"&%s;\\x00" "[]" => [] "res" => stream resource @{$res} - wrapper_type: "plainfile" +%A wrapper_type: "plainfile" stream_type: "STDIO" mode: "r" unread_bytes: 0 seekable: true - timed_out: false - blocked: true - eof: false - options: [] +%A options: [] } "obj" => DumbFoo {#%d +foo: "foo" diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php index 0e0b4ee01e20f..10fbd898f0257 100644 --- a/src/Symfony/Component/Yaml/Inline.php +++ b/src/Symfony/Component/Yaml/Inline.php @@ -519,7 +519,12 @@ private static function evaluateScalar($scalar, $references = array()) case preg_match('/^(-|\+)?[0-9,]+(\.[0-9]+)?$/', $scalar): return (float) str_replace(',', '', $scalar); case preg_match(self::getTimestampRegex(), $scalar): - return strtotime($scalar); + $timeZone = date_default_timezone_get(); + date_default_timezone_set('UTC'); + $time = strtotime($scalar); + date_default_timezone_set($timeZone); + + return $time; } default: return (string) $scalar; diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index 9e4da1766431e..28b58c36c1e33 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -301,8 +301,14 @@ public function parse($value, $exceptionOnInvalidType = false, $objectSupport = mb_internal_encoding($mbEncoding); } - if ($objectForMap && !is_object($data)) { - $data = (object) $data; + if ($objectForMap && !is_object($data) && 'mapping' === $context) { + $object = new \stdClass(); + + foreach ($data as $key => $value) { + $object->$key = $value; + } + + $data = $object; } return empty($data) ? null : $data; diff --git a/src/Symfony/Component/Yaml/Tests/Fixtures/YtsSpecificationExamples.yml b/src/Symfony/Component/Yaml/Tests/Fixtures/YtsSpecificationExamples.yml index d69e97a1a5c65..ec1c4c3a1ab40 100644 --- a/src/Symfony/Component/Yaml/Tests/Fixtures/YtsSpecificationExamples.yml +++ b/src/Symfony/Component/Yaml/Tests/Fixtures/YtsSpecificationExamples.yml @@ -754,7 +754,7 @@ yaml: | Billsmer @ 338-4338. php: | array( - 'invoice' => 34843, 'date' => mktime(0, 0, 0, 1, 23, 2001), + 'invoice' => 34843, 'date' => gmmktime(0, 0, 0, 1, 23, 2001), 'bill-to' => array( 'given' => 'Chris', 'family' => 'Dumars', 'address' => array( 'lines' => "458 Walkman Dr.\nSuite #292\n", 'city' => 'Royal Oak', 'state' => 'MI', 'postal' => 48046 ) ) , 'ship-to' => @@ -879,7 +879,7 @@ yaml: | php: | array( 'invoice' => 34843, - 'date' => mktime(0, 0, 0, 1, 23, 2001), + 'date' => gmmktime(0, 0, 0, 1, 23, 2001), 'total' => 4443.52 ) --- diff --git a/src/Symfony/Component/Yaml/Tests/InlineTest.php b/src/Symfony/Component/Yaml/Tests/InlineTest.php index ab541dade2bdf..3da5dd532cd0f 100644 --- a/src/Symfony/Component/Yaml/Tests/InlineTest.php +++ b/src/Symfony/Component/Yaml/Tests/InlineTest.php @@ -251,7 +251,7 @@ public function getTestsForParse() array("'on'", 'on'), array("'off'", 'off'), - array('2007-10-30', mktime(0, 0, 0, 10, 30, 2007)), + array('2007-10-30', gmmktime(0, 0, 0, 10, 30, 2007)), array('2007-10-30T02:59:43Z', gmmktime(2, 59, 43, 10, 30, 2007)), array('2007-10-30 02:59:43 Z', gmmktime(2, 59, 43, 10, 30, 2007)), array('1960-10-30 02:59:43 Z', gmmktime(2, 59, 43, 10, 30, 1960)), @@ -318,7 +318,7 @@ public function getTestsForParseWithMapObjects() array("'#cfcfcf'", '#cfcfcf'), array('::form_base.html.twig', '::form_base.html.twig'), - array('2007-10-30', mktime(0, 0, 0, 10, 30, 2007)), + array('2007-10-30', gmmktime(0, 0, 0, 10, 30, 2007)), array('2007-10-30T02:59:43Z', gmmktime(2, 59, 43, 10, 30, 2007)), array('2007-10-30 02:59:43 Z', gmmktime(2, 59, 43, 10, 30, 2007)), array('1960-10-30 02:59:43 Z', gmmktime(2, 59, 43, 10, 30, 1960)), diff --git a/src/Symfony/Component/Yaml/Tests/ParserTest.php b/src/Symfony/Component/Yaml/Tests/ParserTest.php index 81f97916a8ca6..fc15c32cd8a5d 100644 --- a/src/Symfony/Component/Yaml/Tests/ParserTest.php +++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php @@ -442,35 +442,75 @@ public function testObjectSupportDisabledButNoExceptions($input) $this->assertEquals(array('foo' => null, 'bar' => 1), $this->parser->parse($input), '->parse() does not parse objects'); } - public function testObjectForMapEnabledWithMapping() + /** + * @dataProvider getObjectForMapTests + */ + public function testObjectForMap($yaml, $expected) + { + $this->assertEquals($expected, $this->parser->parse($yaml, false, false, true)); + } + + public function getObjectForMapTests() { + $tests = array(); + $yaml = <<parser->parse($yaml, false, false, true); - - $this->assertInstanceOf('stdClass', $result); - $this->assertInstanceOf('stdClass', $result->foo); - $this->assertEquals(array('cat'), $result->foo->fiz); - } - - public function testObjectForMapEnabledWithInlineMapping() - { - $result = $this->parser->parse('{ "foo": "bar", "fiz": "cat" }', false, false, true); + $expected = new \stdClass(); + $expected->foo = new \stdClass(); + $expected->foo->fiz = array('cat'); + $tests['mapping'] = array($yaml, $expected); - $this->assertInstanceOf('stdClass', $result); - $this->assertEquals('bar', $result->foo); - $this->assertEquals('cat', $result->fiz); - } + $yaml = '{ "foo": "bar", "fiz": "cat" }'; + $expected = new \stdClass(); + $expected->foo = 'bar'; + $expected->fiz = 'cat'; + $tests['inline-mapping'] = array($yaml, $expected); - public function testObjectForMapIsAppliedAfterParsing() - { + $yaml = "foo: bar\nbaz: foobar"; $expected = new \stdClass(); $expected->foo = 'bar'; $expected->baz = 'foobar'; + $tests['object-for-map-is-applied-after-parsing'] = array($yaml, $expected); - $this->assertEquals($expected, $this->parser->parse("foo: bar\nbaz: foobar", false, false, true)); + $yaml = <<array = array(); + $expected->array[0] = new \stdClass(); + $expected->array[0]->key = 'one'; + $expected->array[1] = new \stdClass(); + $expected->array[1]->key = 'two'; + $tests['nest-map-and-sequence'] = array($yaml, $expected); + + $yaml = <<map = new \stdClass(); + $expected->map->{1} = 'one'; + $expected->map->{2} = 'two'; + $tests['numeric-keys'] = array($yaml, $expected); + + $yaml = <<map = new \stdClass(); + $expected->map->{0} = 'one'; + $expected->map->{1} = 'two'; + $tests['zero-indexed-numeric-keys'] = array($yaml, $expected); + + return $tests; } /** pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy