diff --git a/src/Symfony/Bundle/FrameworkBundle/Test/WebTestCase.php b/src/Symfony/Bundle/FrameworkBundle/Test/WebTestCase.php index e62e2921a1..b5aaa2604b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Test/WebTestCase.php +++ b/src/Symfony/Bundle/FrameworkBundle/Test/WebTestCase.php @@ -23,7 +23,7 @@ abstract class WebTestCase extends KernelTestCase /** * Creates a Client. * - * @param array $options An array of options to pass to the createKernel class + * @param array $options An array of options to pass to the createKernel method * @param array $server An array of server parameters * * @return Client A Client instance diff --git a/src/Symfony/Bundle/TwigBundle/TemplateIterator.php b/src/Symfony/Bundle/TwigBundle/TemplateIterator.php index 611c448232..01262e015b 100644 --- a/src/Symfony/Bundle/TwigBundle/TemplateIterator.php +++ b/src/Symfony/Bundle/TwigBundle/TemplateIterator.php @@ -63,7 +63,7 @@ class TemplateIterator implements \IteratorAggregate $this->templates = array_merge( $this->templates, $this->findTemplatesInDirectory($bundle->getPath().'/Resources/views', $name), - $this->findTemplatesInDirectory($this->rootDir.'/'.$bundle->getName().'/views', $name), + $this->findTemplatesInDirectory($this->rootDir.'/Resources/'.$bundle->getName().'/views', $name), $this->findTemplatesInDirectory($this->defaultPath.'/bundles/'.$bundle->getName(), $name) ); } diff --git a/src/Symfony/Bundle/TwigBundle/Tests/Fixtures/templates/Resources/BarBundle/views/base.html.twig b/src/Symfony/Bundle/TwigBundle/Tests/Fixtures/templates/Resources/BarBundle/views/base.html.twig new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Symfony/Bundle/TwigBundle/Tests/TemplateIteratorTest.php b/src/Symfony/Bundle/TwigBundle/Tests/TemplateIteratorTest.php index ba52cfb66f..04eb5e1878 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/TemplateIteratorTest.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/TemplateIteratorTest.php @@ -31,6 +31,7 @@ class TemplateIteratorTest extends TestCase sort($sorted); $this->assertEquals( array( + '@Bar/base.html.twig', '@Bar/index.html.twig', '@Bar/layout.html.twig', '@Foo/index.html.twig', diff --git a/src/Symfony/Bundle/WebProfilerBundle/README.md b/src/Symfony/Bundle/WebProfilerBundle/README.md index 03780d5e59..48e6075636 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/README.md +++ b/src/Symfony/Bundle/WebProfilerBundle/README.md @@ -1,6 +1,12 @@ WebProfilerBundle ================= +The Web profiler bundle is a **development tool** that gives detailed +information about the execution of any request. + +**Never** enable it on production servers as it will lead to major security +vulnerabilities in your project. + Resources --------- diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index 1d415636fc..6b6192c377 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -153,15 +153,7 @@ class Application $renderException($e); - $exitCode = $e->getCode(); - if (is_numeric($exitCode)) { - $exitCode = (int) $exitCode; - if (0 === $exitCode) { - $exitCode = 1; - } - } else { - $exitCode = 1; - } + $exitCode = $this->getExitCodeForThrowable($e); } finally { // if the exception handler changed, keep it // otherwise, unregister $renderException @@ -1220,4 +1212,26 @@ class Application $this->add($command); } } + + /** + * Type hint omitted to be PHP5 compatible. + * + * @param \Exception|\Throwable $throwable + * + * @return int + */ + private function getExitCodeForThrowable($throwable) + { + $exitCode = $throwable->getCode(); + if (is_numeric($exitCode)) { + $exitCode = (int) $exitCode; + if (0 === $exitCode) { + $exitCode = 1; + } + } else { + $exitCode = 1; + } + + return $exitCode; + } } diff --git a/src/Symfony/Component/Console/Tests/ApplicationTest.php b/src/Symfony/Component/Console/Tests/ApplicationTest.php index 3c3b1284d0..1a10039c22 100644 --- a/src/Symfony/Component/Console/Tests/ApplicationTest.php +++ b/src/Symfony/Component/Console/Tests/ApplicationTest.php @@ -912,6 +912,31 @@ class ApplicationTest extends TestCase $this->assertSame(4, $exitCode, '->run() returns integer exit code extracted from raised exception'); } + public function testRunDispatchesIntegerExitCode() + { + $passedRightValue = false; + + // We can assume here that some other test asserts that the event is dispatched at all + $dispatcher = new EventDispatcher(); + $self = $this; + $dispatcher->addListener('console.terminate', function (ConsoleTerminateEvent $event) use ($self, &$passedRightValue) { + $passedRightValue = (4 === $event->getExitCode()); + }); + + $application = new Application(); + $application->setDispatcher($dispatcher); + $application->setAutoExit(false); + + $application->register('test')->setCode(function (InputInterface $input, OutputInterface $output) { + throw new \Exception('', 4); + }); + + $tester = new ApplicationTester($application); + $tester->run(array('command' => 'test')); + + $this->assertTrue($passedRightValue, '-> exit code 4 was passed in the console.terminate event'); + } + public function testRunReturnsExitCodeOneForExceptionCodeZero() { $exception = new \Exception('', 0); @@ -927,6 +952,31 @@ class ApplicationTest extends TestCase $this->assertSame(1, $exitCode, '->run() returns exit code 1 when exception code is 0'); } + public function testRunDispatchesExitCodeOneForExceptionCodeZero() + { + $passedRightValue = false; + + // We can assume here that some other test asserts that the event is dispatched at all + $dispatcher = new EventDispatcher(); + $self = $this; + $dispatcher->addListener('console.terminate', function (ConsoleTerminateEvent $event) use ($self, &$passedRightValue) { + $passedRightValue = (1 === $event->getExitCode()); + }); + + $application = new Application(); + $application->setDispatcher($dispatcher); + $application->setAutoExit(false); + + $application->register('test')->setCode(function (InputInterface $input, OutputInterface $output) { + throw new \Exception(); + }); + + $tester = new ApplicationTester($application); + $tester->run(array('command' => 'test')); + + $this->assertTrue($passedRightValue, '-> exit code 1 was passed in the console.terminate event'); + } + /** * @expectedException \LogicException * @expectedExceptionMessage An option with shortcut "e" already exists. diff --git a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php index 4537e76903..df8b8124f9 100644 --- a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php +++ b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php @@ -50,6 +50,10 @@ class FilesystemTest extends FilesystemTestCase $this->markTestSkipped('This test cannot run on Windows.'); } + if (!getenv('USER') || 'root' === getenv('USER')) { + $this->markTestSkipped('This test will fail if run under superuser'); + } + $sourceFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_source_file'; $targetFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_target_file'; @@ -124,6 +128,10 @@ class FilesystemTest extends FilesystemTestCase $this->markTestSkipped('This test cannot run on Windows.'); } + if (!getenv('USER') || 'root' === getenv('USER')) { + $this->markTestSkipped('This test will fail if run under superuser'); + } + $sourceFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_source_file'; $targetFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_target_file'; diff --git a/src/Symfony/Component/Filesystem/Tests/LockHandlerTest.php b/src/Symfony/Component/Filesystem/Tests/LockHandlerTest.php index b32e765680..14eabc021e 100644 --- a/src/Symfony/Component/Filesystem/Tests/LockHandlerTest.php +++ b/src/Symfony/Component/Filesystem/Tests/LockHandlerTest.php @@ -52,6 +52,10 @@ class LockHandlerTest extends TestCase $this->markTestSkipped('This test cannot run on Windows.'); } + if (!getenv('USER') || 'root' === getenv('USER')) { + $this->markTestSkipped('This test will fail if run under superuser'); + } + $lockPath = sys_get_temp_dir().'/'.uniqid('', true); $e = null; $wrongMessage = null; diff --git a/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php b/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php index 3168a8ee1b..d23467596e 100644 --- a/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php +++ b/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php @@ -137,7 +137,7 @@ class FormValidator extends ConstraintValidator /** * Returns the validation groups of the given form. * - * @return array The validation groups + * @return string|GroupSequence|(string|GroupSequence)[] The validation groups */ private static function getValidationGroups(FormInterface $form) { @@ -172,10 +172,10 @@ class FormValidator extends ConstraintValidator /** * Post-processes the validation groups option for a given form. * - * @param array|callable $groups The validation groups - * @param FormInterface $form The validated form + * @param string|GroupSequence|(string|GroupSequence)[]|callable $groups The validation groups + * @param FormInterface $form The validated form * - * @return array The validation groups + * @return (string|GroupSequence)[] The validation groups */ private static function resolveValidationGroups($groups, FormInterface $form) { diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php index 6ac23eed4d..e0376ad2d5 100644 --- a/src/Symfony/Component/HttpFoundation/Request.php +++ b/src/Symfony/Component/HttpFoundation/Request.php @@ -1460,7 +1460,7 @@ class Request * * _format request attribute * * $default * - * @param string $default The default format + * @param string|null $default The default format * * @return string The request format */ diff --git a/src/Symfony/Component/HttpKernel/Fragment/InlineFragmentRenderer.php b/src/Symfony/Component/HttpKernel/Fragment/InlineFragmentRenderer.php index 712248578d..13fc335624 100644 --- a/src/Symfony/Component/HttpKernel/Fragment/InlineFragmentRenderer.php +++ b/src/Symfony/Component/HttpKernel/Fragment/InlineFragmentRenderer.php @@ -122,6 +122,13 @@ class InlineFragmentRenderer extends RoutableFragmentRenderer $subRequest->setSession($session); } + if ($request->get('_format')) { + $subRequest->attributes->set('_format', $request->get('_format')); + } + if ($request->getDefaultLocale() !== $request->getLocale()) { + $subRequest->setLocale($request->getLocale()); + } + return $subRequest; } diff --git a/src/Symfony/Component/HttpKernel/Tests/Fragment/InlineFragmentRendererTest.php b/src/Symfony/Component/HttpKernel/Tests/Fragment/InlineFragmentRendererTest.php index b3457b5d7a..75987605e3 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Fragment/InlineFragmentRendererTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Fragment/InlineFragmentRendererTest.php @@ -189,6 +189,26 @@ class InlineFragmentRendererTest extends TestCase $this->assertEquals('Foo', ob_get_clean()); } + public function testLocaleAndFormatAreIsKeptInSubrequest() + { + $expectedSubRequest = Request::create('/'); + $expectedSubRequest->attributes->set('_format', 'foo'); + $expectedSubRequest->setLocale('fr'); + if (Request::getTrustedHeaderName(Request::HEADER_CLIENT_IP)) { + $expectedSubRequest->headers->set('x-forwarded-for', array('127.0.0.1')); + $expectedSubRequest->server->set('HTTP_X_FORWARDED_FOR', '127.0.0.1'); + } + $expectedSubRequest->headers->set('forwarded', array('for="127.0.0.1";host="localhost";proto=http')); + $expectedSubRequest->server->set('HTTP_FORWARDED', 'for="127.0.0.1";host="localhost";proto=http'); + + $strategy = new InlineFragmentRenderer($this->getKernelExpectingRequest($expectedSubRequest)); + + $request = Request::create('/'); + $request->attributes->set('_format', 'foo'); + $request->setLocale('fr'); + $strategy->render('/', $request); + } + public function testESIHeaderIsKeptInSubrequest() { $expectedSubRequest = Request::create('/'); diff --git a/src/Symfony/Component/Security/Http/HttpUtils.php b/src/Symfony/Component/Security/Http/HttpUtils.php index d82bc324e6..a6bcffe485 100644 --- a/src/Symfony/Component/Security/Http/HttpUtils.php +++ b/src/Symfony/Component/Security/Http/HttpUtils.php @@ -91,6 +91,13 @@ class HttpUtils $newRequest->attributes->set(Security::LAST_USERNAME, $request->attributes->get(Security::LAST_USERNAME)); } + if ($request->get('_format')) { + $newRequest->attributes->set('_format', $request->get('_format')); + } + if ($request->getDefaultLocale() !== $request->getLocale()) { + $newRequest->setLocale($request->getLocale()); + } + return $newRequest; } diff --git a/src/Symfony/Component/Validator/GroupSequenceProviderInterface.php b/src/Symfony/Component/Validator/GroupSequenceProviderInterface.php index 62e8a5ed0d..5894397da4 100644 --- a/src/Symfony/Component/Validator/GroupSequenceProviderInterface.php +++ b/src/Symfony/Component/Validator/GroupSequenceProviderInterface.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator; +use Symfony\Component\Validator\Constraints\GroupSequence; + /** * Defines the interface for a group sequence provider. */ @@ -20,7 +22,7 @@ interface GroupSequenceProviderInterface * Returns which validation groups should be used for a certain state * of the object. * - * @return array An array of validation groups + * @return string[]|GroupSequence An array of validation groups */ public function getGroupSequence(); } diff --git a/src/Symfony/Component/Validator/Mapping/ClassMetadata.php b/src/Symfony/Component/Validator/Mapping/ClassMetadata.php index 2b6e9ff4b0..c4e5b11b87 100644 --- a/src/Symfony/Component/Validator/Mapping/ClassMetadata.php +++ b/src/Symfony/Component/Validator/Mapping/ClassMetadata.php @@ -397,7 +397,7 @@ class ClassMetadata extends GenericMetadata implements ClassMetadataInterface /** * Sets the default group sequence for this class. * - * @param array $groupSequence An array of group names + * @param string[]|GroupSequence $groupSequence An array of group names * * @return $this * diff --git a/src/Symfony/Component/Validator/Validator/ContextualValidatorInterface.php b/src/Symfony/Component/Validator/Validator/ContextualValidatorInterface.php index 1cc96c834e..c8b545b54b 100644 --- a/src/Symfony/Component/Validator/Validator/ContextualValidatorInterface.php +++ b/src/Symfony/Component/Validator/Validator/ContextualValidatorInterface.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Validator\Validator; use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\Constraints\GroupSequence; use Symfony\Component\Validator\ConstraintViolationListInterface; /** @@ -39,12 +40,9 @@ interface ContextualValidatorInterface * If no constraint is passed, the constraint * {@link \Symfony\Component\Validator\Constraints\Valid} is assumed. * - * @param mixed $value The value to validate - * @param Constraint|Constraint[] $constraints The constraint(s) to validate - * against - * @param array|null $groups The validation groups to - * validate. If none is given, - * "Default" is assumed + * @param mixed $value The value to validate + * @param Constraint|Constraint[] $constraints The constraint(s) to validate against + * @param string|GroupSequence|(string|GroupSequence)[]|null $groups The validation groups to validate. If none is given, "Default" is assumed * * @return $this */ @@ -54,10 +52,9 @@ interface ContextualValidatorInterface * Validates a property of an object against the constraints specified * for this property. * - * @param object $object The object - * @param string $propertyName The name of the validated property - * @param array|null $groups The validation groups to validate. If - * none is given, "Default" is assumed + * @param object $object The object + * @param string $propertyName The name of the validated property + * @param string|GroupSequence|(string|GroupSequence)[]|null $groups The validation groups to validate. If none is given, "Default" is assumed * * @return $this */ @@ -67,12 +64,10 @@ interface ContextualValidatorInterface * Validates a value against the constraints specified for an object's * property. * - * @param object|string $objectOrClass The object or its class name - * @param string $propertyName The name of the property - * @param mixed $value The value to validate against the - * property's constraints - * @param array|null $groups The validation groups to validate. If - * none is given, "Default" is assumed + * @param object|string $objectOrClass The object or its class name + * @param string $propertyName The name of the property + * @param mixed $value The value to validate against the property's constraints + * @param string|GroupSequence|(string|GroupSequence)[]|null $groups The validation groups to validate. If none is given, "Default" is assumed * * @return $this */ diff --git a/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php b/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php index d8434a96d4..c1af13eaa0 100644 --- a/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php +++ b/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php @@ -272,9 +272,9 @@ class RecursiveContextualValidator implements ContextualValidatorInterface /** * Normalizes the given group or list of groups to an array. * - * @param mixed $groups The groups to normalize + * @param string|GroupSequence|(string|GroupSequence)[] $groups The groups to normalize * - * @return array A group array + * @return (string|GroupSequence)[] A group array */ protected function normalizeGroups($groups) { @@ -295,7 +295,7 @@ class RecursiveContextualValidator implements ContextualValidatorInterface * * @param object $object The object to cascade * @param string $propertyPath The current property path - * @param string[] $groups The validated groups + * @param (string|GroupSequence)[] $groups The validated groups * @param int $traversalStrategy The strategy for traversing the * cascaded object * @param ExecutionContextInterface $context The current execution context @@ -355,10 +355,10 @@ class RecursiveContextualValidator implements ContextualValidatorInterface * objects are iterated as well. Nested arrays are always iterated, * regardless of the value of $recursive. * - * @param iterable $collection The collection - * @param string $propertyPath The current property path - * @param string[] $groups The validated groups - * @param ExecutionContextInterface $context The current execution context + * @param iterable $collection The collection + * @param string $propertyPath The current property path + * @param (string|GroupSequence)[] $groups The validated groups + * @param ExecutionContextInterface $context The current execution context * * @see ClassNode * @see CollectionNode @@ -424,7 +424,7 @@ class RecursiveContextualValidator implements ContextualValidatorInterface * the object * @param string $propertyPath The property path leading * to the object - * @param string[] $groups The groups in which the + * @param (string|GroupSequence)[] $groups The groups in which the * object should be validated * @param string[]|null $cascadedGroups The groups in which * cascaded objects should @@ -608,7 +608,7 @@ class RecursiveContextualValidator implements ContextualValidatorInterface * value * @param string $propertyPath The property path leading * to the value - * @param string[] $groups The groups in which the + * @param (string|GroupSequence)[] $groups The groups in which the * value should be validated * @param string[]|null $cascadedGroups The groups in which * cascaded objects should diff --git a/src/Symfony/Component/Validator/Validator/ValidatorInterface.php b/src/Symfony/Component/Validator/Validator/ValidatorInterface.php index 5bac2e8898..78157465ab 100644 --- a/src/Symfony/Component/Validator/Validator/ValidatorInterface.php +++ b/src/Symfony/Component/Validator/Validator/ValidatorInterface.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Validator\Validator; use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\Constraints\GroupSequence; use Symfony\Component\Validator\ConstraintViolationListInterface; use Symfony\Component\Validator\Context\ExecutionContextInterface; use Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface; @@ -29,12 +30,9 @@ interface ValidatorInterface extends MetadataFactoryInterface * If no constraint is passed, the constraint * {@link \Symfony\Component\Validator\Constraints\Valid} is assumed. * - * @param mixed $value The value to validate - * @param Constraint|Constraint[] $constraints The constraint(s) to validate - * against - * @param array|null $groups The validation groups to - * validate. If none is given, - * "Default" is assumed + * @param mixed $value The value to validate + * @param Constraint|Constraint[] $constraints The constraint(s) to validate against + * @param string|GroupSequence|(string|GroupSequence)[]|null $groups The validation groups to validate. If none is given, "Default" is assumed * * @return ConstraintViolationListInterface A list of constraint violations * If the list is empty, validation @@ -46,10 +44,9 @@ interface ValidatorInterface extends MetadataFactoryInterface * Validates a property of an object against the constraints specified * for this property. * - * @param object $object The object - * @param string $propertyName The name of the validated property - * @param array|null $groups The validation groups to validate. If - * none is given, "Default" is assumed + * @param object $object The object + * @param string $propertyName The name of the validated property + * @param string|GroupSequence|(string|GroupSequence)[]|null $groups The validation groups to validate. If none is given, "Default" is assumed * * @return ConstraintViolationListInterface A list of constraint violations * If the list is empty, validation @@ -61,12 +58,10 @@ interface ValidatorInterface extends MetadataFactoryInterface * Validates a value against the constraints specified for an object's * property. * - * @param object|string $objectOrClass The object or its class name - * @param string $propertyName The name of the property - * @param mixed $value The value to validate against the - * property's constraints - * @param array|null $groups The validation groups to validate. If - * none is given, "Default" is assumed + * @param object|string $objectOrClass The object or its class name + * @param string $propertyName The name of the property + * @param mixed $value The value to validate against the property's constraints + * @param string|GroupSequence|(string|GroupSequence)[]|null $groups The validation groups to validate. If none is given, "Default" is assumed * * @return ConstraintViolationListInterface A list of constraint violations * If the list is empty, validation