Merge branch '2.7' into 2.8
* 2.7: [Console] SymfonyStyle : Fix blocks wordwrapping [Console] SymfonyStyle : Fix blocks output is broken on windows cmd [Validator] remove partial deprecation annotation Updated UPGRADE-2.4.md [Form] Support DateTimeImmutable in transform() Show the FormType and FormTypeExtension in case of deprecated use of setDefaultOptions [FrameworkBundle] Document form.csrf_provider service deprecation [Form] add test to avoid regression of #14891 without this change allways the legacy code get called [Form] Fix call to removed method (BC broken in 2.3) Fix ask and askHidden methods [HttpFoundation] Get response content as resource several times for PHP >= 5.6 Change error message to reflect SecurityContext deprecation. fixed merge Issue #14815 [Console] SymfonyStyle : fix & automate block gaps. [Console] SymfonyStyle : Improve EOL consistency by relying on output instance Improved duplicated code in FileLocator
This commit is contained in:
commit
f38296b58c
@ -7,3 +7,44 @@ Form
|
||||
* The constructor parameter `$precision` in `IntegerToLocalizedStringTransformer`
|
||||
is now ignored completely, because a precision does not make sense for
|
||||
integers.
|
||||
|
||||
EventDispatcher
|
||||
----------------
|
||||
|
||||
* The `getDispatcher()` and `getName()` methods from `Symfony\Component\EventDispatcher\Event`
|
||||
are deprecated, the event dispatcher instance and event name can be received in the listener call instead.
|
||||
|
||||
Before:
|
||||
|
||||
```php
|
||||
use Symfony\Component\EventDispatcher\Event;
|
||||
|
||||
class Foo
|
||||
{
|
||||
public function myFooListener(Event $event)
|
||||
{
|
||||
$dispatcher = $event->getDispatcher();
|
||||
$eventName = $event->getName();
|
||||
$dispatcher->dispatch('log', $event);
|
||||
|
||||
// ... more code
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```php
|
||||
use Symfony\Component\EventDispatcher\Event;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
class Foo
|
||||
{
|
||||
public function myFooListener(Event $event, $eventName, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$dispatcher->dispatch('log', $event);
|
||||
|
||||
// ... more code
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -455,6 +455,12 @@ UPGRADE FROM 2.x to 3.0
|
||||
engines: ['php']
|
||||
```
|
||||
|
||||
* The `form.csrf_provider` service is removed as it implements an adapter for
|
||||
the new token manager to the deprecated
|
||||
`Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface`
|
||||
interface.
|
||||
The `security.csrf.token_manager` should be used instead.
|
||||
|
||||
### HttpKernel
|
||||
|
||||
* The `Symfony\Component\HttpKernel\Log\LoggerInterface` has been removed in
|
||||
|
@ -47,15 +47,15 @@ class FileLocator implements FileLocatorInterface
|
||||
return $name;
|
||||
}
|
||||
|
||||
$filepaths = array();
|
||||
if (null !== $currentPath && file_exists($file = $currentPath.DIRECTORY_SEPARATOR.$name)) {
|
||||
if (true === $first) {
|
||||
return $file;
|
||||
}
|
||||
$filepaths[] = $file;
|
||||
$paths = $this->paths;
|
||||
|
||||
if (null !== $currentPath) {
|
||||
array_unshift($paths, $currentPath);
|
||||
}
|
||||
|
||||
foreach ($this->paths as $path) {
|
||||
$filepaths = array();
|
||||
|
||||
foreach ($paths as $path) {
|
||||
if (file_exists($file = $path.DIRECTORY_SEPARATOR.$name)) {
|
||||
if (true === $first) {
|
||||
return $file;
|
||||
@ -65,7 +65,7 @@ class FileLocator implements FileLocatorInterface
|
||||
}
|
||||
|
||||
if (!$filepaths) {
|
||||
throw new \InvalidArgumentException(sprintf('The file "%s" does not exist (in: %s%s).', $name, null !== $currentPath ? $currentPath.', ' : '', implode(', ', $this->paths)));
|
||||
throw new \InvalidArgumentException(sprintf('The file "%s" does not exist (in: %s).', $name, implode(', ', $paths)));
|
||||
}
|
||||
|
||||
return array_values(array_unique($filepaths));
|
||||
|
@ -18,6 +18,7 @@ use Symfony\Component\Console\Helper\ProgressBar;
|
||||
use Symfony\Component\Console\Helper\SymfonyQuestionHelper;
|
||||
use Symfony\Component\Console\Helper\Table;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\BufferedOutput;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Question\ChoiceQuestion;
|
||||
use Symfony\Component\Console\Question\ConfirmationQuestion;
|
||||
@ -36,6 +37,7 @@ class SymfonyStyle extends OutputStyle
|
||||
private $questionHelper;
|
||||
private $progressBar;
|
||||
private $lineLength;
|
||||
private $bufferedOutput;
|
||||
|
||||
/**
|
||||
* @param InputInterface $input
|
||||
@ -44,7 +46,9 @@ class SymfonyStyle extends OutputStyle
|
||||
public function __construct(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$this->input = $input;
|
||||
$this->lineLength = min($this->getTerminalWidth(), self::MAX_LINE_LENGTH);
|
||||
$this->bufferedOutput = new BufferedOutput($output->getVerbosity(), false, clone $output->getFormatter());
|
||||
// Windows cmd wraps lines as soon as the terminal width is reached, whether there are following chars or not.
|
||||
$this->lineLength = min($this->getTerminalWidth() - (int) (DIRECTORY_SEPARATOR === '\\'), self::MAX_LINE_LENGTH);
|
||||
|
||||
parent::__construct($output);
|
||||
}
|
||||
@ -60,6 +64,7 @@ class SymfonyStyle extends OutputStyle
|
||||
*/
|
||||
public function block($messages, $type = null, $style = null, $prefix = ' ', $padding = false)
|
||||
{
|
||||
$this->autoPrependBlock();
|
||||
$messages = is_array($messages) ? array_values($messages) : array($messages);
|
||||
$lines = array();
|
||||
|
||||
@ -71,7 +76,7 @@ class SymfonyStyle extends OutputStyle
|
||||
// wrap and add newlines for each element
|
||||
foreach ($messages as $key => $message) {
|
||||
$message = OutputFormatter::escape($message);
|
||||
$lines = array_merge($lines, explode("\n", wordwrap($message, $this->lineLength - Helper::strlen($prefix))));
|
||||
$lines = array_merge($lines, explode(PHP_EOL, wordwrap($message, $this->lineLength - Helper::strlen($prefix), PHP_EOL, true)));
|
||||
|
||||
if (count($messages) > 1 && $key < count($messages) - 1) {
|
||||
$lines[] = '';
|
||||
@ -92,7 +97,8 @@ class SymfonyStyle extends OutputStyle
|
||||
}
|
||||
}
|
||||
|
||||
$this->writeln(implode("\n", $lines)."\n");
|
||||
$this->writeln($lines);
|
||||
$this->newLine();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -100,7 +106,12 @@ class SymfonyStyle extends OutputStyle
|
||||
*/
|
||||
public function title($message)
|
||||
{
|
||||
$this->writeln(sprintf("\n<comment>%s</>\n<comment>%s</>\n", $message, str_repeat('=', strlen($message))));
|
||||
$this->autoPrependBlock();
|
||||
$this->writeln(array(
|
||||
sprintf('<comment>%s</>', $message),
|
||||
sprintf('<comment>%s</>', str_repeat('=', strlen($message))),
|
||||
));
|
||||
$this->newLine();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -108,7 +119,12 @@ class SymfonyStyle extends OutputStyle
|
||||
*/
|
||||
public function section($message)
|
||||
{
|
||||
$this->writeln(sprintf("<comment>%s</>\n<comment>%s</>\n", $message, str_repeat('-', strlen($message))));
|
||||
$this->autoPrependBlock();
|
||||
$this->writeln(array(
|
||||
sprintf('<comment>%s</>', $message),
|
||||
sprintf('<comment>%s</>', str_repeat('-', strlen($message))),
|
||||
));
|
||||
$this->newLine();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -116,13 +132,13 @@ class SymfonyStyle extends OutputStyle
|
||||
*/
|
||||
public function listing(array $elements)
|
||||
{
|
||||
$this->autoPrependText();
|
||||
$elements = array_map(function ($element) {
|
||||
return sprintf(' * %s', $element);
|
||||
},
|
||||
$elements
|
||||
);
|
||||
return sprintf(' * %s', $element);
|
||||
}, $elements);
|
||||
|
||||
$this->writeln(implode("\n", $elements)."\n");
|
||||
$this->writeln($elements);
|
||||
$this->newLine();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -130,6 +146,8 @@ class SymfonyStyle extends OutputStyle
|
||||
*/
|
||||
public function text($message)
|
||||
{
|
||||
$this->autoPrependText();
|
||||
|
||||
if (!is_array($message)) {
|
||||
$this->writeln(sprintf(' // %s', $message));
|
||||
|
||||
@ -205,7 +223,7 @@ class SymfonyStyle extends OutputStyle
|
||||
$question = new Question($question, $default);
|
||||
$question->setValidator($validator);
|
||||
|
||||
return $this->askQuestion($question, $validator);
|
||||
return $this->askQuestion($question);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -214,9 +232,11 @@ class SymfonyStyle extends OutputStyle
|
||||
public function askHidden($question, $validator = null)
|
||||
{
|
||||
$question = new Question($question);
|
||||
$question->setHidden(true);
|
||||
|
||||
return $this->askQuestion($question, $validator);
|
||||
$question->setHidden(true);
|
||||
$question->setValidator($validator);
|
||||
|
||||
return $this->askQuestion($question);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -290,17 +310,51 @@ class SymfonyStyle extends OutputStyle
|
||||
*/
|
||||
public function askQuestion(Question $question)
|
||||
{
|
||||
if ($this->input->isInteractive()) {
|
||||
$this->autoPrependBlock();
|
||||
}
|
||||
|
||||
if (!$this->questionHelper) {
|
||||
$this->questionHelper = new SymfonyQuestionHelper();
|
||||
}
|
||||
|
||||
$answer = $this->questionHelper->ask($this->input, $this, $question);
|
||||
|
||||
$this->newLine();
|
||||
if ($this->input->isInteractive()) {
|
||||
$this->newLine();
|
||||
$this->bufferedOutput->write("\n");
|
||||
}
|
||||
|
||||
return $answer;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function writeln($messages, $type = self::OUTPUT_NORMAL)
|
||||
{
|
||||
parent::writeln($messages, $type);
|
||||
$this->bufferedOutput->writeln($this->reduceBuffer($messages), $type);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL)
|
||||
{
|
||||
parent::write($messages, $newline, $type);
|
||||
$this->bufferedOutput->write($this->reduceBuffer($messages), $newline, $type);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function newLine($count = 1)
|
||||
{
|
||||
parent::newLine($count);
|
||||
$this->bufferedOutput->write(str_repeat("\n", $count));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ProgressBar
|
||||
*/
|
||||
@ -320,4 +374,33 @@ class SymfonyStyle extends OutputStyle
|
||||
|
||||
return $dimensions[0] ?: self::MAX_LINE_LENGTH;
|
||||
}
|
||||
|
||||
private function autoPrependBlock()
|
||||
{
|
||||
$chars = substr(str_replace(PHP_EOL, "\n", $this->bufferedOutput->fetch()), -2);
|
||||
|
||||
if (false === $chars) {
|
||||
return $this->newLine(); //empty history, so we should start with a new line.
|
||||
}
|
||||
//Prepend new line for each non LF chars (This means no blank line was output before)
|
||||
$this->newLine(2 - substr_count($chars, "\n"));
|
||||
}
|
||||
|
||||
private function autoPrependText()
|
||||
{
|
||||
$fetched = $this->bufferedOutput->fetch();
|
||||
//Prepend new line if last char isn't EOL:
|
||||
if ("\n" !== substr($fetched, -1)) {
|
||||
$this->newLine();
|
||||
}
|
||||
}
|
||||
|
||||
private function reduceBuffer($messages)
|
||||
{
|
||||
// We need to know if the two last chars are PHP_EOL
|
||||
// Preserve the last 4 chars inserted (PHP_EOL on windows is two chars) in the history buffer
|
||||
return array_map(function ($value) {
|
||||
return substr($value, -4);
|
||||
}, array_merge(array($this->bufferedOutput->fetch()), (array) $messages));
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
|
||||
//Ensure has single blank line at start when using block element
|
||||
return function (InputInterface $input, OutputInterface $output) {
|
||||
$output = new SymfonyStyle($input, $output);
|
||||
$output->caution('Lorem ipsum dolor sit amet');
|
||||
};
|
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
|
||||
//Ensure has single blank line between titles and blocks
|
||||
return function (InputInterface $input, OutputInterface $output) {
|
||||
$output = new SymfonyStyle($input, $output);
|
||||
$output->title('Title');
|
||||
$output->warning('Lorem ipsum dolor sit amet');
|
||||
$output->title('Title');
|
||||
};
|
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
|
||||
//Ensure has single blank line between blocks
|
||||
return function (InputInterface $input, OutputInterface $output) {
|
||||
$output = new SymfonyStyle($input, $output);
|
||||
$output->warning('Warning');
|
||||
$output->caution('Caution');
|
||||
$output->error('Error');
|
||||
$output->success('Success');
|
||||
$output->note('Note');
|
||||
$output->block('Custom block', 'CUSTOM', 'fg=white;bg=green', 'X ', true);
|
||||
};
|
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
|
||||
//Ensure has single blank line between two titles
|
||||
return function (InputInterface $input, OutputInterface $output) {
|
||||
$output = new SymfonyStyle($input, $output);
|
||||
$output->title('First title');
|
||||
$output->title('Second title');
|
||||
};
|
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
|
||||
//Ensure has single blank line after any text and a title
|
||||
return function (InputInterface $input, OutputInterface $output) {
|
||||
$output = new SymfonyStyle($input, $output);
|
||||
|
||||
$output->write('Lorem ipsum dolor sit amet');
|
||||
$output->title('First title');
|
||||
|
||||
$output->writeln('Lorem ipsum dolor sit amet');
|
||||
$output->title('Second title');
|
||||
|
||||
$output->write('Lorem ipsum dolor sit amet');
|
||||
$output->write('');
|
||||
$output->title('Third title');
|
||||
|
||||
//Ensure edge case by appending empty strings to history:
|
||||
$output->write('Lorem ipsum dolor sit amet');
|
||||
$output->write(array('', '', ''));
|
||||
$output->title('Fourth title');
|
||||
|
||||
//Ensure have manual control over number of blank lines:
|
||||
$output->writeln('Lorem ipsum dolor sit amet');
|
||||
$output->writeln(array('', '')); //Should append an extra blank line
|
||||
$output->title('Fifth title');
|
||||
|
||||
$output->writeln('Lorem ipsum dolor sit amet');
|
||||
$output->newLine(2); //Should append an extra blank line
|
||||
$output->title('Fifth title');
|
||||
};
|
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
|
||||
//Ensure has proper line ending before outputing a text block like with SymfonyStyle::listing() or SymfonyStyle::text()
|
||||
return function (InputInterface $input, OutputInterface $output) {
|
||||
$output = new SymfonyStyle($input, $output);
|
||||
|
||||
$output->writeln('Lorem ipsum dolor sit amet');
|
||||
$output->listing(array(
|
||||
'Lorem ipsum dolor sit amet',
|
||||
'consectetur adipiscing elit',
|
||||
));
|
||||
|
||||
//Even using write:
|
||||
$output->write('Lorem ipsum dolor sit amet');
|
||||
$output->listing(array(
|
||||
'Lorem ipsum dolor sit amet',
|
||||
'consectetur adipiscing elit',
|
||||
));
|
||||
|
||||
$output->write('Lorem ipsum dolor sit amet');
|
||||
$output->text(array(
|
||||
'Lorem ipsum dolor sit amet',
|
||||
'consectetur adipiscing elit',
|
||||
));
|
||||
};
|
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
|
||||
//Ensure has proper blank line after text block when using a block like with SymfonyStyle::success
|
||||
return function (InputInterface $input, OutputInterface $output) {
|
||||
$output = new SymfonyStyle($input, $output);
|
||||
|
||||
$output->listing(array(
|
||||
'Lorem ipsum dolor sit amet',
|
||||
'consectetur adipiscing elit',
|
||||
));
|
||||
$output->success('Lorem ipsum dolor sit amet');
|
||||
};
|
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
|
||||
//Ensure questions do not output anything when input is non-interactive
|
||||
return function (InputInterface $input, OutputInterface $output) {
|
||||
$output = new SymfonyStyle($input, $output);
|
||||
$output->title('Title');
|
||||
$output->askHidden('Hidden question');
|
||||
$output->choice('Choice question with default', array('choice1', 'choice2'), 'choice1');
|
||||
$output->confirm('Confirmation with yes default', true);
|
||||
$output->text('Duis aute irure dolor in reprehenderit in voluptate velit esse');
|
||||
};
|
@ -0,0 +1,3 @@
|
||||
|
||||
! [CAUTION] Lorem ipsum dolor sit amet
|
||||
|
@ -0,0 +1,9 @@
|
||||
|
||||
Title
|
||||
=====
|
||||
|
||||
[WARNING] Lorem ipsum dolor sit amet
|
||||
|
||||
Title
|
||||
=====
|
||||
|
@ -0,0 +1,13 @@
|
||||
|
||||
[WARNING] Warning
|
||||
|
||||
! [CAUTION] Caution
|
||||
|
||||
[ERROR] Error
|
||||
|
||||
[OK] Success
|
||||
|
||||
! [NOTE] Note
|
||||
|
||||
X [CUSTOM] Custom block
|
||||
|
@ -0,0 +1,7 @@
|
||||
|
||||
First title
|
||||
===========
|
||||
|
||||
Second title
|
||||
============
|
||||
|
@ -0,0 +1,32 @@
|
||||
Lorem ipsum dolor sit amet
|
||||
|
||||
First title
|
||||
===========
|
||||
|
||||
Lorem ipsum dolor sit amet
|
||||
|
||||
Second title
|
||||
============
|
||||
|
||||
Lorem ipsum dolor sit amet
|
||||
|
||||
Third title
|
||||
===========
|
||||
|
||||
Lorem ipsum dolor sit amet
|
||||
|
||||
Fourth title
|
||||
============
|
||||
|
||||
Lorem ipsum dolor sit amet
|
||||
|
||||
|
||||
Fifth title
|
||||
===========
|
||||
|
||||
Lorem ipsum dolor sit amet
|
||||
|
||||
|
||||
Fifth title
|
||||
===========
|
||||
|
@ -0,0 +1,11 @@
|
||||
Lorem ipsum dolor sit amet
|
||||
* Lorem ipsum dolor sit amet
|
||||
* consectetur adipiscing elit
|
||||
|
||||
Lorem ipsum dolor sit amet
|
||||
* Lorem ipsum dolor sit amet
|
||||
* consectetur adipiscing elit
|
||||
|
||||
Lorem ipsum dolor sit amet
|
||||
// Lorem ipsum dolor sit amet
|
||||
// consectetur adipiscing elit
|
@ -0,0 +1,6 @@
|
||||
|
||||
* Lorem ipsum dolor sit amet
|
||||
* consectetur adipiscing elit
|
||||
|
||||
[OK] Lorem ipsum dolor sit amet
|
||||
|
@ -0,0 +1,5 @@
|
||||
|
||||
Title
|
||||
=====
|
||||
|
||||
// Duis aute irure dolor in reprehenderit in voluptate velit esse
|
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Console\Tests\Style;
|
||||
|
||||
use PHPUnit_Framework_TestCase;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
use Symfony\Component\Console\Tester\CommandTester;
|
||||
|
||||
class SymfonyStyleTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
/** @var Command */
|
||||
protected $command;
|
||||
/** @var CommandTester */
|
||||
protected $tester;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->command = new Command('sfstyle');
|
||||
$this->tester = new CommandTester($this->command);
|
||||
}
|
||||
|
||||
protected function tearDown()
|
||||
{
|
||||
$this->command = null;
|
||||
$this->tester = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider inputCommandToOutputFilesProvider
|
||||
*/
|
||||
public function testOutputs($inputCommandFilepath, $outputFilepath)
|
||||
{
|
||||
$code = require $inputCommandFilepath;
|
||||
$this->command->setCode($code);
|
||||
$this->tester->execute(array(), array('interactive' => false, 'decorated' => false));
|
||||
$this->assertStringEqualsFile($outputFilepath, $this->tester->getDisplay(true));
|
||||
}
|
||||
|
||||
public function inputCommandToOutputFilesProvider()
|
||||
{
|
||||
$baseDir = __DIR__.'/../Fixtures/Style/SymfonyStyle';
|
||||
|
||||
return array_map(null, glob($baseDir.'/command/command_*.php'), glob($baseDir.'/output/output_*.txt'));
|
||||
}
|
||||
|
||||
public function testLongWordsBlockWrapping()
|
||||
{
|
||||
$word = 'Lopadotemachoselachogaleokranioleipsanodrimhypotrimmatosilphioparaomelitokatakechymenokichlepikossyphophattoperisteralektryonoptekephalliokigklopeleiolagoiosiraiobaphetraganopterygon';
|
||||
$wordLength = strlen($word);
|
||||
$maxLineLength = SymfonyStyle::MAX_LINE_LENGTH - 3;
|
||||
|
||||
$this->command->setCode(function (InputInterface $input, OutputInterface $output) use ($word) {
|
||||
$sfStyle = new SymfonyStyle($input, $output);
|
||||
$sfStyle->block($word, 'CUSTOM', 'fg=white;bg=blue', ' § ', false);
|
||||
});
|
||||
|
||||
$this->tester->execute(array(), array('interactive' => false, 'decorated' => false));
|
||||
$expectedCount = (int) ceil($wordLength / ($maxLineLength)) + (int) ($wordLength > $maxLineLength - 5);
|
||||
$this->assertSame($expectedCount, substr_count($this->tester->getDisplay(true), ' § '));
|
||||
}
|
||||
}
|
@ -51,7 +51,7 @@ class DateTimeToArrayTransformer extends BaseDateTimeTransformer
|
||||
/**
|
||||
* Transforms a normalized date into a localized date.
|
||||
*
|
||||
* @param \DateTime $dateTime Normalized date.
|
||||
* @param \DateTime|\DateTimeInterface $dateTime A DateTime object
|
||||
*
|
||||
* @return array Localized date.
|
||||
*
|
||||
@ -72,14 +72,17 @@ class DateTimeToArrayTransformer extends BaseDateTimeTransformer
|
||||
), array_flip($this->fields));
|
||||
}
|
||||
|
||||
if (!$dateTime instanceof \DateTime) {
|
||||
throw new TransformationFailedException('Expected a \DateTime.');
|
||||
if (!$dateTime instanceof \DateTime && !$dateTime instanceof \DateTimeInterface) {
|
||||
throw new TransformationFailedException('Expected a \DateTime or \DateTimeInterface.');
|
||||
}
|
||||
|
||||
$dateTime = clone $dateTime;
|
||||
if ($this->inputTimezone !== $this->outputTimezone) {
|
||||
if (!$dateTime instanceof \DateTimeImmutable) {
|
||||
$dateTime = clone $dateTime;
|
||||
}
|
||||
|
||||
try {
|
||||
$dateTime->setTimezone(new \DateTimeZone($this->outputTimezone));
|
||||
$dateTime = $dateTime->setTimezone(new \DateTimeZone($this->outputTimezone));
|
||||
} catch (\Exception $e) {
|
||||
throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e);
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ class DateTimeToLocalizedStringTransformer extends BaseDateTimeTransformer
|
||||
/**
|
||||
* Transforms a normalized date into a localized date string/array.
|
||||
*
|
||||
* @param \DateTime $dateTime Normalized date.
|
||||
* @param \DateTime|\DateTimeInterface $dateTime A DateTime object
|
||||
*
|
||||
* @return string|array Localized date string/array.
|
||||
*
|
||||
@ -84,17 +84,11 @@ class DateTimeToLocalizedStringTransformer extends BaseDateTimeTransformer
|
||||
return '';
|
||||
}
|
||||
|
||||
if (!$dateTime instanceof \DateTime) {
|
||||
throw new TransformationFailedException('Expected a \DateTime.');
|
||||
if (!$dateTime instanceof \DateTime && !$dateTime instanceof \DateTimeInterface) {
|
||||
throw new TransformationFailedException('Expected a \DateTime or \DateTimeInterface.');
|
||||
}
|
||||
|
||||
// convert time to UTC before passing it to the formatter
|
||||
$dateTime = clone $dateTime;
|
||||
if ('UTC' !== $this->inputTimezone) {
|
||||
$dateTime->setTimezone(new \DateTimeZone('UTC'));
|
||||
}
|
||||
|
||||
$value = $this->getIntlDateFormatter()->format((int) $dateTime->format('U'));
|
||||
$value = $this->getIntlDateFormatter()->format($dateTime->getTimestamp());
|
||||
|
||||
if (intl_get_error_code() != 0) {
|
||||
throw new TransformationFailedException(intl_get_error_message());
|
||||
|
@ -27,13 +27,13 @@ class DateTimeToRfc3339Transformer extends BaseDateTimeTransformer
|
||||
return '';
|
||||
}
|
||||
|
||||
if (!$dateTime instanceof \DateTime) {
|
||||
throw new TransformationFailedException('Expected a \DateTime.');
|
||||
if (!$dateTime instanceof \DateTime && !$dateTime instanceof \DateTimeInterface) {
|
||||
throw new TransformationFailedException('Expected a \DateTime or \DateTimeInterface.');
|
||||
}
|
||||
|
||||
if ($this->inputTimezone !== $this->outputTimezone) {
|
||||
$dateTime = clone $dateTime;
|
||||
$dateTime->setTimezone(new \DateTimeZone($this->outputTimezone));
|
||||
$dateTime = $dateTime->setTimezone(new \DateTimeZone($this->outputTimezone));
|
||||
}
|
||||
|
||||
return preg_replace('/\+00:00$/', 'Z', $dateTime->format('c'));
|
||||
|
@ -86,7 +86,7 @@ class DateTimeToStringTransformer extends BaseDateTimeTransformer
|
||||
* Transforms a DateTime object into a date string with the configured format
|
||||
* and timezone.
|
||||
*
|
||||
* @param \DateTime $value A DateTime object
|
||||
* @param \DateTime|\DateTimeInterface $dateTime A DateTime object
|
||||
*
|
||||
* @return string A value as produced by PHP's date() function
|
||||
*
|
||||
@ -100,13 +100,16 @@ class DateTimeToStringTransformer extends BaseDateTimeTransformer
|
||||
return '';
|
||||
}
|
||||
|
||||
if (!$value instanceof \DateTime) {
|
||||
throw new TransformationFailedException('Expected a \DateTime.');
|
||||
if (!$value instanceof \DateTime && !$value instanceof \DateTimeInterface) {
|
||||
throw new TransformationFailedException('Expected a \DateTime or \DateTimeInterface.');
|
||||
}
|
||||
|
||||
if (!$value instanceof \DateTimeImmutable) {
|
||||
$value = clone $value;
|
||||
}
|
||||
|
||||
$value = clone $value;
|
||||
try {
|
||||
$value->setTimezone(new \DateTimeZone($this->outputTimezone));
|
||||
$value = $value->setTimezone(new \DateTimeZone($this->outputTimezone));
|
||||
} catch (\Exception $e) {
|
||||
throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e);
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ class DateTimeToTimestampTransformer extends BaseDateTimeTransformer
|
||||
/**
|
||||
* Transforms a DateTime object into a timestamp in the configured timezone.
|
||||
*
|
||||
* @param \DateTime $value A \DateTime object
|
||||
* @param \DateTime|\DateTimeInterface $dateTime A DateTime object
|
||||
*
|
||||
* @return int A timestamp
|
||||
*
|
||||
@ -38,18 +38,11 @@ class DateTimeToTimestampTransformer extends BaseDateTimeTransformer
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$value instanceof \DateTime) {
|
||||
throw new TransformationFailedException('Expected a \DateTime.');
|
||||
if (!$value instanceof \DateTime && !$value instanceof \DateTimeInterface) {
|
||||
throw new TransformationFailedException('Expected a \DateTime or \DateTimeInterface.');
|
||||
}
|
||||
|
||||
$value = clone $value;
|
||||
try {
|
||||
$value->setTimezone(new \DateTimeZone($this->outputTimezone));
|
||||
} catch (\Exception $e) {
|
||||
throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e);
|
||||
}
|
||||
|
||||
return (int) $value->format('U');
|
||||
return $value->getTimestamp();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -59,13 +59,13 @@ class ValidatorExtension extends AbstractExtension
|
||||
|
||||
public function loadTypeGuesser()
|
||||
{
|
||||
// 2.4 API
|
||||
if ($this->validator instanceof LegacyValidatorInterface) {
|
||||
return new ValidatorTypeGuesser($this->validator->getMetadataFactory());
|
||||
// 2.5 API
|
||||
if ($this->validator instanceof ValidatorInterface) {
|
||||
return new ValidatorTypeGuesser($this->validator);
|
||||
}
|
||||
|
||||
// 2.5 API - ValidatorInterface extends MetadataFactoryInterface
|
||||
return new ValidatorTypeGuesser($this->validator);
|
||||
// 2.4 API
|
||||
return new ValidatorTypeGuesser($this->validator->getMetadataFactory());
|
||||
}
|
||||
|
||||
protected function loadTypeExtensions()
|
||||
|
@ -93,11 +93,6 @@ class ResolvedFormType implements ResolvedFormTypeInterface
|
||||
*/
|
||||
public function getTypeExtensions()
|
||||
{
|
||||
// BC
|
||||
if ($this->innerType instanceof AbstractType) {
|
||||
return $this->innerType->getExtensions();
|
||||
}
|
||||
|
||||
return $this->typeExtensions;
|
||||
}
|
||||
|
||||
@ -212,7 +207,7 @@ class ResolvedFormType implements ResolvedFormTypeInterface
|
||||
$isNewOverwritten = $reflector->getDeclaringClass()->getName() !== 'Symfony\Component\Form\AbstractType';
|
||||
|
||||
if ($isOldOverwritten && !$isNewOverwritten) {
|
||||
trigger_error('The FormTypeInterface::setDefaultOptions() method is deprecated since version 2.7 and will be removed in 3.0. Use configureOptions() instead. This method will be added to the FormTypeInterface with Symfony 3.0.', E_USER_DEPRECATED);
|
||||
trigger_error(get_class($this->innerType).': The FormTypeInterface::setDefaultOptions() method is deprecated since version 2.7 and will be removed in 3.0. Use configureOptions() instead. This method will be added to the FormTypeInterface with Symfony 3.0.', E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
foreach ($this->typeExtensions as $extension) {
|
||||
@ -225,7 +220,7 @@ class ResolvedFormType implements ResolvedFormTypeInterface
|
||||
$isNewOverwritten = $reflector->getDeclaringClass()->getName() !== 'Symfony\Component\Form\AbstractTypeExtension';
|
||||
|
||||
if ($isOldOverwritten && !$isNewOverwritten) {
|
||||
trigger_error('The FormTypeExtensionInterface::setDefaultOptions() method is deprecated since version 2.7 and will be removed in 3.0. Use configureOptions() instead. This method will be added to the FormTypeExtensionInterface with Symfony 3.0.', E_USER_DEPRECATED);
|
||||
trigger_error(get_class($extension).': The FormTypeExtensionInterface::setDefaultOptions() method is deprecated since version 2.7 and will be removed in 3.0. Use configureOptions() instead. This method will be added to the FormTypeExtensionInterface with Symfony 3.0.', E_USER_DEPRECATED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -116,6 +116,30 @@ class DateTimeToArrayTransformerTest extends DateTimeTestCase
|
||||
$this->assertSame($output, $transformer->transform($input));
|
||||
}
|
||||
|
||||
public function testTransformDateTimeImmutable()
|
||||
{
|
||||
if (PHP_VERSION_ID < 50500) {
|
||||
$this->markTestSkipped('DateTimeImmutable was introduced in PHP 5.5.0');
|
||||
}
|
||||
|
||||
$transformer = new DateTimeToArrayTransformer('America/New_York', 'Asia/Hong_Kong');
|
||||
|
||||
$input = new \DateTimeImmutable('2010-02-03 04:05:06 America/New_York');
|
||||
|
||||
$dateTime = new \DateTimeImmutable('2010-02-03 04:05:06 America/New_York');
|
||||
$dateTime = $dateTime->setTimezone(new \DateTimeZone('Asia/Hong_Kong'));
|
||||
$output = array(
|
||||
'year' => (string) (int) $dateTime->format('Y'),
|
||||
'month' => (string) (int) $dateTime->format('m'),
|
||||
'day' => (string) (int) $dateTime->format('d'),
|
||||
'hour' => (string) (int) $dateTime->format('H'),
|
||||
'minute' => (string) (int) $dateTime->format('i'),
|
||||
'second' => (string) (int) $dateTime->format('s'),
|
||||
);
|
||||
|
||||
$this->assertSame($output, $transformer->transform($input));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
|
||||
*/
|
||||
|
@ -141,6 +141,22 @@ class DateTimeToLocalizedStringTransformerTest extends DateTimeTestCase
|
||||
$this->assertEquals('02*2010*03 04|05|06', $transformer->transform($this->dateTime));
|
||||
}
|
||||
|
||||
public function testTransformDateTimeImmutableTimezones()
|
||||
{
|
||||
if (PHP_VERSION_ID < 50500) {
|
||||
$this->markTestSkipped('DateTimeImmutable was introduced in PHP 5.5.0');
|
||||
}
|
||||
|
||||
$transformer = new DateTimeToLocalizedStringTransformer('America/New_York', 'Asia/Hong_Kong');
|
||||
|
||||
$input = new \DateTimeImmutable('2010-02-03 04:05:06 America/New_York');
|
||||
|
||||
$dateTime = clone $input;
|
||||
$dateTime = $dateTime->setTimezone(new \DateTimeZone('Asia/Hong_Kong'));
|
||||
|
||||
$this->assertEquals($dateTime->format('d.m.Y H:i'), $transformer->transform($input));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
|
||||
*/
|
||||
|
@ -79,6 +79,20 @@ class DateTimeToRfc3339TransformerTest extends DateTimeTestCase
|
||||
$this->assertSame($to, $transformer->transform(null !== $from ? new \DateTime($from) : null));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider transformProvider
|
||||
*/
|
||||
public function testTransformDateTimeImmutable($fromTz, $toTz, $from, $to)
|
||||
{
|
||||
if (PHP_VERSION_ID < 50500) {
|
||||
$this->markTestSkipped('DateTimeImmutable was introduced in PHP 5.5.0');
|
||||
}
|
||||
|
||||
$transformer = new DateTimeToRfc3339Transformer($fromTz, $toTz);
|
||||
|
||||
$this->assertSame($to, $transformer->transform(null !== $from ? new \DateTimeImmutable($from) : null));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
|
||||
*/
|
||||
|
@ -94,6 +94,21 @@ class DateTimeToStringTransformerTest extends DateTimeTestCase
|
||||
$this->assertEquals($output, $transformer->transform($input));
|
||||
}
|
||||
|
||||
public function testTransformDateTimeImmutable()
|
||||
{
|
||||
if (PHP_VERSION_ID < 50500) {
|
||||
$this->markTestSkipped('DateTimeImmutable was introduced in PHP 5.5.0');
|
||||
}
|
||||
|
||||
$transformer = new DateTimeToStringTransformer('Asia/Hong_Kong', 'America/New_York', 'Y-m-d H:i:s');
|
||||
|
||||
$input = new \DateTimeImmutable('2010-02-03 12:05:06 America/New_York');
|
||||
$output = $input->format('Y-m-d H:i:s');
|
||||
$input = $input->setTimezone(new \DateTimeZone('Asia/Hong_Kong'));
|
||||
|
||||
$this->assertEquals($output, $transformer->transform($input));
|
||||
}
|
||||
|
||||
public function testTransformExpectsDateTime()
|
||||
{
|
||||
$transformer = new DateTimeToStringTransformer();
|
||||
|
@ -56,6 +56,21 @@ class DateTimeToTimestampTransformerTest extends DateTimeTestCase
|
||||
$this->assertEquals($output, $transformer->transform($input));
|
||||
}
|
||||
|
||||
public function testTransformDateTimeImmutable()
|
||||
{
|
||||
if (PHP_VERSION_ID < 50500) {
|
||||
$this->markTestSkipped('DateTimeImmutable was introduced in PHP 5.5.0');
|
||||
}
|
||||
|
||||
$transformer = new DateTimeToTimestampTransformer('Asia/Hong_Kong', 'America/New_York');
|
||||
|
||||
$input = new \DateTimeImmutable('2010-02-03 04:05:06 America/New_York');
|
||||
$output = $input->format('U');
|
||||
$input = $input->setTimezone(new \DateTimeZone('Asia/Hong_Kong'));
|
||||
|
||||
$this->assertEquals($output, $transformer->transform($input));
|
||||
}
|
||||
|
||||
public function testTransformExpectsDateTime()
|
||||
{
|
||||
$transformer = new DateTimeToTimestampTransformer();
|
||||
|
@ -17,7 +17,9 @@ class ValidatorExtensionTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function test2Dot5ValidationApi()
|
||||
{
|
||||
$validator = $this->getMock('Symfony\Component\Validator\Validator\ValidatorInterface');
|
||||
$validator = $this->getMockBuilder('Symfony\Component\Validator\Validator\RecursiveValidator')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$metadata = $this->getMockBuilder('Symfony\Component\Validator\Mapping\ClassMetadata')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
@ -36,6 +38,10 @@ class ValidatorExtensionTest extends \PHPUnit_Framework_TestCase
|
||||
->method('addPropertyConstraint')
|
||||
->with('children', $this->isInstanceOf('Symfony\Component\Validator\Constraints\Valid'));
|
||||
|
||||
$validator
|
||||
->expects($this->never())
|
||||
->method('getMetadataFactory');
|
||||
|
||||
$extension = new ValidatorExtension($validator);
|
||||
$guesser = $extension->loadTypeGuesser();
|
||||
|
||||
|
@ -1557,8 +1557,8 @@ class Request
|
||||
*/
|
||||
public function getContent($asResource = false)
|
||||
{
|
||||
if (false === $this->content || (true === $asResource && null !== $this->content)) {
|
||||
throw new \LogicException('getContent() can only be called once when using the resource return type.');
|
||||
if (PHP_VERSION_ID < 50600 && (false === $this->content || (true === $asResource && null !== $this->content))) {
|
||||
throw new \LogicException('getContent() can only be called once when using the resource return type and PHP below 5.6.');
|
||||
}
|
||||
|
||||
if (true === $asResource) {
|
||||
|
@ -975,11 +975,40 @@ class RequestTest extends \PHPUnit_Framework_TestCase
|
||||
*/
|
||||
public function testGetContentCantBeCalledTwiceWithResources($first, $second)
|
||||
{
|
||||
if (PHP_VERSION_ID >= 50600) {
|
||||
$this->markTestSkipped('PHP >= 5.6 allows to open php://input several times.');
|
||||
}
|
||||
|
||||
$req = new Request();
|
||||
$req->getContent($first);
|
||||
$req->getContent($second);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @dataProvider getContentCantBeCalledTwiceWithResourcesProvider
|
||||
*/
|
||||
public function testGetContentCanBeCalledTwiceWithResources($first, $second)
|
||||
{
|
||||
if (PHP_VERSION_ID < 50600) {
|
||||
$this->markTestSkipped('PHP < 5.6 does not allow to open php://input several times.');
|
||||
}
|
||||
|
||||
$req = new Request();
|
||||
$a = $req->getContent($first);
|
||||
$b = $req->getContent($second);
|
||||
|
||||
if ($first) {
|
||||
$a = stream_get_contents($a);
|
||||
}
|
||||
|
||||
if ($second) {
|
||||
$b = stream_get_contents($b);
|
||||
}
|
||||
|
||||
$this->assertEquals($a, $b);
|
||||
}
|
||||
|
||||
public function getContentCantBeCalledTwiceWithResourcesProvider()
|
||||
{
|
||||
return array(
|
||||
|
@ -50,7 +50,7 @@ class AccessListener implements ListenerInterface
|
||||
public function handle(GetResponseEvent $event)
|
||||
{
|
||||
if (null === $token = $this->tokenStorage->getToken()) {
|
||||
throw new AuthenticationCredentialsNotFoundException('A Token was not found in the SecurityContext.');
|
||||
throw new AuthenticationCredentialsNotFoundException('A Token was not found in the TokenStorage.');
|
||||
}
|
||||
|
||||
$request = $event->getRequest();
|
||||
|
@ -91,6 +91,8 @@ interface ExecutionContextInterface
|
||||
/**
|
||||
* Adds a violation at the current node of the validation graph.
|
||||
*
|
||||
* Note: the parameters $invalidValue, $plural and $code are deprecated since version 2.5 and will be removed in 3.0.
|
||||
*
|
||||
* @param string $message The error message
|
||||
* @param array $params The parameters substituted in the error message
|
||||
* @param mixed $invalidValue The invalid, validated value
|
||||
@ -98,8 +100,6 @@ interface ExecutionContextInterface
|
||||
* @param int|null $code The violation code
|
||||
*
|
||||
* @api
|
||||
*
|
||||
* @deprecated the parameters $invalidValue, $plural and $code are deprecated since version 2.5 and will be removed in 3.0.
|
||||
*/
|
||||
public function addViolation($message, array $params = array(), $invalidValue = null, $plural = null, $code = null);
|
||||
|
||||
|
@ -38,6 +38,8 @@ class Yaml
|
||||
* you must validate the input before calling this method. Passing a file
|
||||
* as an input is a deprecated feature and will be removed in 3.0.
|
||||
*
|
||||
* Note: the ability to pass file names to the Yaml::parse method is deprecated since version 2.2 and will be removed in 3.0. Pass the YAML contents of the file instead.
|
||||
*
|
||||
* @param string $input Path to a YAML file or a string containing YAML
|
||||
* @param bool $exceptionOnInvalidType True if an exception must be thrown on invalid types false otherwise
|
||||
* @param bool $objectSupport True if object support is enabled, false otherwise
|
||||
|
Reference in New Issue
Block a user