diff options
author | Frédéric Guillot <fred@kanboard.net> | 2017-12-15 11:24:35 -0800 |
---|---|---|
committer | Frédéric Guillot <fred@kanboard.net> | 2017-12-15 11:55:42 -0800 |
commit | a93b8e10f5954be0853eec693c13e84c4bd9e6f2 (patch) | |
tree | eda5de9494b819235616e8623bb3393e9cc373af /vendor | |
parent | 2c72a283f2d51034f85f4e2ca8b194d304a3c433 (diff) |
Kanboard requires at least PHP 5.6 now
Diffstat (limited to 'vendor')
350 files changed, 14098 insertions, 6196 deletions
diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index b4ca84b7..ec299289 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -61,6 +61,8 @@ return array( 'Kanboard\\Action\\Base' => $baseDir . '/app/Action/Base.php', 'Kanboard\\Action\\CommentCreation' => $baseDir . '/app/Action/CommentCreation.php', 'Kanboard\\Action\\CommentCreationMoveTaskColumn' => $baseDir . '/app/Action/CommentCreationMoveTaskColumn.php', + 'Kanboard\\Action\\StopSubtaskTimerMoveTaskColumn' => $baseDir . '/app/Action/StopSubtaskTimerMoveTaskColumn.php', + 'Kanboard\\Action\\SubtaskTimerMoveTaskColumn' => $baseDir . '/app/Action/SubtaskTimerMoveTaskColumn.php', 'Kanboard\\Action\\TaskAssignCategoryColor' => $baseDir . '/app/Action/TaskAssignCategoryColor.php', 'Kanboard\\Action\\TaskAssignCategoryLabel' => $baseDir . '/app/Action/TaskAssignCategoryLabel.php', 'Kanboard\\Action\\TaskAssignCategoryLink' => $baseDir . '/app/Action/TaskAssignCategoryLink.php', @@ -820,10 +822,15 @@ return array( 'SimpleValidator\\Validators\\Required' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/Required.php', 'SimpleValidator\\Validators\\Unique' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/Unique.php', 'Symfony\\Component\\Console\\Application' => $vendorDir . '/symfony/console/Application.php', + 'Symfony\\Component\\Console\\CommandLoader\\CommandLoaderInterface' => $vendorDir . '/symfony/console/CommandLoader/CommandLoaderInterface.php', + 'Symfony\\Component\\Console\\CommandLoader\\ContainerCommandLoader' => $vendorDir . '/symfony/console/CommandLoader/ContainerCommandLoader.php', + 'Symfony\\Component\\Console\\CommandLoader\\FactoryCommandLoader' => $vendorDir . '/symfony/console/CommandLoader/FactoryCommandLoader.php', 'Symfony\\Component\\Console\\Command\\Command' => $vendorDir . '/symfony/console/Command/Command.php', 'Symfony\\Component\\Console\\Command\\HelpCommand' => $vendorDir . '/symfony/console/Command/HelpCommand.php', 'Symfony\\Component\\Console\\Command\\ListCommand' => $vendorDir . '/symfony/console/Command/ListCommand.php', + 'Symfony\\Component\\Console\\Command\\LockableTrait' => $vendorDir . '/symfony/console/Command/LockableTrait.php', 'Symfony\\Component\\Console\\ConsoleEvents' => $vendorDir . '/symfony/console/ConsoleEvents.php', + 'Symfony\\Component\\Console\\DependencyInjection\\AddConsoleCommandPass' => $vendorDir . '/symfony/console/DependencyInjection/AddConsoleCommandPass.php', 'Symfony\\Component\\Console\\Descriptor\\ApplicationDescription' => $vendorDir . '/symfony/console/Descriptor/ApplicationDescription.php', 'Symfony\\Component\\Console\\Descriptor\\Descriptor' => $vendorDir . '/symfony/console/Descriptor/Descriptor.php', 'Symfony\\Component\\Console\\Descriptor\\DescriptorInterface' => $vendorDir . '/symfony/console/Descriptor/DescriptorInterface.php', @@ -831,7 +838,9 @@ return array( 'Symfony\\Component\\Console\\Descriptor\\MarkdownDescriptor' => $vendorDir . '/symfony/console/Descriptor/MarkdownDescriptor.php', 'Symfony\\Component\\Console\\Descriptor\\TextDescriptor' => $vendorDir . '/symfony/console/Descriptor/TextDescriptor.php', 'Symfony\\Component\\Console\\Descriptor\\XmlDescriptor' => $vendorDir . '/symfony/console/Descriptor/XmlDescriptor.php', + 'Symfony\\Component\\Console\\EventListener\\ErrorListener' => $vendorDir . '/symfony/console/EventListener/ErrorListener.php', 'Symfony\\Component\\Console\\Event\\ConsoleCommandEvent' => $vendorDir . '/symfony/console/Event/ConsoleCommandEvent.php', + 'Symfony\\Component\\Console\\Event\\ConsoleErrorEvent' => $vendorDir . '/symfony/console/Event/ConsoleErrorEvent.php', 'Symfony\\Component\\Console\\Event\\ConsoleEvent' => $vendorDir . '/symfony/console/Event/ConsoleEvent.php', 'Symfony\\Component\\Console\\Event\\ConsoleExceptionEvent' => $vendorDir . '/symfony/console/Event/ConsoleExceptionEvent.php', 'Symfony\\Component\\Console\\Event\\ConsoleTerminateEvent' => $vendorDir . '/symfony/console/Event/ConsoleTerminateEvent.php', @@ -848,7 +857,6 @@ return array( 'Symfony\\Component\\Console\\Formatter\\OutputFormatterStyleStack' => $vendorDir . '/symfony/console/Formatter/OutputFormatterStyleStack.php', 'Symfony\\Component\\Console\\Helper\\DebugFormatterHelper' => $vendorDir . '/symfony/console/Helper/DebugFormatterHelper.php', 'Symfony\\Component\\Console\\Helper\\DescriptorHelper' => $vendorDir . '/symfony/console/Helper/DescriptorHelper.php', - 'Symfony\\Component\\Console\\Helper\\DialogHelper' => $vendorDir . '/symfony/console/Helper/DialogHelper.php', 'Symfony\\Component\\Console\\Helper\\FormatterHelper' => $vendorDir . '/symfony/console/Helper/FormatterHelper.php', 'Symfony\\Component\\Console\\Helper\\Helper' => $vendorDir . '/symfony/console/Helper/Helper.php', 'Symfony\\Component\\Console\\Helper\\HelperInterface' => $vendorDir . '/symfony/console/Helper/HelperInterface.php', @@ -856,13 +864,11 @@ return array( 'Symfony\\Component\\Console\\Helper\\InputAwareHelper' => $vendorDir . '/symfony/console/Helper/InputAwareHelper.php', 'Symfony\\Component\\Console\\Helper\\ProcessHelper' => $vendorDir . '/symfony/console/Helper/ProcessHelper.php', 'Symfony\\Component\\Console\\Helper\\ProgressBar' => $vendorDir . '/symfony/console/Helper/ProgressBar.php', - 'Symfony\\Component\\Console\\Helper\\ProgressHelper' => $vendorDir . '/symfony/console/Helper/ProgressHelper.php', 'Symfony\\Component\\Console\\Helper\\ProgressIndicator' => $vendorDir . '/symfony/console/Helper/ProgressIndicator.php', 'Symfony\\Component\\Console\\Helper\\QuestionHelper' => $vendorDir . '/symfony/console/Helper/QuestionHelper.php', 'Symfony\\Component\\Console\\Helper\\SymfonyQuestionHelper' => $vendorDir . '/symfony/console/Helper/SymfonyQuestionHelper.php', 'Symfony\\Component\\Console\\Helper\\Table' => $vendorDir . '/symfony/console/Helper/Table.php', 'Symfony\\Component\\Console\\Helper\\TableCell' => $vendorDir . '/symfony/console/Helper/TableCell.php', - 'Symfony\\Component\\Console\\Helper\\TableHelper' => $vendorDir . '/symfony/console/Helper/TableHelper.php', 'Symfony\\Component\\Console\\Helper\\TableSeparator' => $vendorDir . '/symfony/console/Helper/TableSeparator.php', 'Symfony\\Component\\Console\\Helper\\TableStyle' => $vendorDir . '/symfony/console/Helper/TableStyle.php', 'Symfony\\Component\\Console\\Input\\ArgvInput' => $vendorDir . '/symfony/console/Input/ArgvInput.php', @@ -873,6 +879,7 @@ return array( 'Symfony\\Component\\Console\\Input\\InputDefinition' => $vendorDir . '/symfony/console/Input/InputDefinition.php', 'Symfony\\Component\\Console\\Input\\InputInterface' => $vendorDir . '/symfony/console/Input/InputInterface.php', 'Symfony\\Component\\Console\\Input\\InputOption' => $vendorDir . '/symfony/console/Input/InputOption.php', + 'Symfony\\Component\\Console\\Input\\StreamableInputInterface' => $vendorDir . '/symfony/console/Input/StreamableInputInterface.php', 'Symfony\\Component\\Console\\Input\\StringInput' => $vendorDir . '/symfony/console/Input/StringInput.php', 'Symfony\\Component\\Console\\Logger\\ConsoleLogger' => $vendorDir . '/symfony/console/Logger/ConsoleLogger.php', 'Symfony\\Component\\Console\\Output\\BufferedOutput' => $vendorDir . '/symfony/console/Output/BufferedOutput.php', @@ -885,16 +892,35 @@ return array( 'Symfony\\Component\\Console\\Question\\ChoiceQuestion' => $vendorDir . '/symfony/console/Question/ChoiceQuestion.php', 'Symfony\\Component\\Console\\Question\\ConfirmationQuestion' => $vendorDir . '/symfony/console/Question/ConfirmationQuestion.php', 'Symfony\\Component\\Console\\Question\\Question' => $vendorDir . '/symfony/console/Question/Question.php', - 'Symfony\\Component\\Console\\Shell' => $vendorDir . '/symfony/console/Shell.php', 'Symfony\\Component\\Console\\Style\\OutputStyle' => $vendorDir . '/symfony/console/Style/OutputStyle.php', 'Symfony\\Component\\Console\\Style\\StyleInterface' => $vendorDir . '/symfony/console/Style/StyleInterface.php', 'Symfony\\Component\\Console\\Style\\SymfonyStyle' => $vendorDir . '/symfony/console/Style/SymfonyStyle.php', + 'Symfony\\Component\\Console\\Terminal' => $vendorDir . '/symfony/console/Terminal.php', 'Symfony\\Component\\Console\\Tester\\ApplicationTester' => $vendorDir . '/symfony/console/Tester/ApplicationTester.php', 'Symfony\\Component\\Console\\Tester\\CommandTester' => $vendorDir . '/symfony/console/Tester/CommandTester.php', + 'Symfony\\Component\\Debug\\BufferingLogger' => $vendorDir . '/symfony/debug/BufferingLogger.php', + 'Symfony\\Component\\Debug\\Debug' => $vendorDir . '/symfony/debug/Debug.php', + 'Symfony\\Component\\Debug\\DebugClassLoader' => $vendorDir . '/symfony/debug/DebugClassLoader.php', + 'Symfony\\Component\\Debug\\ErrorHandler' => $vendorDir . '/symfony/debug/ErrorHandler.php', + 'Symfony\\Component\\Debug\\ExceptionHandler' => $vendorDir . '/symfony/debug/ExceptionHandler.php', + 'Symfony\\Component\\Debug\\Exception\\ClassNotFoundException' => $vendorDir . '/symfony/debug/Exception/ClassNotFoundException.php', + 'Symfony\\Component\\Debug\\Exception\\ContextErrorException' => $vendorDir . '/symfony/debug/Exception/ContextErrorException.php', + 'Symfony\\Component\\Debug\\Exception\\FatalErrorException' => $vendorDir . '/symfony/debug/Exception/FatalErrorException.php', + 'Symfony\\Component\\Debug\\Exception\\FatalThrowableError' => $vendorDir . '/symfony/debug/Exception/FatalThrowableError.php', + 'Symfony\\Component\\Debug\\Exception\\FlattenException' => $vendorDir . '/symfony/debug/Exception/FlattenException.php', + 'Symfony\\Component\\Debug\\Exception\\OutOfMemoryException' => $vendorDir . '/symfony/debug/Exception/OutOfMemoryException.php', + 'Symfony\\Component\\Debug\\Exception\\SilencedErrorContext' => $vendorDir . '/symfony/debug/Exception/SilencedErrorContext.php', + 'Symfony\\Component\\Debug\\Exception\\UndefinedFunctionException' => $vendorDir . '/symfony/debug/Exception/UndefinedFunctionException.php', + 'Symfony\\Component\\Debug\\Exception\\UndefinedMethodException' => $vendorDir . '/symfony/debug/Exception/UndefinedMethodException.php', + 'Symfony\\Component\\Debug\\FatalErrorHandler\\ClassNotFoundFatalErrorHandler' => $vendorDir . '/symfony/debug/FatalErrorHandler/ClassNotFoundFatalErrorHandler.php', + 'Symfony\\Component\\Debug\\FatalErrorHandler\\FatalErrorHandlerInterface' => $vendorDir . '/symfony/debug/FatalErrorHandler/FatalErrorHandlerInterface.php', + 'Symfony\\Component\\Debug\\FatalErrorHandler\\UndefinedFunctionFatalErrorHandler' => $vendorDir . '/symfony/debug/FatalErrorHandler/UndefinedFunctionFatalErrorHandler.php', + 'Symfony\\Component\\Debug\\FatalErrorHandler\\UndefinedMethodFatalErrorHandler' => $vendorDir . '/symfony/debug/FatalErrorHandler/UndefinedMethodFatalErrorHandler.php', 'Symfony\\Component\\EventDispatcher\\ContainerAwareEventDispatcher' => $vendorDir . '/symfony/event-dispatcher/ContainerAwareEventDispatcher.php', 'Symfony\\Component\\EventDispatcher\\Debug\\TraceableEventDispatcher' => $vendorDir . '/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php', 'Symfony\\Component\\EventDispatcher\\Debug\\TraceableEventDispatcherInterface' => $vendorDir . '/symfony/event-dispatcher/Debug/TraceableEventDispatcherInterface.php', 'Symfony\\Component\\EventDispatcher\\Debug\\WrappedListener' => $vendorDir . '/symfony/event-dispatcher/Debug/WrappedListener.php', + 'Symfony\\Component\\EventDispatcher\\DependencyInjection\\ExtractingEventDispatcher' => $vendorDir . '/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php', 'Symfony\\Component\\EventDispatcher\\DependencyInjection\\RegisterListenersPass' => $vendorDir . '/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php', 'Symfony\\Component\\EventDispatcher\\Event' => $vendorDir . '/symfony/event-dispatcher/Event.php', 'Symfony\\Component\\EventDispatcher\\EventDispatcher' => $vendorDir . '/symfony/event-dispatcher/EventDispatcher.php', diff --git a/vendor/composer/autoload_files.php b/vendor/composer/autoload_files.php index e7fae22d..1fd5dc4c 100644 --- a/vendor/composer/autoload_files.php +++ b/vendor/composer/autoload_files.php @@ -8,8 +8,6 @@ $baseDir = dirname($vendorDir); return array( '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php', '5255c38a0faeba867671b61dfda6d864' => $vendorDir . '/paragonie/random_compat/lib/random.php', - '8cd2fca4db21bffce1ad0612f7caeec4' => $vendorDir . '/ramsey/array_column/src/array_column.php', '2c102faa651ef8ea5874edb585946bce' => $vendorDir . '/swiftmailer/swiftmailer/lib/swift_required.php', - 'f51af1d1e172536bcdb5baf6f649449d' => $baseDir . '/app/functions.php', - 'da6e17f7b0fa11d4819751ff2afd0bac' => $baseDir . '/app/Library/password.php', + '8a67f3044590529ed0a5e02f9cc9c90b' => $baseDir . '/app/functions.php', ); diff --git a/vendor/composer/autoload_psr4.php b/vendor/composer/autoload_psr4.php index 7367aa46..cf0305aa 100644 --- a/vendor/composer/autoload_psr4.php +++ b/vendor/composer/autoload_psr4.php @@ -8,6 +8,7 @@ $baseDir = dirname($vendorDir); return array( 'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'), 'Symfony\\Component\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher'), + 'Symfony\\Component\\Debug\\' => array($vendorDir . '/symfony/debug'), 'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'), 'SimpleQueue\\' => array($vendorDir . '/fguillot/simple-queue/src'), 'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'), diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index 197baa63..48245eed 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -9,10 +9,8 @@ class ComposerStaticInit6edea6294a88689e3f5c56484bb70c9b public static $files = array ( '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php', '5255c38a0faeba867671b61dfda6d864' => __DIR__ . '/..' . '/paragonie/random_compat/lib/random.php', - '8cd2fca4db21bffce1ad0612f7caeec4' => __DIR__ . '/..' . '/ramsey/array_column/src/array_column.php', '2c102faa651ef8ea5874edb585946bce' => __DIR__ . '/..' . '/swiftmailer/swiftmailer/lib/swift_required.php', - 'f51af1d1e172536bcdb5baf6f649449d' => __DIR__ . '/../..' . '/app/functions.php', - 'da6e17f7b0fa11d4819751ff2afd0bac' => __DIR__ . '/../..' . '/app/Library/password.php', + '8a67f3044590529ed0a5e02f9cc9c90b' => __DIR__ . '/../..' . '/app/functions.php', ); public static $prefixLengthsPsr4 = array ( @@ -20,6 +18,7 @@ class ComposerStaticInit6edea6294a88689e3f5c56484bb70c9b array ( 'Symfony\\Polyfill\\Mbstring\\' => 26, 'Symfony\\Component\\EventDispatcher\\' => 34, + 'Symfony\\Component\\Debug\\' => 24, 'Symfony\\Component\\Console\\' => 26, 'SimpleQueue\\' => 12, ), @@ -50,6 +49,10 @@ class ComposerStaticInit6edea6294a88689e3f5c56484bb70c9b array ( 0 => __DIR__ . '/..' . '/symfony/event-dispatcher', ), + 'Symfony\\Component\\Debug\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/debug', + ), 'Symfony\\Component\\Console\\' => array ( 0 => __DIR__ . '/..' . '/symfony/console', @@ -197,6 +200,8 @@ class ComposerStaticInit6edea6294a88689e3f5c56484bb70c9b 'Kanboard\\Action\\Base' => __DIR__ . '/../..' . '/app/Action/Base.php', 'Kanboard\\Action\\CommentCreation' => __DIR__ . '/../..' . '/app/Action/CommentCreation.php', 'Kanboard\\Action\\CommentCreationMoveTaskColumn' => __DIR__ . '/../..' . '/app/Action/CommentCreationMoveTaskColumn.php', + 'Kanboard\\Action\\StopSubtaskTimerMoveTaskColumn' => __DIR__ . '/../..' . '/app/Action/StopSubtaskTimerMoveTaskColumn.php', + 'Kanboard\\Action\\SubtaskTimerMoveTaskColumn' => __DIR__ . '/../..' . '/app/Action/SubtaskTimerMoveTaskColumn.php', 'Kanboard\\Action\\TaskAssignCategoryColor' => __DIR__ . '/../..' . '/app/Action/TaskAssignCategoryColor.php', 'Kanboard\\Action\\TaskAssignCategoryLabel' => __DIR__ . '/../..' . '/app/Action/TaskAssignCategoryLabel.php', 'Kanboard\\Action\\TaskAssignCategoryLink' => __DIR__ . '/../..' . '/app/Action/TaskAssignCategoryLink.php', @@ -956,10 +961,15 @@ class ComposerStaticInit6edea6294a88689e3f5c56484bb70c9b 'SimpleValidator\\Validators\\Required' => __DIR__ . '/..' . '/fguillot/simple-validator/src/SimpleValidator/Validators/Required.php', 'SimpleValidator\\Validators\\Unique' => __DIR__ . '/..' . '/fguillot/simple-validator/src/SimpleValidator/Validators/Unique.php', 'Symfony\\Component\\Console\\Application' => __DIR__ . '/..' . '/symfony/console/Application.php', + 'Symfony\\Component\\Console\\CommandLoader\\CommandLoaderInterface' => __DIR__ . '/..' . '/symfony/console/CommandLoader/CommandLoaderInterface.php', + 'Symfony\\Component\\Console\\CommandLoader\\ContainerCommandLoader' => __DIR__ . '/..' . '/symfony/console/CommandLoader/ContainerCommandLoader.php', + 'Symfony\\Component\\Console\\CommandLoader\\FactoryCommandLoader' => __DIR__ . '/..' . '/symfony/console/CommandLoader/FactoryCommandLoader.php', 'Symfony\\Component\\Console\\Command\\Command' => __DIR__ . '/..' . '/symfony/console/Command/Command.php', 'Symfony\\Component\\Console\\Command\\HelpCommand' => __DIR__ . '/..' . '/symfony/console/Command/HelpCommand.php', 'Symfony\\Component\\Console\\Command\\ListCommand' => __DIR__ . '/..' . '/symfony/console/Command/ListCommand.php', + 'Symfony\\Component\\Console\\Command\\LockableTrait' => __DIR__ . '/..' . '/symfony/console/Command/LockableTrait.php', 'Symfony\\Component\\Console\\ConsoleEvents' => __DIR__ . '/..' . '/symfony/console/ConsoleEvents.php', + 'Symfony\\Component\\Console\\DependencyInjection\\AddConsoleCommandPass' => __DIR__ . '/..' . '/symfony/console/DependencyInjection/AddConsoleCommandPass.php', 'Symfony\\Component\\Console\\Descriptor\\ApplicationDescription' => __DIR__ . '/..' . '/symfony/console/Descriptor/ApplicationDescription.php', 'Symfony\\Component\\Console\\Descriptor\\Descriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/Descriptor.php', 'Symfony\\Component\\Console\\Descriptor\\DescriptorInterface' => __DIR__ . '/..' . '/symfony/console/Descriptor/DescriptorInterface.php', @@ -967,7 +977,9 @@ class ComposerStaticInit6edea6294a88689e3f5c56484bb70c9b 'Symfony\\Component\\Console\\Descriptor\\MarkdownDescriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/MarkdownDescriptor.php', 'Symfony\\Component\\Console\\Descriptor\\TextDescriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/TextDescriptor.php', 'Symfony\\Component\\Console\\Descriptor\\XmlDescriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/XmlDescriptor.php', + 'Symfony\\Component\\Console\\EventListener\\ErrorListener' => __DIR__ . '/..' . '/symfony/console/EventListener/ErrorListener.php', 'Symfony\\Component\\Console\\Event\\ConsoleCommandEvent' => __DIR__ . '/..' . '/symfony/console/Event/ConsoleCommandEvent.php', + 'Symfony\\Component\\Console\\Event\\ConsoleErrorEvent' => __DIR__ . '/..' . '/symfony/console/Event/ConsoleErrorEvent.php', 'Symfony\\Component\\Console\\Event\\ConsoleEvent' => __DIR__ . '/..' . '/symfony/console/Event/ConsoleEvent.php', 'Symfony\\Component\\Console\\Event\\ConsoleExceptionEvent' => __DIR__ . '/..' . '/symfony/console/Event/ConsoleExceptionEvent.php', 'Symfony\\Component\\Console\\Event\\ConsoleTerminateEvent' => __DIR__ . '/..' . '/symfony/console/Event/ConsoleTerminateEvent.php', @@ -984,7 +996,6 @@ class ComposerStaticInit6edea6294a88689e3f5c56484bb70c9b 'Symfony\\Component\\Console\\Formatter\\OutputFormatterStyleStack' => __DIR__ . '/..' . '/symfony/console/Formatter/OutputFormatterStyleStack.php', 'Symfony\\Component\\Console\\Helper\\DebugFormatterHelper' => __DIR__ . '/..' . '/symfony/console/Helper/DebugFormatterHelper.php', 'Symfony\\Component\\Console\\Helper\\DescriptorHelper' => __DIR__ . '/..' . '/symfony/console/Helper/DescriptorHelper.php', - 'Symfony\\Component\\Console\\Helper\\DialogHelper' => __DIR__ . '/..' . '/symfony/console/Helper/DialogHelper.php', 'Symfony\\Component\\Console\\Helper\\FormatterHelper' => __DIR__ . '/..' . '/symfony/console/Helper/FormatterHelper.php', 'Symfony\\Component\\Console\\Helper\\Helper' => __DIR__ . '/..' . '/symfony/console/Helper/Helper.php', 'Symfony\\Component\\Console\\Helper\\HelperInterface' => __DIR__ . '/..' . '/symfony/console/Helper/HelperInterface.php', @@ -992,13 +1003,11 @@ class ComposerStaticInit6edea6294a88689e3f5c56484bb70c9b 'Symfony\\Component\\Console\\Helper\\InputAwareHelper' => __DIR__ . '/..' . '/symfony/console/Helper/InputAwareHelper.php', 'Symfony\\Component\\Console\\Helper\\ProcessHelper' => __DIR__ . '/..' . '/symfony/console/Helper/ProcessHelper.php', 'Symfony\\Component\\Console\\Helper\\ProgressBar' => __DIR__ . '/..' . '/symfony/console/Helper/ProgressBar.php', - 'Symfony\\Component\\Console\\Helper\\ProgressHelper' => __DIR__ . '/..' . '/symfony/console/Helper/ProgressHelper.php', 'Symfony\\Component\\Console\\Helper\\ProgressIndicator' => __DIR__ . '/..' . '/symfony/console/Helper/ProgressIndicator.php', 'Symfony\\Component\\Console\\Helper\\QuestionHelper' => __DIR__ . '/..' . '/symfony/console/Helper/QuestionHelper.php', 'Symfony\\Component\\Console\\Helper\\SymfonyQuestionHelper' => __DIR__ . '/..' . '/symfony/console/Helper/SymfonyQuestionHelper.php', 'Symfony\\Component\\Console\\Helper\\Table' => __DIR__ . '/..' . '/symfony/console/Helper/Table.php', 'Symfony\\Component\\Console\\Helper\\TableCell' => __DIR__ . '/..' . '/symfony/console/Helper/TableCell.php', - 'Symfony\\Component\\Console\\Helper\\TableHelper' => __DIR__ . '/..' . '/symfony/console/Helper/TableHelper.php', 'Symfony\\Component\\Console\\Helper\\TableSeparator' => __DIR__ . '/..' . '/symfony/console/Helper/TableSeparator.php', 'Symfony\\Component\\Console\\Helper\\TableStyle' => __DIR__ . '/..' . '/symfony/console/Helper/TableStyle.php', 'Symfony\\Component\\Console\\Input\\ArgvInput' => __DIR__ . '/..' . '/symfony/console/Input/ArgvInput.php', @@ -1009,6 +1018,7 @@ class ComposerStaticInit6edea6294a88689e3f5c56484bb70c9b 'Symfony\\Component\\Console\\Input\\InputDefinition' => __DIR__ . '/..' . '/symfony/console/Input/InputDefinition.php', 'Symfony\\Component\\Console\\Input\\InputInterface' => __DIR__ . '/..' . '/symfony/console/Input/InputInterface.php', 'Symfony\\Component\\Console\\Input\\InputOption' => __DIR__ . '/..' . '/symfony/console/Input/InputOption.php', + 'Symfony\\Component\\Console\\Input\\StreamableInputInterface' => __DIR__ . '/..' . '/symfony/console/Input/StreamableInputInterface.php', 'Symfony\\Component\\Console\\Input\\StringInput' => __DIR__ . '/..' . '/symfony/console/Input/StringInput.php', 'Symfony\\Component\\Console\\Logger\\ConsoleLogger' => __DIR__ . '/..' . '/symfony/console/Logger/ConsoleLogger.php', 'Symfony\\Component\\Console\\Output\\BufferedOutput' => __DIR__ . '/..' . '/symfony/console/Output/BufferedOutput.php', @@ -1021,16 +1031,35 @@ class ComposerStaticInit6edea6294a88689e3f5c56484bb70c9b 'Symfony\\Component\\Console\\Question\\ChoiceQuestion' => __DIR__ . '/..' . '/symfony/console/Question/ChoiceQuestion.php', 'Symfony\\Component\\Console\\Question\\ConfirmationQuestion' => __DIR__ . '/..' . '/symfony/console/Question/ConfirmationQuestion.php', 'Symfony\\Component\\Console\\Question\\Question' => __DIR__ . '/..' . '/symfony/console/Question/Question.php', - 'Symfony\\Component\\Console\\Shell' => __DIR__ . '/..' . '/symfony/console/Shell.php', 'Symfony\\Component\\Console\\Style\\OutputStyle' => __DIR__ . '/..' . '/symfony/console/Style/OutputStyle.php', 'Symfony\\Component\\Console\\Style\\StyleInterface' => __DIR__ . '/..' . '/symfony/console/Style/StyleInterface.php', 'Symfony\\Component\\Console\\Style\\SymfonyStyle' => __DIR__ . '/..' . '/symfony/console/Style/SymfonyStyle.php', + 'Symfony\\Component\\Console\\Terminal' => __DIR__ . '/..' . '/symfony/console/Terminal.php', 'Symfony\\Component\\Console\\Tester\\ApplicationTester' => __DIR__ . '/..' . '/symfony/console/Tester/ApplicationTester.php', 'Symfony\\Component\\Console\\Tester\\CommandTester' => __DIR__ . '/..' . '/symfony/console/Tester/CommandTester.php', + 'Symfony\\Component\\Debug\\BufferingLogger' => __DIR__ . '/..' . '/symfony/debug/BufferingLogger.php', + 'Symfony\\Component\\Debug\\Debug' => __DIR__ . '/..' . '/symfony/debug/Debug.php', + 'Symfony\\Component\\Debug\\DebugClassLoader' => __DIR__ . '/..' . '/symfony/debug/DebugClassLoader.php', + 'Symfony\\Component\\Debug\\ErrorHandler' => __DIR__ . '/..' . '/symfony/debug/ErrorHandler.php', + 'Symfony\\Component\\Debug\\ExceptionHandler' => __DIR__ . '/..' . '/symfony/debug/ExceptionHandler.php', + 'Symfony\\Component\\Debug\\Exception\\ClassNotFoundException' => __DIR__ . '/..' . '/symfony/debug/Exception/ClassNotFoundException.php', + 'Symfony\\Component\\Debug\\Exception\\ContextErrorException' => __DIR__ . '/..' . '/symfony/debug/Exception/ContextErrorException.php', + 'Symfony\\Component\\Debug\\Exception\\FatalErrorException' => __DIR__ . '/..' . '/symfony/debug/Exception/FatalErrorException.php', + 'Symfony\\Component\\Debug\\Exception\\FatalThrowableError' => __DIR__ . '/..' . '/symfony/debug/Exception/FatalThrowableError.php', + 'Symfony\\Component\\Debug\\Exception\\FlattenException' => __DIR__ . '/..' . '/symfony/debug/Exception/FlattenException.php', + 'Symfony\\Component\\Debug\\Exception\\OutOfMemoryException' => __DIR__ . '/..' . '/symfony/debug/Exception/OutOfMemoryException.php', + 'Symfony\\Component\\Debug\\Exception\\SilencedErrorContext' => __DIR__ . '/..' . '/symfony/debug/Exception/SilencedErrorContext.php', + 'Symfony\\Component\\Debug\\Exception\\UndefinedFunctionException' => __DIR__ . '/..' . '/symfony/debug/Exception/UndefinedFunctionException.php', + 'Symfony\\Component\\Debug\\Exception\\UndefinedMethodException' => __DIR__ . '/..' . '/symfony/debug/Exception/UndefinedMethodException.php', + 'Symfony\\Component\\Debug\\FatalErrorHandler\\ClassNotFoundFatalErrorHandler' => __DIR__ . '/..' . '/symfony/debug/FatalErrorHandler/ClassNotFoundFatalErrorHandler.php', + 'Symfony\\Component\\Debug\\FatalErrorHandler\\FatalErrorHandlerInterface' => __DIR__ . '/..' . '/symfony/debug/FatalErrorHandler/FatalErrorHandlerInterface.php', + 'Symfony\\Component\\Debug\\FatalErrorHandler\\UndefinedFunctionFatalErrorHandler' => __DIR__ . '/..' . '/symfony/debug/FatalErrorHandler/UndefinedFunctionFatalErrorHandler.php', + 'Symfony\\Component\\Debug\\FatalErrorHandler\\UndefinedMethodFatalErrorHandler' => __DIR__ . '/..' . '/symfony/debug/FatalErrorHandler/UndefinedMethodFatalErrorHandler.php', 'Symfony\\Component\\EventDispatcher\\ContainerAwareEventDispatcher' => __DIR__ . '/..' . '/symfony/event-dispatcher/ContainerAwareEventDispatcher.php', 'Symfony\\Component\\EventDispatcher\\Debug\\TraceableEventDispatcher' => __DIR__ . '/..' . '/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php', 'Symfony\\Component\\EventDispatcher\\Debug\\TraceableEventDispatcherInterface' => __DIR__ . '/..' . '/symfony/event-dispatcher/Debug/TraceableEventDispatcherInterface.php', 'Symfony\\Component\\EventDispatcher\\Debug\\WrappedListener' => __DIR__ . '/..' . '/symfony/event-dispatcher/Debug/WrappedListener.php', + 'Symfony\\Component\\EventDispatcher\\DependencyInjection\\ExtractingEventDispatcher' => __DIR__ . '/..' . '/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php', 'Symfony\\Component\\EventDispatcher\\DependencyInjection\\RegisterListenersPass' => __DIR__ . '/..' . '/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php', 'Symfony\\Component\\EventDispatcher\\Event' => __DIR__ . '/..' . '/symfony/event-dispatcher/Event.php', 'Symfony\\Component\\EventDispatcher\\EventDispatcher' => __DIR__ . '/..' . '/symfony/event-dispatcher/EventDispatcher.php', diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 12b9857f..bbf6fc50 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -761,53 +761,6 @@ ] }, { - "name": "ramsey/array_column", - "version": "1.1.3", - "version_normalized": "1.1.3.0", - "source": { - "type": "git", - "url": "https://github.com/ramsey/array_column.git", - "reference": "f8e52eb28e67eb50e613b451dd916abcf783c1db" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/ramsey/array_column/zipball/f8e52eb28e67eb50e613b451dd916abcf783c1db", - "reference": "f8e52eb28e67eb50e613b451dd916abcf783c1db", - "shasum": "" - }, - "require-dev": { - "jakub-onderka/php-parallel-lint": "0.8.*", - "phpunit/phpunit": "~4.5", - "satooshi/php-coveralls": "0.6.*", - "squizlabs/php_codesniffer": "~2.2" - }, - "time": "2015-03-20T22:07:39+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "files": [ - "src/array_column.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ben Ramsey", - "homepage": "http://benramsey.com" - } - ], - "description": "Provides functionality for array_column() to projects using PHP earlier than version 5.5.", - "homepage": "https://github.com/ramsey/array_column", - "keywords": [ - "array", - "array_column", - "column" - ] - }, - { "name": "swiftmailer/swiftmailer", "version": "v5.4.5", "version_normalized": "5.4.5.0", @@ -865,17 +818,17 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "v1.4.0", - "version_normalized": "1.4.0.0", + "version": "v1.6.0", + "version_normalized": "1.6.0.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "f29dca382a6485c3cbe6379f0c61230167681937" + "reference": "2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/f29dca382a6485c3cbe6379f0c61230167681937", - "reference": "f29dca382a6485c3cbe6379f0c61230167681937", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296", + "reference": "2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296", "shasum": "" }, "require": { @@ -884,11 +837,11 @@ "suggest": { "ext-mbstring": "For best performance" }, - "time": "2017-06-09T14:24:12+00:00", + "time": "2017-10-11T12:05:26+00:00", "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "1.6-dev" } }, "installation-source": "dist", @@ -926,38 +879,47 @@ }, { "name": "symfony/console", - "version": "v2.8.7", - "version_normalized": "2.8.7.0", + "version": "v3.4.2", + "version_normalized": "3.4.2.0", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "5ac8bc9aa77bb2edf06af3a1bb6bc1020d23acd3" + "reference": "9f21adfb92a9315b73ae2ed43138988ee4913d4e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/5ac8bc9aa77bb2edf06af3a1bb6bc1020d23acd3", - "reference": "5ac8bc9aa77bb2edf06af3a1bb6bc1020d23acd3", + "url": "https://api.github.com/repos/symfony/console/zipball/9f21adfb92a9315b73ae2ed43138988ee4913d4e", + "reference": "9f21adfb92a9315b73ae2ed43138988ee4913d4e", "shasum": "" }, "require": { - "php": ">=5.3.9", + "php": "^5.5.9|>=7.0.8", + "symfony/debug": "~2.8|~3.0|~4.0", "symfony/polyfill-mbstring": "~1.0" }, + "conflict": { + "symfony/dependency-injection": "<3.4", + "symfony/process": "<3.3" + }, "require-dev": { "psr/log": "~1.0", - "symfony/event-dispatcher": "~2.1|~3.0.0", - "symfony/process": "~2.1|~3.0.0" + "symfony/config": "~3.3|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/event-dispatcher": "~2.8|~3.0|~4.0", + "symfony/lock": "~3.4|~4.0", + "symfony/process": "~3.3|~4.0" }, "suggest": { "psr/log": "For using the console logger", "symfony/event-dispatcher": "", + "symfony/lock": "", "symfony/process": "" }, - "time": "2016-06-06T15:06:25+00:00", + "time": "2017-12-14T19:40:10+00:00", "type": "library", "extra": { "branch-alias": { - "dev-master": "2.8-dev" + "dev-master": "3.4-dev" } }, "installation-source": "dist", @@ -988,38 +950,41 @@ }, { "name": "symfony/event-dispatcher", - "version": "v2.7.14", - "version_normalized": "2.7.14.0", + "version": "v3.4.2", + "version_normalized": "3.4.2.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "d3e09ed1224503791f31b913d22196f65f9afed5" + "reference": "b869cbf8a15ca6261689de2c28a7d7f2d0706835" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/d3e09ed1224503791f31b913d22196f65f9afed5", - "reference": "d3e09ed1224503791f31b913d22196f65f9afed5", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/b869cbf8a15ca6261689de2c28a7d7f2d0706835", + "reference": "b869cbf8a15ca6261689de2c28a7d7f2d0706835", "shasum": "" }, "require": { - "php": ">=5.3.9" + "php": "^5.5.9|>=7.0.8" + }, + "conflict": { + "symfony/dependency-injection": "<3.3" }, "require-dev": { "psr/log": "~1.0", - "symfony/config": "~2.0,>=2.0.5", - "symfony/dependency-injection": "~2.6", - "symfony/expression-language": "~2.6", - "symfony/stopwatch": "~2.3" + "symfony/config": "~2.8|~3.0|~4.0", + "symfony/dependency-injection": "~3.3|~4.0", + "symfony/expression-language": "~2.8|~3.0|~4.0", + "symfony/stopwatch": "~2.8|~3.0|~4.0" }, "suggest": { "symfony/dependency-injection": "", "symfony/http-kernel": "" }, - "time": "2016-06-06T11:03:51+00:00", + "time": "2017-12-14T19:40:10+00:00", "type": "library", "extra": { "branch-alias": { - "dev-master": "2.7-dev" + "dev-master": "3.4-dev" } }, "installation-source": "dist", @@ -1047,5 +1012,63 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com" + }, + { + "name": "symfony/debug", + "version": "v3.4.2", + "version_normalized": "3.4.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/debug.git", + "reference": "543deab3ffff94402440b326fc94153bae2dfa7a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/debug/zipball/543deab3ffff94402440b326fc94153bae2dfa7a", + "reference": "543deab3ffff94402440b326fc94153bae2dfa7a", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8", + "psr/log": "~1.0" + }, + "conflict": { + "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" + }, + "require-dev": { + "symfony/http-kernel": "~2.8|~3.0|~4.0" + }, + "time": "2017-12-12T08:27:14+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\Debug\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Debug Component", + "homepage": "https://symfony.com" } ] diff --git a/vendor/ramsey/array_column/.gitignore b/vendor/ramsey/array_column/.gitignore deleted file mode 100644 index 7e8f330b..00000000 --- a/vendor/ramsey/array_column/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -.DS_Store -phpunit.xml -composer.lock -build -vendor -*.phar diff --git a/vendor/ramsey/array_column/.travis.yml b/vendor/ramsey/array_column/.travis.yml deleted file mode 100644 index ffc234e7..00000000 --- a/vendor/ramsey/array_column/.travis.yml +++ /dev/null @@ -1,26 +0,0 @@ -language: php - -php: - - 5.3 - - 5.4 - - 5.5 - - 5.6 - - 7.0 - - hhvm - -before_script: - - travis_retry composer self-update - - travis_retry composer install --no-interaction --prefer-source - -script: - - mkdir -p build/logs - - ./vendor/bin/parallel-lint src tests - - ./vendor/bin/phpunit --coverage-text - - ./vendor/bin/phpcs src --standard=psr2 -sp - -after_script: - - php vendor/bin/coveralls - -matrix: - allow_failures: - - php: hhvm diff --git a/vendor/ramsey/array_column/CHANGELOG.md b/vendor/ramsey/array_column/CHANGELOG.md deleted file mode 100644 index 1dd01361..00000000 --- a/vendor/ramsey/array_column/CHANGELOG.md +++ /dev/null @@ -1,37 +0,0 @@ -# array_column() Changelog - -## 1.1.3 - -_Released 2015-03-20_ - -* Changing package name from "rhumsaa/array_column" to "ramsey/array_column" -* Updated Travis CI build config to test more versions of PHP -* Updated Travis CI config to lint and check PSR-2 coding standards -* Added project badges -* Added CHANGELOG - -## 1.1.2 - -_Released 2013-07-22_ - -* Remove unnecessary conditionals -* Whitespace changes - -## 1.1.1 - -_Released 2013-07-06_ - -* Documentation updates - -## 1.1.0 - -_Released 2013-07-06_ - -* Catching up array_column() library functionality and tests with PHP 5.5.0 -* Set Travis CI to run tests on PHP 5.5 - -## 1.0.0 - -_Released 2013-03-22_ - -* Initial release of userland library diff --git a/vendor/ramsey/array_column/README.md b/vendor/ramsey/array_column/README.md deleted file mode 100644 index 24b5b73f..00000000 --- a/vendor/ramsey/array_column/README.md +++ /dev/null @@ -1,91 +0,0 @@ -# array_column() for PHP - -[![Build Status](https://travis-ci.org/ramsey/array_column.svg?branch=master)](https://travis-ci.org/ramsey/array_column) -[![Coverage Status](https://coveralls.io/repos/ramsey/array_column/badge.svg?branch=master)](https://coveralls.io/r/ramsey/array_column) -[![Latest Stable Version](https://poser.pugx.org/ramsey/array_column/v/stable.svg)](https://packagist.org/packages/ramsey/array_column) -[![Total Downloads](https://poser.pugx.org/ramsey/array_column/downloads.svg)](https://packagist.org/packages/ramsey/array_column) -[![Latest Unstable Version](https://poser.pugx.org/ramsey/array_column/v/unstable.svg)](https://packagist.org/packages/ramsey/array_column) -[![License](https://poser.pugx.org/ramsey/array_column/license.svg)](https://packagist.org/packages/ramsey/array_column) - -This simple library provides functionality for [`array_column()`](http://php.net/array_column) -to versions of PHP earlier than 5.5. It mimics the functionality of the built-in -function in every way. - - -## Usage - -``` -array array_column(array $input, mixed $columnKey[, mixed $indexKey]) -``` - -Given a multi-dimensional array of data, `array_column()` returns the values -from a single column of the input array, identified by the `$columnKey`. -Optionally, you may provide an `$indexKey` to index the values in the returned -array by the values from the `$indexKey` column in the input array. - -For example, using the following array of data, we tell `array_column()` to -return an array of just the last names, indexed by their record IDs. - -``` php -<?php -$records = array( - array( - 'id' => 2135, - 'first_name' => 'John', - 'last_name' => 'Doe' - ), - array( - 'id' => 3245, - 'first_name' => 'Sally', - 'last_name' => 'Smith' - ), - array( - 'id' => 5342, - 'first_name' => 'Jane', - 'last_name' => 'Jones' - ), - array( - 'id' => 5623, - 'first_name' => 'Peter', - 'last_name' => 'Doe' - ) -); - -$lastNames = array_column($records, 'last_name', 'id'); -``` - -If we call `print_r()` on `$lastNames`, you'll see a resulting array that looks -a bit like this: - -``` text -Array -( - [2135] => Doe - [3245] => Smith - [5342] => Jones - [5623] => Doe -) -``` - - -## Installation - -The easiest way to install this library is to use [Composer](https://getcomposer.org/): - -``` -php composer.phar require ramsey/array_column -``` - -Then, when you run `composer install`, everything will fall magically into place, -and the `array_column()` function will be available to your project, as long as -you are including Composer's autoloader. - -_However, you do not need Composer to use this library._ - -This library has no dependencies and should work on older versions of PHP. -Download the code and include `src/array_column.php` in your project, and all -should work fine. - -When you are ready to run your project on PHP 5.5, everything should -continue to run well without conflicts, even if this library remains included -in your project. diff --git a/vendor/ramsey/array_column/composer.json b/vendor/ramsey/array_column/composer.json deleted file mode 100644 index 2316b225..00000000 --- a/vendor/ramsey/array_column/composer.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "name": "ramsey/array_column", - "description": "Provides functionality for array_column() to projects using PHP earlier than version 5.5.", - "type": "library", - "keywords": ["array", "column", "array_column"], - "homepage": "https://github.com/ramsey/array_column", - "license": "MIT", - "authors": [ - { - "name": "Ben Ramsey", - "homepage": "http://benramsey.com" - } - ], - "support": { - "issues": "https://github.com/ramsey/array_column/issues", - "source": "https://github.com/ramsey/array_column" - }, - "require-dev": { - "phpunit/phpunit": "~4.5", - "squizlabs/php_codesniffer": "~2.2", - "jakub-onderka/php-parallel-lint": "0.8.*", - "satooshi/php-coveralls": "0.6.*" - }, - "autoload": { - "files": ["src/array_column.php"] - } -} diff --git a/vendor/ramsey/array_column/phpunit.xml.dist b/vendor/ramsey/array_column/phpunit.xml.dist deleted file mode 100644 index 61da3c17..00000000 --- a/vendor/ramsey/array_column/phpunit.xml.dist +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<phpunit bootstrap="./tests/bootstrap.php" colors="true"> - <testsuites> - <testsuite> - <directory>./tests</directory> - </testsuite> - </testsuites> - <filter> - <whitelist> - <directory suffix=".php">./src</directory> - </whitelist> - </filter> - <logging> - <log type="coverage-html" target="build/coverage" title="array_column()" - charset="UTF-8" yui="true" highlight="true" - lowUpperBound="35" highLowerBound="70"/> - <log type="coverage-clover" target="build/logs/clover.xml"/> - <log type="junit" target="build/logs/junit.xml" - logIncompleteSkipped="false"/> - </logging> -</phpunit> diff --git a/vendor/ramsey/array_column/src/array_column.php b/vendor/ramsey/array_column/src/array_column.php deleted file mode 100644 index 1e7fa99f..00000000 --- a/vendor/ramsey/array_column/src/array_column.php +++ /dev/null @@ -1,115 +0,0 @@ -<?php -/** - * This file is part of the array_column library - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - * @copyright Copyright (c) Ben Ramsey (http://benramsey.com) - * @license http://opensource.org/licenses/MIT MIT - */ - -if (!function_exists('array_column')) { - /** - * Returns the values from a single column of the input array, identified by - * the $columnKey. - * - * Optionally, you may provide an $indexKey to index the values in the returned - * array by the values from the $indexKey column in the input array. - * - * @param array $input A multi-dimensional array (record set) from which to pull - * a column of values. - * @param mixed $columnKey The column of values to return. This value may be the - * integer key of the column you wish to retrieve, or it - * may be the string key name for an associative array. - * @param mixed $indexKey (Optional.) The column to use as the index/keys for - * the returned array. This value may be the integer key - * of the column, or it may be the string key name. - * @return array - */ - function array_column($input = null, $columnKey = null, $indexKey = null) - { - // Using func_get_args() in order to check for proper number of - // parameters and trigger errors exactly as the built-in array_column() - // does in PHP 5.5. - $argc = func_num_args(); - $params = func_get_args(); - - if ($argc < 2) { - trigger_error("array_column() expects at least 2 parameters, {$argc} given", E_USER_WARNING); - return null; - } - - if (!is_array($params[0])) { - trigger_error( - 'array_column() expects parameter 1 to be array, ' . gettype($params[0]) . ' given', - E_USER_WARNING - ); - return null; - } - - if (!is_int($params[1]) - && !is_float($params[1]) - && !is_string($params[1]) - && $params[1] !== null - && !(is_object($params[1]) && method_exists($params[1], '__toString')) - ) { - trigger_error('array_column(): The column key should be either a string or an integer', E_USER_WARNING); - return false; - } - - if (isset($params[2]) - && !is_int($params[2]) - && !is_float($params[2]) - && !is_string($params[2]) - && !(is_object($params[2]) && method_exists($params[2], '__toString')) - ) { - trigger_error('array_column(): The index key should be either a string or an integer', E_USER_WARNING); - return false; - } - - $paramsInput = $params[0]; - $paramsColumnKey = ($params[1] !== null) ? (string) $params[1] : null; - - $paramsIndexKey = null; - if (isset($params[2])) { - if (is_float($params[2]) || is_int($params[2])) { - $paramsIndexKey = (int) $params[2]; - } else { - $paramsIndexKey = (string) $params[2]; - } - } - - $resultArray = array(); - - foreach ($paramsInput as $row) { - $key = $value = null; - $keySet = $valueSet = false; - - if ($paramsIndexKey !== null && array_key_exists($paramsIndexKey, $row)) { - $keySet = true; - $key = (string) $row[$paramsIndexKey]; - } - - if ($paramsColumnKey === null) { - $valueSet = true; - $value = $row; - } elseif (is_array($row) && array_key_exists($paramsColumnKey, $row)) { - $valueSet = true; - $value = $row[$paramsColumnKey]; - } - - if ($valueSet) { - if ($keySet) { - $resultArray[$key] = $value; - } else { - $resultArray[] = $value; - } - } - - } - - return $resultArray; - } - -} diff --git a/vendor/ramsey/array_column/tests/ArrayColumnTest.php b/vendor/ramsey/array_column/tests/ArrayColumnTest.php deleted file mode 100644 index 597b1dea..00000000 --- a/vendor/ramsey/array_column/tests/ArrayColumnTest.php +++ /dev/null @@ -1,422 +0,0 @@ -<?php -class ArrayColumnTest extends \PHPUnit_Framework_TestCase -{ - protected $recordSet; - protected $multiDataTypes; - protected $numericColumns; - protected $mismatchedColumns; - - protected function setUp() - { - $this->recordSet = array( - array( - 'id' => 1, - 'first_name' => 'John', - 'last_name' => 'Doe' - ), - array( - 'id' => 2, - 'first_name' => 'Sally', - 'last_name' => 'Smith' - ), - array( - 'id' => 3, - 'first_name' => 'Jane', - 'last_name' => 'Jones' - ), - ); - - $fh = fopen(__FILE__, 'r', true); - - $this->multiDataTypes = array( - array( - 'id' => 1, - 'value' => new stdClass - ), - array( - 'id' => 2, - 'value' => 34.2345 - ), - array( - 'id' => 3, - 'value' => true - ), - array( - 'id' => 4, - 'value' => false - ), - array( - 'id' => 5, - 'value' => null - ), - array( - 'id' => 6, - 'value' => 1234 - ), - array( - 'id' => 7, - 'value' => 'Foo' - ), - array( - 'id' => 8, - 'value' => $fh - ), - ); - - $this->numericColumns = array( - array('aaa', '111'), - array('bbb', '222'), - array('ccc', '333', -1 => 'ddd'), - ); - - $this->mismatchedColumns = array( - array('a' => 'foo', 'b' => 'bar', 'e' => 'bbb'), - array('a' => 'baz', 'c' => 'qux', 'd' => 'aaa'), - array('a' => 'eee', 'b' => 'fff', 'e' => 'ggg'), - ); - } - - public function testFirstNameColumnFromRecordset() - { - $expected = array('John', 'Sally', 'Jane'); - $this->assertEquals($expected, array_column($this->recordSet, 'first_name')); - } - - public function testIdColumnFromRecordset() - { - $expected = array(1, 2, 3); - $this->assertEquals($expected, array_column($this->recordSet, 'id')); - } - - public function testLastNameColumnKeyedByIdColumnFromRecordset() - { - $expected = array(1 => 'Doe', 2 => 'Smith', 3 => 'Jones'); - $this->assertEquals($expected, array_column($this->recordSet, 'last_name', 'id')); - } - - public function testLastNameColumnKeyedByFirstNameColumnFromRecordset() - { - $expected = array('John' => 'Doe', 'Sally' => 'Smith', 'Jane' => 'Jones'); - $this->assertEquals($expected, array_column($this->recordSet, 'last_name', 'first_name')); - } - - public function testValueColumnWithMultipleDataTypes() - { - $expected = array(); - foreach ($this->multiDataTypes as $row) { - $expected[] = $row['value']; - } - $this->assertEquals($expected, array_column($this->multiDataTypes, 'value')); - } - - public function testValueColumnKeyedByIdWithMultipleDataTypes() - { - $expected = array(); - foreach ($this->multiDataTypes as $row) { - $expected[$row['id']] = $row['value']; - } - $this->assertEquals($expected, array_column($this->multiDataTypes, 'value', 'id')); - } - - public function testNumericColumnKeys1() - { - $expected = array('111', '222', '333'); - $this->assertEquals($expected, array_column($this->numericColumns, 1)); - } - - public function testNumericColumnKeys2() - { - $expected = array('aaa' => '111', 'bbb' => '222', 'ccc' => '333'); - $this->assertEquals($expected, array_column($this->numericColumns, 1, 0)); - } - - public function testNumericColumnKeys3() - { - $expected = array('aaa' => '111', 'bbb' => '222', 'ccc' => '333'); - $this->assertEquals($expected, array_column($this->numericColumns, 1, 0.123)); - } - - public function testNumericColumnKeys4() - { - $expected = array(0 => '111', 1 => '222', 'ddd' => '333'); - $this->assertEquals($expected, array_column($this->numericColumns, 1, -1)); - } - - public function testFailureToFindColumn1() - { - $this->assertEquals(array(), array_column($this->numericColumns, 2)); - } - - public function testFailureToFindColumn2() - { - $this->assertEquals(array(), array_column($this->numericColumns, 'foo')); - } - - public function testFailureToFindColumn3() - { - $expected = array('aaa', 'bbb', 'ccc'); - $this->assertEquals($expected, array_column($this->numericColumns, 0, 'foo')); - } - - public function testFailureToFindColumn4() - { - $this->assertEquals(array(), array_column($this->numericColumns, 3.14)); - } - - public function testSingleDimensionalArray() - { - $singleDimension = array('foo', 'bar', 'baz'); - $this->assertEquals(array(), array_column($singleDimension, 1)); - } - - public function testMismatchedColumns1() - { - $expected = array('qux'); - $this->assertEquals($expected, array_column($this->mismatchedColumns, 'c')); - } - - public function testMismatchedColumns2() - { - $expected = array('baz' => 'qux'); - $this->assertEquals($expected, array_column($this->mismatchedColumns, 'c', 'a')); - } - - public function testMismatchedColumns3() - { - $expected = array('foo', 'aaa' => 'baz', 'eee'); - $this->assertEquals($expected, array_column($this->mismatchedColumns, 'a', 'd')); - } - - public function testMismatchedColumns4() - { - $expected = array('bbb' => 'foo', 'baz', 'ggg' => 'eee'); - $this->assertEquals($expected, array_column($this->mismatchedColumns, 'a', 'e')); - } - - public function testMismatchedColumns5() - { - $expected = array('bar', 'fff'); - $this->assertEquals($expected, array_column($this->mismatchedColumns, 'b')); - } - - public function testMismatchedColumns6() - { - $expected = array('foo' => 'bar', 'eee' => 'fff'); - $this->assertEquals($expected, array_column($this->mismatchedColumns, 'b', 'a')); - } - - public function testObjectConvertedToString() - { - $f = new Foo(); - $b = new Bar(); - $this->assertEquals(array('Doe', 'Smith', 'Jones'), array_column($this->recordSet, $f)); - $this->assertEquals(array('John' => 'Doe', 'Sally' => 'Smith', 'Jane' => 'Jones'), array_column($this->recordSet, $f, $b)); - } - - /** - * @expectedException PHPUnit_Framework_Error_Warning - * @expectedExceptionMessage array_column() expects at least 2 parameters, 0 given - */ - public function testFunctionWithZeroArgs() - { - $foo = array_column(); - } - - public function testFunctionWithZeroArgsReturnValue() - { - $foo = @array_column(); - $this->assertNull($foo); - } - - /** - * @expectedException PHPUnit_Framework_Error_Warning - * @expectedExceptionMessage array_column() expects at least 2 parameters, 1 given - */ - public function testFunctionWithOneArg() - { - $foo = array_column(array()); - } - - public function testFunctionWithOneArgReturnValue() - { - $foo = @array_column(array()); - $this->assertNull($foo); - } - - /** - * @expectedException PHPUnit_Framework_Error_Warning - * @expectedExceptionMessage array_column() expects parameter 1 to be array, string given - */ - public function testFunctionWithStringAsFirstArg() - { - $foo = array_column('foo', 0); - } - - public function testFunctionWithStringAsFirstArgReturnValue() - { - $foo = @array_column('foo', 0); - $this->assertNull($foo); - } - - /** - * @expectedException PHPUnit_Framework_Error_Warning - * @expectedExceptionMessage array_column() expects parameter 1 to be array, integer given - */ - public function testFunctionWithIntAsFirstArg() - { - $foo = array_column(1, 'foo'); - } - - public function testFunctionWithIntAsFirstArgReturnValue() - { - $foo = @array_column(1, 'foo'); - $this->assertNull($foo); - } - - /** - * @expectedException PHPUnit_Framework_Error_Warning - * @expectedExceptionMessage array_column(): The column key should be either a string or an integer - */ - public function testFunctionWithColumnKeyAsBool() - { - $foo = array_column(array(), true); - } - - public function testFunctionWithColumnKeyAsBoolReturnValue() - { - $foo = @array_column(array(), true); - $this->assertFalse($foo); - } - - /** - * @expectedException PHPUnit_Framework_Error_Warning - * @expectedExceptionMessage array_column(): The column key should be either a string or an integer - */ - public function testFunctionWithColumnKeyAsArray() - { - $foo = array_column(array(), array()); - } - - public function testFunctionWithColumnKeyAsArrayReturnValue() - { - $foo = @array_column(array(), array()); - $this->assertFalse($foo); - } - - /** - * @expectedException PHPUnit_Framework_Error_Warning - * @expectedExceptionMessage array_column(): The index key should be either a string or an integer - */ - public function testFunctionWithIndexKeyAsBool() - { - $foo = array_column(array(), 'foo', true); - } - - public function testFunctionWithIndexKeyAsBoolReturnValue() - { - $foo = @array_column(array(), 'foo', true); - $this->assertFalse($foo); - } - - /** - * @expectedException PHPUnit_Framework_Error_Warning - * @expectedExceptionMessage array_column(): The index key should be either a string or an integer - */ - public function testFunctionWithIndexKeyAsArray() - { - $foo = array_column(array(), 'foo', array()); - } - - public function testFunctionWithIndexKeyAsArrayReturnValue() - { - $foo = @array_column(array(), 'foo', array()); - $this->assertFalse($foo); - } - - /** - * @link https://bugs.php.net/bug.php?id=64493 - */ - public function testBugRequest64493() - { - // Array from Bug Request #64493 test script - $rows = array( - 456 => array('id' => '3', 'title' => 'Foo', 'date' => '2013-03-25'), - 457 => array('id' => '5', 'title' => 'Bar', 'date' => '2012-05-20'), - ); - - // pass null as second parameter to get back all columns indexed by third parameter - $expected1 = array( - 3 => array('id' => '3', 'title' => 'Foo', 'date' => '2013-03-25'), - 5 => array('id' => '5', 'title' => 'Bar', 'date' => '2012-05-20'), - ); - $this->assertEquals($expected1, array_column($rows, null, 'id')); - - // pass null as second parameter and bogus third param to get back zero-indexed array of all columns - $expected2 = array( - array('id' => '3', 'title' => 'Foo', 'date' => '2013-03-25'), - array('id' => '5', 'title' => 'Bar', 'date' => '2012-05-20'), - ); - $this->assertEquals($expected2, array_column($rows, null, 'foo')); - - // pass null as second parameter and no third param to get back array_values(input) (same as $expected2) - $this->assertEquals($expected2, array_column($rows, null)); - } - - public function testObjectCast() - { - $columnKey = new ColumnKeyClass(); - $indexKey = new IndexKeyClass(); - $value = new ValueClass(); - - $records = array( - array( - 'id' => $value, - 'first_name' => 'John', - 'last_name' => 'XXX' - ), - array( - 'id' => 3245, - 'first_name' => 'Sally', - 'last_name' => 'Smith' - ), - ); - - $expected = array( - 2135 => 'John', - 3245 => 'Sally', - ); - - $this->assertEquals($expected, array_column($records, $columnKey, $indexKey)); - } -} - -class Foo -{ - public function __toString() - { - return 'last_name'; - } -} - -class Bar -{ - public function __toString() - { - return 'first_name'; - } -} - -class ColumnKeyClass -{ - function __toString() { return 'first_name'; } -} - -class IndexKeyClass -{ - function __toString() { return 'id'; } -} - -class ValueClass -{ - function __toString() { return '2135'; } -} diff --git a/vendor/ramsey/array_column/tests/bootstrap.php b/vendor/ramsey/array_column/tests/bootstrap.php deleted file mode 100644 index 97eabbac..00000000 --- a/vendor/ramsey/array_column/tests/bootstrap.php +++ /dev/null @@ -1,5 +0,0 @@ -<?php - -error_reporting(E_ALL | E_STRICT); - -require_once 'src/array_column.php'; diff --git a/vendor/symfony/console/Application.php b/vendor/symfony/console/Application.php index 603559f0..f3bc0d59 100644 --- a/vendor/symfony/console/Application.php +++ b/vendor/symfony/console/Application.php @@ -11,20 +11,21 @@ namespace Symfony\Component\Console; -use Symfony\Component\Console\Descriptor\TextDescriptor; -use Symfony\Component\Console\Descriptor\XmlDescriptor; +use Symfony\Component\Console\CommandLoader\CommandLoaderInterface; use Symfony\Component\Console\Exception\ExceptionInterface; +use Symfony\Component\Console\Formatter\OutputFormatter; use Symfony\Component\Console\Helper\DebugFormatterHelper; +use Symfony\Component\Console\Helper\Helper; use Symfony\Component\Console\Helper\ProcessHelper; use Symfony\Component\Console\Helper\QuestionHelper; use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\StreamableInputInterface; use Symfony\Component\Console\Input\ArgvInput; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputAwareInterface; -use Symfony\Component\Console\Output\BufferedOutput; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\ConsoleOutput; use Symfony\Component\Console\Output\ConsoleOutputInterface; @@ -33,14 +34,14 @@ use Symfony\Component\Console\Command\HelpCommand; use Symfony\Component\Console\Command\ListCommand; use Symfony\Component\Console\Helper\HelperSet; use Symfony\Component\Console\Helper\FormatterHelper; -use Symfony\Component\Console\Helper\DialogHelper; -use Symfony\Component\Console\Helper\ProgressHelper; -use Symfony\Component\Console\Helper\TableHelper; use Symfony\Component\Console\Event\ConsoleCommandEvent; +use Symfony\Component\Console\Event\ConsoleErrorEvent; use Symfony\Component\Console\Event\ConsoleExceptionEvent; use Symfony\Component\Console\Event\ConsoleTerminateEvent; use Symfony\Component\Console\Exception\CommandNotFoundException; use Symfony\Component\Console\Exception\LogicException; +use Symfony\Component\Debug\ErrorHandler; +use Symfony\Component\Debug\Exception\FatalThrowableError; use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** @@ -65,17 +66,18 @@ class Application private $runningCommand; private $name; private $version; + private $commandLoader; private $catchExceptions = true; private $autoExit = true; private $definition; private $helperSet; private $dispatcher; - private $terminalDimensions; + private $terminal; private $defaultCommand; + private $singleCommand; + private $initialized; /** - * Constructor. - * * @param string $name The name of the application * @param string $version The version of the application */ @@ -83,13 +85,8 @@ class Application { $this->name = $name; $this->version = $version; + $this->terminal = new Terminal(); $this->defaultCommand = 'list'; - $this->helperSet = $this->getDefaultHelperSet(); - $this->definition = $this->getDefaultInputDefinition(); - - foreach ($this->getDefaultCommands() as $command) { - $this->add($command); - } } public function setDispatcher(EventDispatcherInterface $dispatcher) @@ -97,18 +94,23 @@ class Application $this->dispatcher = $dispatcher; } + public function setCommandLoader(CommandLoaderInterface $commandLoader) + { + $this->commandLoader = $commandLoader; + } + /** * Runs the current application. * - * @param InputInterface $input An Input instance - * @param OutputInterface $output An Output instance - * * @return int 0 if everything went fine, or an error code * - * @throws \Exception When doRun returns Exception + * @throws \Exception When running fails. Bypass this when {@link setCatchExceptions()}. */ public function run(InputInterface $input = null, OutputInterface $output = null) { + putenv('LINES='.$this->terminal->getHeight()); + putenv('COLUMNS='.$this->terminal->getWidth()); + if (null === $input) { $input = new ArgvInput(); } @@ -117,6 +119,29 @@ class Application $output = new ConsoleOutput(); } + $renderException = function ($e) use ($output) { + if (!$e instanceof \Exception) { + $e = class_exists(FatalThrowableError::class) ? new FatalThrowableError($e) : new \ErrorException($e->getMessage(), $e->getCode(), E_ERROR, $e->getFile(), $e->getLine()); + } + if ($output instanceof ConsoleOutputInterface) { + $this->renderException($e, $output->getErrorOutput()); + } else { + $this->renderException($e, $output); + } + }; + if ($phpHandler = set_exception_handler($renderException)) { + restore_exception_handler(); + if (!is_array($phpHandler) || !$phpHandler[0] instanceof ErrorHandler) { + $debugHandler = true; + } elseif ($debugHandler = $phpHandler[0]->setExceptionHandler($renderException)) { + $phpHandler[0]->setExceptionHandler($debugHandler); + } + } + + if (null !== $this->dispatcher && $this->dispatcher->hasListeners(ConsoleEvents::EXCEPTION)) { + @trigger_error(sprintf('The "ConsoleEvents::EXCEPTION" event is deprecated since Symfony 3.3 and will be removed in 4.0. Listen to the "ConsoleEvents::ERROR" event instead.'), E_USER_DEPRECATED); + } + $this->configureIO($input, $output); try { @@ -126,11 +151,7 @@ class Application throw $e; } - if ($output instanceof ConsoleOutputInterface) { - $this->renderException($e, $output->getErrorOutput()); - } else { - $this->renderException($e, $output); - } + $renderException($e); $exitCode = $e->getCode(); if (is_numeric($exitCode)) { @@ -141,6 +162,12 @@ class Application } else { $exitCode = 1; } + } finally { + if (!$phpHandler) { + restore_exception_handler(); + } elseif (!$debugHandler) { + $phpHandler[0]->setExceptionHandler(null); + } } if ($this->autoExit) { @@ -157,24 +184,21 @@ class Application /** * Runs the current application. * - * @param InputInterface $input An Input instance - * @param OutputInterface $output An Output instance - * * @return int 0 if everything went fine, or an error code */ public function doRun(InputInterface $input, OutputInterface $output) { - if (true === $input->hasParameterOption(array('--version', '-V'))) { + if (true === $input->hasParameterOption(array('--version', '-V'), true)) { $output->writeln($this->getLongVersion()); return 0; } $name = $this->getCommandName($input); - if (true === $input->hasParameterOption(array('--help', '-h'))) { + if (true === $input->hasParameterOption(array('--help', '-h'), true)) { if (!$name) { $name = 'help'; - $input = new ArrayInput(array('command' => 'help')); + $input = new ArrayInput(array('command_name' => $this->defaultCommand)); } else { $this->wantHelps = true; } @@ -182,11 +206,35 @@ class Application if (!$name) { $name = $this->defaultCommand; - $input = new ArrayInput(array('command' => $this->defaultCommand)); + $definition = $this->getDefinition(); + $definition->setArguments(array_merge( + $definition->getArguments(), + array( + 'command' => new InputArgument('command', InputArgument::OPTIONAL, $definition->getArgument('command')->getDescription(), $name), + ) + )); } - // the command name MUST be the first element of the input - $command = $this->find($name); + try { + $e = $this->runningCommand = null; + // the command name MUST be the first element of the input + $command = $this->find($name); + } catch (\Exception $e) { + } catch (\Throwable $e) { + } + if (null !== $e) { + if (null !== $this->dispatcher) { + $event = new ConsoleErrorEvent($input, $output, $e); + $this->dispatcher->dispatch(ConsoleEvents::ERROR, $event); + $e = $event->getError(); + + if (0 === $event->getExitCode()) { + return 0; + } + } + + throw $e; + } $this->runningCommand = $command; $exitCode = $this->doRunCommand($command, $input, $output); @@ -195,11 +243,6 @@ class Application return $exitCode; } - /** - * Set a helper set to be used with the command. - * - * @param HelperSet $helperSet The helper set - */ public function setHelperSet(HelperSet $helperSet) { $this->helperSet = $helperSet; @@ -212,14 +255,13 @@ class Application */ public function getHelperSet() { + if (!$this->helperSet) { + $this->helperSet = $this->getDefaultHelperSet(); + } + return $this->helperSet; } - /** - * Set an input definition set to be used with this application. - * - * @param InputDefinition $definition The input definition - */ public function setDefinition(InputDefinition $definition) { $this->definition = $definition; @@ -232,13 +274,24 @@ class Application */ public function getDefinition() { + if (!$this->definition) { + $this->definition = $this->getDefaultInputDefinition(); + } + + if ($this->singleCommand) { + $inputDefinition = $this->definition; + $inputDefinition->setArguments(); + + return $inputDefinition; + } + return $this->definition; } /** * Gets the help message. * - * @return string A help message. + * @return string A help message */ public function getHelp() { @@ -246,6 +299,16 @@ class Application } /** + * Gets whether to catch exceptions or not during commands execution. + * + * @return bool Whether to catch exceptions or not during commands execution + */ + public function areExceptionsCaught() + { + return $this->catchExceptions; + } + + /** * Sets whether to catch exceptions or not during commands execution. * * @param bool $boolean Whether to catch exceptions or not during commands execution @@ -256,6 +319,16 @@ class Application } /** + * Gets whether to automatically exit after a command execution or not. + * + * @return bool Whether to automatically exit after a command execution or not + */ + public function isAutoExitEnabled() + { + return $this->autoExit; + } + + /** * Sets whether to automatically exit after a command execution or not. * * @param bool $boolean Whether to automatically exit after a command execution or not @@ -314,13 +387,13 @@ class Application { if ('UNKNOWN' !== $this->getName()) { if ('UNKNOWN' !== $this->getVersion()) { - return sprintf('<info>%s</info> version <comment>%s</comment>', $this->getName(), $this->getVersion()); + return sprintf('%s <info>%s</info>', $this->getName(), $this->getVersion()); } - return sprintf('<info>%s</info>', $this->getName()); + return $this->getName(); } - return '<info>Console Tool</info>'; + return 'Console Tool'; } /** @@ -338,6 +411,8 @@ class Application /** * Adds an array of command objects. * + * If a Command is not enabled it will not be added. + * * @param Command[] $commands An array of commands */ public function addCommands(array $commands) @@ -351,13 +426,14 @@ class Application * Adds a command object. * * If a command with the same name already exists, it will be overridden. + * If the command is not enabled it will not be added. * - * @param Command $command A Command object - * - * @return Command The registered command + * @return Command|null The registered command if enabled or null */ public function add(Command $command) { + $this->init(); + $command->setApplication($this); if (!$command->isEnabled()) { @@ -370,6 +446,10 @@ class Application throw new LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', get_class($command))); } + if (!$command->getName()) { + throw new LogicException(sprintf('The command defined in "%s" cannot have an empty name.', get_class($command))); + } + $this->commands[$command->getName()] = $command; foreach ($command->getAliases() as $alias) { @@ -386,11 +466,13 @@ class Application * * @return Command A Command object * - * @throws CommandNotFoundException When command name given does not exist + * @throws CommandNotFoundException When given command name does not exist */ public function get($name) { - if (!isset($this->commands[$name])) { + $this->init(); + + if (!$this->has($name)) { throw new CommandNotFoundException(sprintf('The command "%s" does not exist.', $name)); } @@ -417,15 +499,17 @@ class Application */ public function has($name) { - return isset($this->commands[$name]); + $this->init(); + + return isset($this->commands[$name]) || ($this->commandLoader && $this->commandLoader->has($name) && $this->add($this->commandLoader->get($name))); } /** * Returns an array of all unique namespaces used by currently registered commands. * - * It does not returns the global namespace which always exists. + * It does not return the global namespace which always exists. * - * @return array An array of namespaces + * @return string[] An array of namespaces */ public function getNamespaces() { @@ -474,7 +558,7 @@ class Application $exact = in_array($namespace, $namespaces, true); if (count($namespaces) > 1 && !$exact) { - throw new CommandNotFoundException(sprintf('The namespace "%s" is ambiguous (%s).', $namespace, $this->getAbbreviationSuggestions(array_values($namespaces))), array_values($namespaces)); + throw new CommandNotFoundException(sprintf("The namespace \"%s\" is ambiguous.\nDid you mean one of these?\n%s", $namespace, $this->getAbbreviationSuggestions(array_values($namespaces))), array_values($namespaces)); } return $exact ? $namespace : reset($namespaces); @@ -494,11 +578,18 @@ class Application */ public function find($name) { - $allCommands = array_keys($this->commands); + $this->init(); + + $allCommands = $this->commandLoader ? array_merge($this->commandLoader->getNames(), array_keys($this->commands)) : array_keys($this->commands); $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $name); $commands = preg_grep('{^'.$expr.'}', $allCommands); - if (empty($commands) || count(preg_grep('{^'.$expr.'$}', $commands)) < 1) { + if (empty($commands)) { + $commands = preg_grep('{^'.$expr.'}i', $allCommands); + } + + // if no commands matched or we just matched namespaces + if (empty($commands) || count(preg_grep('{^'.$expr.'$}i', $commands)) < 1) { if (false !== $pos = strrpos($name, ':')) { // check if a namespace exists and contains commands $this->findNamespace(substr($name, 0, $pos)); @@ -520,19 +611,33 @@ class Application // filter out aliases for commands which are already on the list if (count($commands) > 1) { - $commandList = $this->commands; - $commands = array_filter($commands, function ($nameOrAlias) use ($commandList, $commands) { - $commandName = $commandList[$nameOrAlias]->getName(); + $commandList = $this->commandLoader ? array_merge(array_flip($this->commandLoader->getNames()), $this->commands) : $this->commands; + $commands = array_unique(array_filter($commands, function ($nameOrAlias) use ($commandList, $commands) { + $commandName = $commandList[$nameOrAlias] instanceof Command ? $commandList[$nameOrAlias]->getName() : $nameOrAlias; return $commandName === $nameOrAlias || !in_array($commandName, $commands); - }); + })); } $exact = in_array($name, $commands, true); if (count($commands) > 1 && !$exact) { - $suggestions = $this->getAbbreviationSuggestions(array_values($commands)); + $usableWidth = $this->terminal->getWidth() - 10; + $abbrevs = array_values($commands); + $maxLen = 0; + foreach ($abbrevs as $abbrev) { + $maxLen = max(Helper::strlen($abbrev), $maxLen); + } + $abbrevs = array_map(function ($cmd) use ($commandList, $usableWidth, $maxLen) { + if (!$commandList[$cmd] instanceof Command) { + return $cmd; + } + $abbrev = str_pad($cmd, $maxLen, ' ').' '.$commandList[$cmd]->getDescription(); + + return Helper::strlen($abbrev) > $usableWidth ? Helper::substr($abbrev, 0, $usableWidth - 3).'...' : $abbrev; + }, array_values($commands)); + $suggestions = $this->getAbbreviationSuggestions($abbrevs); - throw new CommandNotFoundException(sprintf('Command "%s" is ambiguous (%s).', $name, $suggestions), array_values($commands)); + throw new CommandNotFoundException(sprintf("Command \"%s\" is ambiguous.\nDid you mean one of these?\n%s", $name, $suggestions), array_values($commands)); } return $this->get($exact ? $name : reset($commands)); @@ -549,8 +654,21 @@ class Application */ public function all($namespace = null) { + $this->init(); + if (null === $namespace) { - return $this->commands; + if (!$this->commandLoader) { + return $this->commands; + } + + $commands = $this->commands; + foreach ($this->commandLoader->getNames() as $name) { + if (!isset($commands[$name]) && $this->has($name)) { + $commands[$name] = $this->get($name); + } + } + + return $commands; } $commands = array(); @@ -560,6 +678,14 @@ class Application } } + if ($this->commandLoader) { + foreach ($this->commandLoader->getNames() as $name) { + if (!isset($commands[$name]) && $namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1) && $this->has($name)) { + $commands[$name] = $this->get($name); + } + } + } + return $commands; } @@ -584,78 +710,41 @@ class Application } /** - * Returns a text representation of the Application. - * - * @param string $namespace An optional namespace name - * @param bool $raw Whether to return raw command list - * - * @return string A string representing the Application - * - * @deprecated since version 2.3, to be removed in 3.0. - */ - public function asText($namespace = null, $raw = false) - { - @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0.', E_USER_DEPRECATED); - - $descriptor = new TextDescriptor(); - $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, !$raw); - $descriptor->describe($output, $this, array('namespace' => $namespace, 'raw_output' => true)); - - return $output->fetch(); - } - - /** - * Returns an XML representation of the Application. - * - * @param string $namespace An optional namespace name - * @param bool $asDom Whether to return a DOM or an XML string - * - * @return string|\DOMDocument An XML string representing the Application - * - * @deprecated since version 2.3, to be removed in 3.0. + * Renders a caught exception. */ - public function asXml($namespace = null, $asDom = false) + public function renderException(\Exception $e, OutputInterface $output) { - @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0.', E_USER_DEPRECATED); + $output->writeln('', OutputInterface::VERBOSITY_QUIET); - $descriptor = new XmlDescriptor(); + $this->doRenderException($e, $output); - if ($asDom) { - return $descriptor->getApplicationDocument($this, $namespace); + if (null !== $this->runningCommand) { + $output->writeln(sprintf('<info>%s</info>', sprintf($this->runningCommand->getSynopsis(), $this->getName())), OutputInterface::VERBOSITY_QUIET); + $output->writeln('', OutputInterface::VERBOSITY_QUIET); } - - $output = new BufferedOutput(); - $descriptor->describe($output, $this, array('namespace' => $namespace)); - - return $output->fetch(); } - /** - * Renders a caught exception. - * - * @param \Exception $e An exception instance - * @param OutputInterface $output An OutputInterface instance - */ - public function renderException($e, $output) + protected function doRenderException(\Exception $e, OutputInterface $output) { - $output->writeln('', OutputInterface::VERBOSITY_QUIET); - do { - $title = sprintf(' [%s] ', get_class($e)); - - $len = $this->stringWidth($title); + $message = trim($e->getMessage()); + if ('' === $message || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { + $title = sprintf(' [%s%s] ', get_class($e), 0 !== ($code = $e->getCode()) ? ' ('.$code.')' : ''); + $len = Helper::strlen($title); + } else { + $len = 0; + } - $width = $this->getTerminalWidth() ? $this->getTerminalWidth() - 1 : PHP_INT_MAX; + $width = $this->terminal->getWidth() ? $this->terminal->getWidth() - 1 : PHP_INT_MAX; // HHVM only accepts 32 bits integer in str_split, even when PHP_INT_MAX is a 64 bit integer: https://github.com/facebook/hhvm/issues/1327 if (defined('HHVM_VERSION') && $width > 1 << 31) { $width = 1 << 31; } - $formatter = $output->getFormatter(); $lines = array(); - foreach (preg_split('/\r?\n/', $e->getMessage()) as $line) { + foreach ('' !== $message ? preg_split('/\r?\n/', $message) : array() as $line) { foreach ($this->splitStringByWidth($line, $width - 4) as $line) { // pre-format lines to get the right string length - $lineLength = $this->stringWidth(preg_replace('/\[[^m]*m/', '', $formatter->format($line))) + 4; + $lineLength = Helper::strlen($line) + 4; $lines[] = array($line, $lineLength); $len = max($lineLength, $len); @@ -663,27 +752,26 @@ class Application } $messages = array(); - $messages[] = $emptyLine = $formatter->format(sprintf('<error>%s</error>', str_repeat(' ', $len))); - $messages[] = $formatter->format(sprintf('<error>%s%s</error>', $title, str_repeat(' ', max(0, $len - $this->stringWidth($title))))); + if (!$e instanceof ExceptionInterface || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { + $messages[] = sprintf('<comment>%s</comment>', OutputFormatter::escape(sprintf('In %s line %s:', basename($e->getFile()) ?: 'n/a', $e->getLine() ?: 'n/a'))); + } + $messages[] = $emptyLine = sprintf('<error>%s</error>', str_repeat(' ', $len)); + if ('' === $message || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { + $messages[] = sprintf('<error>%s%s</error>', $title, str_repeat(' ', max(0, $len - Helper::strlen($title)))); + } foreach ($lines as $line) { - $messages[] = $formatter->format(sprintf('<error> %s %s</error>', $line[0], str_repeat(' ', $len - $line[1]))); + $messages[] = sprintf('<error> %s %s</error>', OutputFormatter::escape($line[0]), str_repeat(' ', $len - $line[1])); } $messages[] = $emptyLine; $messages[] = ''; - $output->writeln($messages, OutputInterface::OUTPUT_RAW | OutputInterface::VERBOSITY_QUIET); + $output->writeln($messages, OutputInterface::VERBOSITY_QUIET); if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { $output->writeln('<comment>Exception trace:</comment>', OutputInterface::VERBOSITY_QUIET); // exception related properties $trace = $e->getTrace(); - array_unshift($trace, array( - 'function' => '', - 'file' => $e->getFile() !== null ? $e->getFile() : 'n/a', - 'line' => $e->getLine() !== null ? $e->getLine() : 'n/a', - 'args' => array(), - )); for ($i = 0, $count = count($trace); $i < $count; ++$i) { $class = isset($trace[$i]['class']) ? $trace[$i]['class'] : ''; @@ -698,71 +786,48 @@ class Application $output->writeln('', OutputInterface::VERBOSITY_QUIET); } } while ($e = $e->getPrevious()); - - if (null !== $this->runningCommand) { - $output->writeln(sprintf('<info>%s</info>', sprintf($this->runningCommand->getSynopsis(), $this->getName())), OutputInterface::VERBOSITY_QUIET); - $output->writeln('', OutputInterface::VERBOSITY_QUIET); - } } /** * Tries to figure out the terminal width in which this application runs. * * @return int|null + * + * @deprecated since version 3.2, to be removed in 4.0. Create a Terminal instance instead. */ protected function getTerminalWidth() { - $dimensions = $this->getTerminalDimensions(); + @trigger_error(sprintf('%s is deprecated as of 3.2 and will be removed in 4.0. Create a Terminal instance instead.', __METHOD__), E_USER_DEPRECATED); - return $dimensions[0]; + return $this->terminal->getWidth(); } /** * Tries to figure out the terminal height in which this application runs. * * @return int|null + * + * @deprecated since version 3.2, to be removed in 4.0. Create a Terminal instance instead. */ protected function getTerminalHeight() { - $dimensions = $this->getTerminalDimensions(); + @trigger_error(sprintf('%s is deprecated as of 3.2 and will be removed in 4.0. Create a Terminal instance instead.', __METHOD__), E_USER_DEPRECATED); - return $dimensions[1]; + return $this->terminal->getHeight(); } /** * Tries to figure out the terminal dimensions based on the current environment. * * @return array Array containing width and height + * + * @deprecated since version 3.2, to be removed in 4.0. Create a Terminal instance instead. */ public function getTerminalDimensions() { - if ($this->terminalDimensions) { - return $this->terminalDimensions; - } - - if ('\\' === DIRECTORY_SEPARATOR) { - // extract [w, H] from "wxh (WxH)" - if (preg_match('/^(\d+)x\d+ \(\d+x(\d+)\)$/', trim(getenv('ANSICON')), $matches)) { - return array((int) $matches[1], (int) $matches[2]); - } - // extract [w, h] from "wxh" - if (preg_match('/^(\d+)x(\d+)$/', $this->getConsoleMode(), $matches)) { - return array((int) $matches[1], (int) $matches[2]); - } - } + @trigger_error(sprintf('%s is deprecated as of 3.2 and will be removed in 4.0. Create a Terminal instance instead.', __METHOD__), E_USER_DEPRECATED); - if ($sttyString = $this->getSttyColumns()) { - // extract [w, h] from "rows h; columns w;" - if (preg_match('/rows.(\d+);.columns.(\d+);/i', $sttyString, $matches)) { - return array((int) $matches[2], (int) $matches[1]); - } - // extract [w, h] from "; h rows; w columns" - if (preg_match('/;.(\d+).rows;.(\d+).columns/i', $sttyString, $matches)) { - return array((int) $matches[2], (int) $matches[1]); - } - } - - return array(null, null); + return array($this->terminal->getWidth(), $this->terminal->getHeight()); } /** @@ -773,49 +838,82 @@ class Application * @param int $width The width * @param int $height The height * - * @return Application The current application + * @return $this + * + * @deprecated since version 3.2, to be removed in 4.0. Set the COLUMNS and LINES env vars instead. */ public function setTerminalDimensions($width, $height) { - $this->terminalDimensions = array($width, $height); + @trigger_error(sprintf('%s is deprecated as of 3.2 and will be removed in 4.0. Set the COLUMNS and LINES env vars instead.', __METHOD__), E_USER_DEPRECATED); + + putenv('COLUMNS='.$width); + putenv('LINES='.$height); return $this; } /** * Configures the input and output instances based on the user arguments and options. - * - * @param InputInterface $input An InputInterface instance - * @param OutputInterface $output An OutputInterface instance */ protected function configureIO(InputInterface $input, OutputInterface $output) { - if (true === $input->hasParameterOption(array('--ansi'))) { + if (true === $input->hasParameterOption(array('--ansi'), true)) { $output->setDecorated(true); - } elseif (true === $input->hasParameterOption(array('--no-ansi'))) { + } elseif (true === $input->hasParameterOption(array('--no-ansi'), true)) { $output->setDecorated(false); } - if (true === $input->hasParameterOption(array('--no-interaction', '-n'))) { + if (true === $input->hasParameterOption(array('--no-interaction', '-n'), true)) { $input->setInteractive(false); - } elseif (function_exists('posix_isatty') && $this->getHelperSet()->has('question')) { - $inputStream = $this->getHelperSet()->get('question')->getInputStream(); + } elseif (function_exists('posix_isatty')) { + $inputStream = null; + + if ($input instanceof StreamableInputInterface) { + $inputStream = $input->getStream(); + } + + // This check ensures that calling QuestionHelper::setInputStream() works + // To be removed in 4.0 (in the same time as QuestionHelper::setInputStream) + if (!$inputStream && $this->getHelperSet()->has('question')) { + $inputStream = $this->getHelperSet()->get('question')->getInputStream(false); + } + if (!@posix_isatty($inputStream) && false === getenv('SHELL_INTERACTIVE')) { $input->setInteractive(false); } } - if (true === $input->hasParameterOption(array('--quiet', '-q'))) { + switch ($shellVerbosity = (int) getenv('SHELL_VERBOSITY')) { + case -1: $output->setVerbosity(OutputInterface::VERBOSITY_QUIET); break; + case 1: $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE); break; + case 2: $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE); break; + case 3: $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG); break; + default: $shellVerbosity = 0; break; + } + + if (true === $input->hasParameterOption(array('--quiet', '-q'), true)) { $output->setVerbosity(OutputInterface::VERBOSITY_QUIET); + $shellVerbosity = -1; } else { - if ($input->hasParameterOption('-vvv') || $input->hasParameterOption('--verbose=3') || $input->getParameterOption('--verbose') === 3) { + if ($input->hasParameterOption('-vvv', true) || $input->hasParameterOption('--verbose=3', true) || 3 === $input->getParameterOption('--verbose', false, true)) { $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG); - } elseif ($input->hasParameterOption('-vv') || $input->hasParameterOption('--verbose=2') || $input->getParameterOption('--verbose') === 2) { + $shellVerbosity = 3; + } elseif ($input->hasParameterOption('-vv', true) || $input->hasParameterOption('--verbose=2', true) || 2 === $input->getParameterOption('--verbose', false, true)) { $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE); - } elseif ($input->hasParameterOption('-v') || $input->hasParameterOption('--verbose=1') || $input->hasParameterOption('--verbose') || $input->getParameterOption('--verbose')) { + $shellVerbosity = 2; + } elseif ($input->hasParameterOption('-v', true) || $input->hasParameterOption('--verbose=1', true) || $input->hasParameterOption('--verbose', true) || $input->getParameterOption('--verbose', false, true)) { $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE); + $shellVerbosity = 1; } } + + if (-1 === $shellVerbosity) { + $input->setInteractive(false); + } + + putenv('SHELL_VERBOSITY='.$shellVerbosity); + $_ENV['SHELL_VERBOSITY'] = $shellVerbosity; + $_SERVER['SHELL_VERBOSITY'] = $shellVerbosity; } /** @@ -824,13 +922,7 @@ class Application * If an event dispatcher has been attached to the application, * events are also dispatched during the life-cycle of the command. * - * @param Command $command A Command instance - * @param InputInterface $input An Input instance - * @param OutputInterface $output An Output instance - * * @return int 0 if everything went fine, or an error code - * - * @throws \Exception when the command being run threw an exception */ protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output) { @@ -853,42 +945,56 @@ class Application } $event = new ConsoleCommandEvent($command, $input, $output); - $this->dispatcher->dispatch(ConsoleEvents::COMMAND, $event); + $e = null; + + try { + $this->dispatcher->dispatch(ConsoleEvents::COMMAND, $event); - if ($event->commandShouldRun()) { - try { + if ($event->commandShouldRun()) { $exitCode = $command->run($input, $output); - } catch (\Exception $e) { - $event = new ConsoleExceptionEvent($command, $input, $output, $e, $e->getCode()); + } else { + $exitCode = ConsoleCommandEvent::RETURN_CODE_DISABLED; + } + } catch (\Exception $e) { + } catch (\Throwable $e) { + } + if (null !== $e) { + if ($this->dispatcher->hasListeners(ConsoleEvents::EXCEPTION)) { + $x = $e instanceof \Exception ? $e : new FatalThrowableError($e); + $event = new ConsoleExceptionEvent($command, $input, $output, $x, $x->getCode()); $this->dispatcher->dispatch(ConsoleEvents::EXCEPTION, $event); - $e = $event->getException(); - - $event = new ConsoleTerminateEvent($command, $input, $output, $e->getCode()); - $this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event); + if ($x !== $event->getException()) { + $e = $event->getException(); + } + } + $event = new ConsoleErrorEvent($input, $output, $e, $command); + $this->dispatcher->dispatch(ConsoleEvents::ERROR, $event); + $e = $event->getError(); - throw $e; + if (0 === $exitCode = $event->getExitCode()) { + $e = null; } - } else { - $exitCode = ConsoleCommandEvent::RETURN_CODE_DISABLED; } $event = new ConsoleTerminateEvent($command, $input, $output, $exitCode); $this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event); + if (null !== $e) { + throw $e; + } + return $event->getExitCode(); } /** * Gets the name of the command based on input. * - * @param InputInterface $input The input interface - * * @return string The command name */ protected function getCommandName(InputInterface $input) { - return $input->getFirstArgument(); + return $this->singleCommand ? $this->defaultCommand : $input->getFirstArgument(); } /** @@ -930,9 +1036,6 @@ class Application { return new HelperSet(array( new FormatterHelper(), - new DialogHelper(false), - new ProgressHelper(false), - new TableHelper(false), new DebugFormatterHelper(), new ProcessHelper(), new QuestionHelper(), @@ -940,54 +1043,6 @@ class Application } /** - * Runs and parses stty -a if it's available, suppressing any error output. - * - * @return string - */ - private function getSttyColumns() - { - if (!function_exists('proc_open')) { - return; - } - - $descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w')); - $process = proc_open('stty -a | grep columns', $descriptorspec, $pipes, null, null, array('suppress_errors' => true)); - if (is_resource($process)) { - $info = stream_get_contents($pipes[1]); - fclose($pipes[1]); - fclose($pipes[2]); - proc_close($process); - - return $info; - } - } - - /** - * Runs and parses mode CON if it's available, suppressing any error output. - * - * @return string <width>x<height> or null if it could not be parsed - */ - private function getConsoleMode() - { - if (!function_exists('proc_open')) { - return; - } - - $descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w')); - $process = proc_open('mode CON', $descriptorspec, $pipes, null, null, array('suppress_errors' => true)); - if (is_resource($process)) { - $info = stream_get_contents($pipes[1]); - fclose($pipes[1]); - fclose($pipes[2]); - proc_close($process); - - if (preg_match('/--------+\r?\n.+?(\d+)\r?\n.+?(\d+)\r?\n/', $info, $matches)) { - return $matches[2].'x'.$matches[1]; - } - } - } - - /** * Returns abbreviated suggestions in string format. * * @param array $abbrevs Abbreviated suggestions to convert @@ -996,7 +1051,7 @@ class Application */ private function getAbbreviationSuggestions($abbrevs) { - return sprintf('%s, %s%s', $abbrevs[0], $abbrevs[1], count($abbrevs) > 2 ? sprintf(' and %d more', count($abbrevs) - 2) : ''); + return ' '.implode("\n ", $abbrevs); } /** @@ -1021,10 +1076,10 @@ class Application * Finds alternative of $name among $collection, * if nothing is found in $collection, try in $abbrevs. * - * @param string $name The string - * @param array|\Traversable $collection The collection + * @param string $name The string + * @param iterable $collection The collection * - * @return array A sorted array of similar string + * @return string[] A sorted array of similar string */ private function findAlternatives($name, $collection) { @@ -1063,7 +1118,7 @@ class Application } $alternatives = array_filter($alternatives, function ($lev) use ($threshold) { return $lev < 2 * $threshold; }); - asort($alternatives); + ksort($alternatives, SORT_NATURAL | SORT_FLAG_CASE); return array_keys($alternatives); } @@ -1071,20 +1126,23 @@ class Application /** * Sets the default Command name. * - * @param string $commandName The Command name + * @param string $commandName The Command name + * @param bool $isSingleCommand Set to true if there is only one command in this application + * + * @return self */ - public function setDefaultCommand($commandName) + public function setDefaultCommand($commandName, $isSingleCommand = false) { $this->defaultCommand = $commandName; - } - private function stringWidth($string) - { - if (false === $encoding = mb_detect_encoding($string, null, true)) { - return strlen($string); + if ($isSingleCommand) { + // Ensure the command exist + $this->find($commandName); + + $this->singleCommand = true; } - return mb_strwidth($string, $encoding); + return $this; } private function splitStringByWidth($string, $width) @@ -1109,9 +1167,8 @@ class Application $lines[] = str_pad($line, $width); $line = $char; } - if ('' !== $line) { - $lines[] = count($lines) ? str_pad($line, $width) : $line; - } + + $lines[] = count($lines) ? str_pad($line, $width) : $line; mb_convert_variables($encoding, 'utf8', $lines); @@ -1123,7 +1180,7 @@ class Application * * @param string $name The full name of the command * - * @return array The namespaces of the command + * @return string[] The namespaces of the command */ private function extractAllNamespaces($name) { @@ -1141,4 +1198,16 @@ class Application return $namespaces; } + + private function init() + { + if ($this->initialized) { + return; + } + $this->initialized = true; + + foreach ($this->getDefaultCommands() as $command) { + $this->add($command); + } + } } diff --git a/vendor/symfony/console/CHANGELOG.md b/vendor/symfony/console/CHANGELOG.md index 8021068e..946ff1e0 100644 --- a/vendor/symfony/console/CHANGELOG.md +++ b/vendor/symfony/console/CHANGELOG.md @@ -1,6 +1,45 @@ CHANGELOG ========= +3.4.0 +----- + + * added `SHELL_VERBOSITY` env var to control verbosity + * added `CommandLoaderInterface`, `FactoryCommandLoader` and PSR-11 + `ContainerCommandLoader` for commands lazy-loading + * added a case-insensitive command name matching fallback + * added static `Command::$defaultName/getDefaultName()`, allowing for + commands to be registered at compile time in the application command loader. + Setting the `$defaultName` property avoids the need for filling the `command` + attribute on the `console.command` tag when using `AddConsoleCommandPass`. + +3.3.0 +----- + +* added `ExceptionListener` +* added `AddConsoleCommandPass` (originally in FrameworkBundle) +* [BC BREAK] `Input::getOption()` no longer returns the default value for options + with value optional explicitly passed empty +* added console.error event to catch exceptions thrown by other listeners +* deprecated console.exception event in favor of console.error +* added ability to handle `CommandNotFoundException` through the + `console.error` event +* deprecated default validation in `SymfonyQuestionHelper::ask` + +3.2.0 +------ + +* added `setInputs()` method to CommandTester for ease testing of commands expecting inputs +* added `setStream()` and `getStream()` methods to Input (implement StreamableInputInterface) +* added StreamableInputInterface +* added LockableTrait + +3.1.0 +----- + + * added truncate method to FormatterHelper + * added setColumnWidth(s) method to Table + 2.8.3 ----- diff --git a/vendor/symfony/console/Command/Command.php b/vendor/symfony/console/Command/Command.php index 6acbe219..06930425 100644 --- a/vendor/symfony/console/Command/Command.php +++ b/vendor/symfony/console/Command/Command.php @@ -11,14 +11,11 @@ namespace Symfony\Component\Console\Command; -use Symfony\Component\Console\Descriptor\TextDescriptor; -use Symfony\Component\Console\Descriptor\XmlDescriptor; use Symfony\Component\Console\Exception\ExceptionInterface; use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\BufferedOutput; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Application; use Symfony\Component\Console\Helper\HelperSet; @@ -32,11 +29,17 @@ use Symfony\Component\Console\Exception\LogicException; */ class Command { + /** + * @var string|null The default command name + */ + protected static $defaultName; + private $application; private $name; private $processTitle; private $aliases = array(); private $definition; + private $hidden = false; private $help; private $description; private $ignoreValidationErrors = false; @@ -48,8 +51,17 @@ class Command private $helperSet; /** - * Constructor. - * + * @return string|null The default command name or null when no default name is set + */ + public static function getDefaultName() + { + $class = get_called_class(); + $r = new \ReflectionProperty($class, 'defaultName'); + + return $class === $r->class ? static::$defaultName : null; + } + + /** * @param string|null $name The name of the command; passing null means it must be set in configure() * * @throws LogicException When the command name is empty @@ -58,15 +70,11 @@ class Command { $this->definition = new InputDefinition(); - if (null !== $name) { + if (null !== $name || null !== $name = static::getDefaultName()) { $this->setName($name); } $this->configure(); - - if (!$this->name) { - throw new LogicException(sprintf('The command defined in "%s" cannot have an empty name.', get_class($this))); - } } /** @@ -79,11 +87,6 @@ class Command $this->ignoreValidationErrors = true; } - /** - * Sets the application instance for this command. - * - * @param Application $application An Application instance - */ public function setApplication(Application $application = null) { $this->application = $application; @@ -94,11 +97,6 @@ class Command } } - /** - * Sets the helper set. - * - * @param HelperSet $helperSet A HelperSet instance - */ public function setHelperSet(HelperSet $helperSet) { $this->helperSet = $helperSet; @@ -152,9 +150,6 @@ class Command * execute() method, you set the code to execute by passing * a Closure to the setCode() method. * - * @param InputInterface $input An InputInterface instance - * @param OutputInterface $output An OutputInterface instance - * * @return null|int null or 0 if everything went fine, or an error code * * @throws LogicException When this abstract method is not implemented @@ -172,9 +167,6 @@ class Command * This method is executed before the InputDefinition is validated. * This means that this is the only place where the command can * interactively ask for values of missing required arguments. - * - * @param InputInterface $input An InputInterface instance - * @param OutputInterface $output An OutputInterface instance */ protected function interact(InputInterface $input, OutputInterface $output) { @@ -185,9 +177,6 @@ class Command * * This is mainly useful when a lot of commands extends one main command * where some things need to be initialized based on the input arguments and options. - * - * @param InputInterface $input An InputInterface instance - * @param OutputInterface $output An OutputInterface instance */ protected function initialize(InputInterface $input, OutputInterface $output) { @@ -200,12 +189,9 @@ class Command * setCode() method or by overriding the execute() method * in a sub-class. * - * @param InputInterface $input An InputInterface instance - * @param OutputInterface $output An OutputInterface instance - * * @return int The command exit code * - * @throws \Exception + * @throws \Exception When binding input fails. Bypass this by calling {@link ignoreValidationErrors()}. * * @see setCode() * @see execute() @@ -232,7 +218,14 @@ class Command if (null !== $this->processTitle) { if (function_exists('cli_set_process_title')) { - cli_set_process_title($this->processTitle); + if (false === @cli_set_process_title($this->processTitle)) { + if ('Darwin' === PHP_OS) { + $output->writeln('<comment>Running "cli_get_process_title" as an unprivileged user is not supported on MacOS.</comment>'); + } else { + $error = error_get_last(); + trigger_error($error['message'], E_USER_WARNING); + } + } } elseif (function_exists('setproctitle')) { setproctitle($this->processTitle); } elseif (OutputInterface::VERBOSITY_VERY_VERBOSE === $output->getVerbosity()) { @@ -270,22 +263,26 @@ class Command * * @param callable $code A callable(InputInterface $input, OutputInterface $output) * - * @return Command The current instance + * @return $this * * @throws InvalidArgumentException * * @see execute() */ - public function setCode($code) + public function setCode(callable $code) { - if (!is_callable($code)) { - throw new InvalidArgumentException('Invalid callable provided to Command::setCode.'); - } - - if (PHP_VERSION_ID >= 50400 && $code instanceof \Closure) { + if ($code instanceof \Closure) { $r = new \ReflectionFunction($code); if (null === $r->getClosureThis()) { - $code = \Closure::bind($code, $this); + if (\PHP_VERSION_ID < 70000) { + // Bug in PHP5: https://bugs.php.net/bug.php?id=64761 + // This means that we cannot bind static closures and therefore we must + // ignore any errors here. There is no way to test if the closure is + // bindable. + $code = @\Closure::bind($code, $this); + } else { + $code = \Closure::bind($code, $this); + } } } @@ -326,7 +323,7 @@ class Command * * @param array|InputDefinition $definition An array of argument and option instances or a definition instance * - * @return Command The current instance + * @return $this */ public function setDefinition($definition) { @@ -352,7 +349,7 @@ class Command } /** - * Gets the InputDefinition to be used to create XML and Text representations of this Command. + * Gets the InputDefinition to be used to create representations of this Command. * * Can be overridden to provide the original command representation when it would otherwise * be changed by merging with the application InputDefinition. @@ -374,7 +371,7 @@ class Command * @param string $description A description text * @param mixed $default The default value (for InputArgument::OPTIONAL mode only) * - * @return Command The current instance + * @return $this */ public function addArgument($name, $mode = null, $description = '', $default = null) { @@ -392,7 +389,7 @@ class Command * @param string $description A description text * @param mixed $default The default value (must be null for InputOption::VALUE_NONE) * - * @return Command The current instance + * @return $this */ public function addOption($name, $shortcut = null, $mode = null, $description = '', $default = null) { @@ -411,7 +408,7 @@ class Command * * @param string $name The command name * - * @return Command The current instance + * @return $this * * @throws InvalidArgumentException When the name is invalid */ @@ -434,7 +431,7 @@ class Command * * @param string $title The process title * - * @return Command The current instance + * @return $this */ public function setProcessTitle($title) { @@ -454,11 +451,31 @@ class Command } /** + * @param bool $hidden Whether or not the command should be hidden from the list of commands + * + * @return Command The current instance + */ + public function setHidden($hidden) + { + $this->hidden = (bool) $hidden; + + return $this; + } + + /** + * @return bool whether the command should be publicly shown or not + */ + public function isHidden() + { + return $this->hidden; + } + + /** * Sets the description for the command. * * @param string $description The description for the command * - * @return Command The current instance + * @return $this */ public function setDescription($description) { @@ -482,7 +499,7 @@ class Command * * @param string $help The help for the command * - * @return Command The current instance + * @return $this */ public function setHelp($help) { @@ -528,7 +545,7 @@ class Command * * @param string[] $aliases An array of aliases for the command * - * @return Command The current instance + * @return $this * * @throws InvalidArgumentException When an alias is invalid */ @@ -579,6 +596,8 @@ class Command * Add a command usage example. * * @param string $usage The usage, it'll be prefixed with the command name + * + * @return $this */ public function addUsage($usage) { @@ -621,49 +640,6 @@ class Command } /** - * Returns a text representation of the command. - * - * @return string A string representing the command - * - * @deprecated since version 2.3, to be removed in 3.0. - */ - public function asText() - { - @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0.', E_USER_DEPRECATED); - - $descriptor = new TextDescriptor(); - $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true); - $descriptor->describe($output, $this, array('raw_output' => true)); - - return $output->fetch(); - } - - /** - * Returns an XML representation of the command. - * - * @param bool $asDom Whether to return a DOM or an XML string - * - * @return string|\DOMDocument An XML string representing the command - * - * @deprecated since version 2.3, to be removed in 3.0. - */ - public function asXml($asDom = false) - { - @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0.', E_USER_DEPRECATED); - - $descriptor = new XmlDescriptor(); - - if ($asDom) { - return $descriptor->getCommandDocument($this); - } - - $output = new BufferedOutput(); - $descriptor->describe($output, $this); - - return $output->fetch(); - } - - /** * Validates a command name. * * It must be non-empty and parts can optionally be separated by ":". diff --git a/vendor/symfony/console/Command/HelpCommand.php b/vendor/symfony/console/Command/HelpCommand.php index c0e7b388..112679b3 100644 --- a/vendor/symfony/console/Command/HelpCommand.php +++ b/vendor/symfony/console/Command/HelpCommand.php @@ -37,7 +37,6 @@ class HelpCommand extends Command ->setName('help') ->setDefinition(array( new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help'), - new InputOption('xml', null, InputOption::VALUE_NONE, 'To output help as XML'), new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'), new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command help'), )) @@ -57,11 +56,6 @@ EOF ; } - /** - * Sets the command. - * - * @param Command $command The command to set - */ public function setCommand(Command $command) { $this->command = $command; @@ -76,12 +70,6 @@ EOF $this->command = $this->getApplication()->find($input->getArgument('command_name')); } - if ($input->getOption('xml')) { - @trigger_error('The --xml option was deprecated in version 2.7 and will be removed in version 3.0. Use the --format option instead.', E_USER_DEPRECATED); - - $input->setOption('format', 'xml'); - } - $helper = new DescriptorHelper(); $helper->describe($output, $this->command, array( 'format' => $input->getOption('format'), diff --git a/vendor/symfony/console/Command/ListCommand.php b/vendor/symfony/console/Command/ListCommand.php index 5e1b926a..179ddea5 100644 --- a/vendor/symfony/console/Command/ListCommand.php +++ b/vendor/symfony/console/Command/ListCommand.php @@ -68,12 +68,6 @@ EOF */ protected function execute(InputInterface $input, OutputInterface $output) { - if ($input->getOption('xml')) { - @trigger_error('The --xml option was deprecated in version 2.7 and will be removed in version 3.0. Use the --format option instead.', E_USER_DEPRECATED); - - $input->setOption('format', 'xml'); - } - $helper = new DescriptorHelper(); $helper->describe($output, $this->getApplication(), array( 'format' => $input->getOption('format'), @@ -89,7 +83,6 @@ EOF { return new InputDefinition(array( new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'), - new InputOption('xml', null, InputOption::VALUE_NONE, 'To output list as XML'), new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command list'), new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'), )); diff --git a/vendor/symfony/console/Command/LockableTrait.php b/vendor/symfony/console/Command/LockableTrait.php new file mode 100644 index 00000000..308ebf28 --- /dev/null +++ b/vendor/symfony/console/Command/LockableTrait.php @@ -0,0 +1,72 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Command; + +use Symfony\Component\Console\Exception\LogicException; +use Symfony\Component\Console\Exception\RuntimeException; +use Symfony\Component\Lock\Factory; +use Symfony\Component\Lock\Lock; +use Symfony\Component\Lock\Store\FlockStore; +use Symfony\Component\Lock\Store\SemaphoreStore; + +/** + * Basic lock feature for commands. + * + * @author Geoffrey Brier <geoffrey.brier@gmail.com> + */ +trait LockableTrait +{ + /** @var Lock */ + private $lock; + + /** + * Locks a command. + * + * @return bool + */ + private function lock($name = null, $blocking = false) + { + if (!class_exists(SemaphoreStore::class)) { + throw new RuntimeException('To enable the locking feature you must install the symfony/lock component.'); + } + + if (null !== $this->lock) { + throw new LogicException('A lock is already in place.'); + } + + if (SemaphoreStore::isSupported($blocking)) { + $store = new SemaphoreStore(); + } else { + $store = new FlockStore(); + } + + $this->lock = (new Factory($store))->createLock($name ?: $this->getName()); + if (!$this->lock->acquire($blocking)) { + $this->lock = null; + + return false; + } + + return true; + } + + /** + * Releases the command lock if there is one. + */ + private function release() + { + if ($this->lock) { + $this->lock->release(); + $this->lock = null; + } + } +} diff --git a/vendor/symfony/console/CommandLoader/CommandLoaderInterface.php b/vendor/symfony/console/CommandLoader/CommandLoaderInterface.php new file mode 100644 index 00000000..9462996f --- /dev/null +++ b/vendor/symfony/console/CommandLoader/CommandLoaderInterface.php @@ -0,0 +1,37 @@ +<?php + +namespace Symfony\Component\Console\CommandLoader; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Exception\CommandNotFoundException; + +/** + * @author Robin Chalas <robin.chalas@gmail.com> + */ +interface CommandLoaderInterface +{ + /** + * Loads a command. + * + * @param string $name + * + * @return Command + * + * @throws CommandNotFoundException + */ + public function get($name); + + /** + * Checks if a command exists. + * + * @param string $name + * + * @return bool + */ + public function has($name); + + /** + * @return string[] All registered command names + */ + public function getNames(); +} diff --git a/vendor/symfony/console/CommandLoader/ContainerCommandLoader.php b/vendor/symfony/console/CommandLoader/ContainerCommandLoader.php new file mode 100644 index 00000000..753ad0fb --- /dev/null +++ b/vendor/symfony/console/CommandLoader/ContainerCommandLoader.php @@ -0,0 +1,55 @@ +<?php + +namespace Symfony\Component\Console\CommandLoader; + +use Psr\Container\ContainerInterface; +use Symfony\Component\Console\Exception\CommandNotFoundException; + +/** + * Loads commands from a PSR-11 container. + * + * @author Robin Chalas <robin.chalas@gmail.com> + */ +class ContainerCommandLoader implements CommandLoaderInterface +{ + private $container; + private $commandMap; + + /** + * @param ContainerInterface $container A container from which to load command services + * @param array $commandMap An array with command names as keys and service ids as values + */ + public function __construct(ContainerInterface $container, array $commandMap) + { + $this->container = $container; + $this->commandMap = $commandMap; + } + + /** + * {@inheritdoc} + */ + public function get($name) + { + if (!$this->has($name)) { + throw new CommandNotFoundException(sprintf('Command "%s" does not exist.', $name)); + } + + return $this->container->get($this->commandMap[$name]); + } + + /** + * {@inheritdoc} + */ + public function has($name) + { + return isset($this->commandMap[$name]) && $this->container->has($this->commandMap[$name]); + } + + /** + * {@inheritdoc} + */ + public function getNames() + { + return array_keys($this->commandMap); + } +} diff --git a/vendor/symfony/console/CommandLoader/FactoryCommandLoader.php b/vendor/symfony/console/CommandLoader/FactoryCommandLoader.php new file mode 100644 index 00000000..d9c20557 --- /dev/null +++ b/vendor/symfony/console/CommandLoader/FactoryCommandLoader.php @@ -0,0 +1,62 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\CommandLoader; + +use Symfony\Component\Console\Exception\CommandNotFoundException; + +/** + * A simple command loader using factories to instantiate commands lazily. + * + * @author Maxime Steinhausser <maxime.steinhausser@gmail.com> + */ +class FactoryCommandLoader implements CommandLoaderInterface +{ + private $factories; + + /** + * @param callable[] $factories Indexed by command names + */ + public function __construct(array $factories) + { + $this->factories = $factories; + } + + /** + * {@inheritdoc} + */ + public function has($name) + { + return isset($this->factories[$name]); + } + + /** + * {@inheritdoc} + */ + public function get($name) + { + if (!isset($this->factories[$name])) { + throw new CommandNotFoundException(sprintf('Command "%s" does not exist.', $name)); + } + + $factory = $this->factories[$name]; + + return $factory(); + } + + /** + * {@inheritdoc} + */ + public function getNames() + { + return array_keys($this->factories); + } +} diff --git a/vendor/symfony/console/ConsoleEvents.php b/vendor/symfony/console/ConsoleEvents.php index 1ed41b7d..bf6cab9a 100644 --- a/vendor/symfony/console/ConsoleEvents.php +++ b/vendor/symfony/console/ConsoleEvents.php @@ -23,12 +23,7 @@ final class ConsoleEvents * executed by the console. It also allows you to modify the command, input and output * before they are handled to the command. * - * The event listener method receives a Symfony\Component\Console\Event\ConsoleCommandEvent - * instance. - * - * @Event - * - * @var string + * @Event("Symfony\Component\Console\Event\ConsoleCommandEvent") */ const COMMAND = 'console.command'; @@ -36,26 +31,30 @@ final class ConsoleEvents * The TERMINATE event allows you to attach listeners after a command is * executed by the console. * - * The event listener method receives a Symfony\Component\Console\Event\ConsoleTerminateEvent - * instance. - * - * @Event - * - * @var string + * @Event("Symfony\Component\Console\Event\ConsoleTerminateEvent") */ const TERMINATE = 'console.terminate'; /** - * The EXCEPTION event occurs when an uncaught exception appears. + * The EXCEPTION event occurs when an uncaught exception appears + * while executing Command#run(). * * This event allows you to deal with the exception or - * to modify the thrown exception. The event listener method receives - * a Symfony\Component\Console\Event\ConsoleExceptionEvent - * instance. + * to modify the thrown exception. * - * @Event + * @Event("Symfony\Component\Console\Event\ConsoleExceptionEvent") * - * @var string + * @deprecated The console.exception event is deprecated since version 3.3 and will be removed in 4.0. Use the console.error event instead. */ const EXCEPTION = 'console.exception'; + + /** + * The ERROR event occurs when an uncaught exception or error appears. + * + * This event allows you to deal with the exception/error or + * to modify the thrown exception. + * + * @Event("Symfony\Component\Console\Event\ConsoleErrorEvent") + */ + const ERROR = 'console.error'; } diff --git a/vendor/symfony/console/DependencyInjection/AddConsoleCommandPass.php b/vendor/symfony/console/DependencyInjection/AddConsoleCommandPass.php new file mode 100644 index 00000000..39d53ef8 --- /dev/null +++ b/vendor/symfony/console/DependencyInjection/AddConsoleCommandPass.php @@ -0,0 +1,106 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\DependencyInjection; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\CommandLoader\ContainerCommandLoader; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\TypedReference; + +/** + * Registers console commands. + * + * @author Grégoire Pineau <lyrixx@lyrixx.info> + */ +class AddConsoleCommandPass implements CompilerPassInterface +{ + private $commandLoaderServiceId; + private $commandTag; + + public function __construct($commandLoaderServiceId = 'console.command_loader', $commandTag = 'console.command') + { + $this->commandLoaderServiceId = $commandLoaderServiceId; + $this->commandTag = $commandTag; + } + + public function process(ContainerBuilder $container) + { + $commandServices = $container->findTaggedServiceIds($this->commandTag, true); + $lazyCommandMap = array(); + $lazyCommandRefs = array(); + $serviceIds = array(); + $lazyServiceIds = array(); + + foreach ($commandServices as $id => $tags) { + $definition = $container->getDefinition($id); + $class = $container->getParameterBag()->resolveValue($definition->getClass()); + + $commandId = 'console.command.'.strtolower(str_replace('\\', '_', $class)); + + if (isset($tags[0]['command'])) { + $commandName = $tags[0]['command']; + } else { + if (!$r = $container->getReflectionClass($class)) { + throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); + } + if (!$r->isSubclassOf(Command::class)) { + throw new InvalidArgumentException(sprintf('The service "%s" tagged "%s" must be a subclass of "%s".', $id, $this->commandTag, Command::class)); + } + $commandName = $class::getDefaultName(); + } + + if (null === $commandName) { + if (isset($serviceIds[$commandId]) || $container->hasAlias($commandId)) { + $commandId = $commandId.'_'.$id; + } + if (!$definition->isPublic() || $definition->isPrivate()) { + $container->setAlias($commandId, $id)->setPublic(true); + $id = $commandId; + } + $serviceIds[$commandId] = $id; + + continue; + } + + $serviceIds[$commandId] = $id; + $lazyServiceIds[$id] = true; + unset($tags[0]); + $lazyCommandMap[$commandName] = $id; + $lazyCommandRefs[$id] = new TypedReference($id, $class); + $aliases = array(); + + foreach ($tags as $tag) { + if (isset($tag['command'])) { + $aliases[] = $tag['command']; + $lazyCommandMap[$tag['command']] = $id; + } + } + + $definition->addMethodCall('setName', array($commandName)); + + if ($aliases) { + $definition->addMethodCall('setAliases', array($aliases)); + } + } + + $container + ->register($this->commandLoaderServiceId, ContainerCommandLoader::class) + ->setPublic(true) + ->setArguments(array(ServiceLocatorTagPass::register($container, $lazyCommandRefs), $lazyCommandMap)); + + $container->setParameter('console.command.ids', $serviceIds); + $container->setParameter('console.lazy_command.ids', $lazyServiceIds); + } +} diff --git a/vendor/symfony/console/Descriptor/ApplicationDescription.php b/vendor/symfony/console/Descriptor/ApplicationDescription.php index 89961b9c..ef4c673b 100644 --- a/vendor/symfony/console/Descriptor/ApplicationDescription.php +++ b/vendor/symfony/console/Descriptor/ApplicationDescription.php @@ -24,15 +24,9 @@ class ApplicationDescription { const GLOBAL_NAMESPACE = '_global'; - /** - * @var Application - */ private $application; - - /** - * @var null|string - */ private $namespace; + private $showHidden; /** * @var array @@ -50,15 +44,15 @@ class ApplicationDescription private $aliases; /** - * Constructor. - * * @param Application $application * @param string|null $namespace + * @param bool $showHidden */ - public function __construct(Application $application, $namespace = null) + public function __construct(Application $application, $namespace = null, $showHidden = false) { $this->application = $application; $this->namespace = $namespace; + $this->showHidden = $showHidden; } /** @@ -112,7 +106,7 @@ class ApplicationDescription /** @var Command $command */ foreach ($commands as $name => $command) { - if (!$command->getName()) { + if (!$command->getName() || (!$this->showHidden && $command->isHidden())) { continue; } @@ -130,8 +124,6 @@ class ApplicationDescription } /** - * @param array $commands - * * @return array */ private function sortCommands(array $commands) diff --git a/vendor/symfony/console/Descriptor/Descriptor.php b/vendor/symfony/console/Descriptor/Descriptor.php index 43a7a0a1..fe169cb4 100644 --- a/vendor/symfony/console/Descriptor/Descriptor.php +++ b/vendor/symfony/console/Descriptor/Descriptor.php @@ -29,7 +29,7 @@ abstract class Descriptor implements DescriptorInterface /** * @var OutputInterface */ - private $output; + protected $output; /** * {@inheritdoc} @@ -73,9 +73,6 @@ abstract class Descriptor implements DescriptorInterface /** * Describes an InputArgument instance. * - * @param InputArgument $argument - * @param array $options - * * @return string|mixed */ abstract protected function describeInputArgument(InputArgument $argument, array $options = array()); @@ -83,9 +80,6 @@ abstract class Descriptor implements DescriptorInterface /** * Describes an InputOption instance. * - * @param InputOption $option - * @param array $options - * * @return string|mixed */ abstract protected function describeInputOption(InputOption $option, array $options = array()); @@ -93,9 +87,6 @@ abstract class Descriptor implements DescriptorInterface /** * Describes an InputDefinition instance. * - * @param InputDefinition $definition - * @param array $options - * * @return string|mixed */ abstract protected function describeInputDefinition(InputDefinition $definition, array $options = array()); @@ -103,9 +94,6 @@ abstract class Descriptor implements DescriptorInterface /** * Describes a Command instance. * - * @param Command $command - * @param array $options - * * @return string|mixed */ abstract protected function describeCommand(Command $command, array $options = array()); @@ -113,9 +101,6 @@ abstract class Descriptor implements DescriptorInterface /** * Describes an Application instance. * - * @param Application $application - * @param array $options - * * @return string|mixed */ abstract protected function describeApplication(Application $application, array $options = array()); diff --git a/vendor/symfony/console/Descriptor/JsonDescriptor.php b/vendor/symfony/console/Descriptor/JsonDescriptor.php index 87e38fdb..35c87c22 100644 --- a/vendor/symfony/console/Descriptor/JsonDescriptor.php +++ b/vendor/symfony/console/Descriptor/JsonDescriptor.php @@ -64,16 +64,28 @@ class JsonDescriptor extends Descriptor protected function describeApplication(Application $application, array $options = array()) { $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null; - $description = new ApplicationDescription($application, $describedNamespace); + $description = new ApplicationDescription($application, $describedNamespace, true); $commands = array(); foreach ($description->getCommands() as $command) { $commands[] = $this->getCommandData($command); } - $data = $describedNamespace - ? array('commands' => $commands, 'namespace' => $describedNamespace) - : array('commands' => $commands, 'namespaces' => array_values($description->getNamespaces())); + $data = array(); + if ('UNKNOWN' !== $application->getName()) { + $data['application']['name'] = $application->getName(); + if ('UNKNOWN' !== $application->getVersion()) { + $data['application']['version'] = $application->getVersion(); + } + } + + $data['commands'] = $commands; + + if ($describedNamespace) { + $data['namespace'] = $describedNamespace; + } else { + $data['namespaces'] = array_values($description->getNamespaces()); + } $this->writeData($data, $options); } @@ -81,9 +93,6 @@ class JsonDescriptor extends Descriptor /** * Writes data as json. * - * @param array $data - * @param array $options - * * @return array|string */ private function writeData(array $data, array $options) @@ -92,8 +101,6 @@ class JsonDescriptor extends Descriptor } /** - * @param InputArgument $argument - * * @return array */ private function getInputArgumentData(InputArgument $argument) @@ -103,13 +110,11 @@ class JsonDescriptor extends Descriptor 'is_required' => $argument->isRequired(), 'is_array' => $argument->isArray(), 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $argument->getDescription()), - 'default' => $argument->getDefault(), + 'default' => INF === $argument->getDefault() ? 'INF' : $argument->getDefault(), ); } /** - * @param InputOption $option - * * @return array */ private function getInputOptionData(InputOption $option) @@ -121,13 +126,11 @@ class JsonDescriptor extends Descriptor 'is_value_required' => $option->isValueRequired(), 'is_multiple' => $option->isArray(), 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $option->getDescription()), - 'default' => $option->getDefault(), + 'default' => INF === $option->getDefault() ? 'INF' : $option->getDefault(), ); } /** - * @param InputDefinition $definition - * * @return array */ private function getInputDefinitionData(InputDefinition $definition) @@ -146,8 +149,6 @@ class JsonDescriptor extends Descriptor } /** - * @param Command $command - * * @return array */ private function getCommandData(Command $command) @@ -161,6 +162,7 @@ class JsonDescriptor extends Descriptor 'description' => $command->getDescription(), 'help' => $command->getProcessedHelp(), 'definition' => $this->getInputDefinitionData($command->getNativeDefinition()), + 'hidden' => $command->isHidden(), ); } } diff --git a/vendor/symfony/console/Descriptor/MarkdownDescriptor.php b/vendor/symfony/console/Descriptor/MarkdownDescriptor.php index d3d76a42..106bff51 100644 --- a/vendor/symfony/console/Descriptor/MarkdownDescriptor.php +++ b/vendor/symfony/console/Descriptor/MarkdownDescriptor.php @@ -13,9 +13,11 @@ namespace Symfony\Component\Console\Descriptor; use Symfony\Component\Console\Application; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Helper\Helper; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; /** * Markdown descriptor. @@ -29,14 +31,34 @@ class MarkdownDescriptor extends Descriptor /** * {@inheritdoc} */ + public function describe(OutputInterface $output, $object, array $options = array()) + { + $decorated = $output->isDecorated(); + $output->setDecorated(false); + + parent::describe($output, $object, $options); + + $output->setDecorated($decorated); + } + + /** + * {@inheritdoc} + */ + protected function write($content, $decorated = true) + { + parent::write($content, $decorated); + } + + /** + * {@inheritdoc} + */ protected function describeInputArgument(InputArgument $argument, array $options = array()) { $this->write( - '**'.$argument->getName().':**'."\n\n" - .'* Name: '.($argument->getName() ?: '<none>')."\n" + '#### `'.($argument->getName() ?: '<none>')."`\n\n" + .($argument->getDescription() ? preg_replace('/\s*[\r\n]\s*/', "\n", $argument->getDescription())."\n\n" : '') .'* Is required: '.($argument->isRequired() ? 'yes' : 'no')."\n" .'* Is array: '.($argument->isArray() ? 'yes' : 'no')."\n" - .'* Description: '.preg_replace('/\s*[\r\n]\s*/', "\n ", $argument->getDescription() ?: '<none>')."\n" .'* Default: `'.str_replace("\n", '', var_export($argument->getDefault(), true)).'`' ); } @@ -46,14 +68,17 @@ class MarkdownDescriptor extends Descriptor */ protected function describeInputOption(InputOption $option, array $options = array()) { + $name = '--'.$option->getName(); + if ($option->getShortcut()) { + $name .= '|-'.implode('|-', explode('|', $option->getShortcut())).''; + } + $this->write( - '**'.$option->getName().':**'."\n\n" - .'* Name: `--'.$option->getName().'`'."\n" - .'* Shortcut: '.($option->getShortcut() ? '`-'.implode('|-', explode('|', $option->getShortcut())).'`' : '<none>')."\n" + '#### `'.$name.'`'."\n\n" + .($option->getDescription() ? preg_replace('/\s*[\r\n]\s*/', "\n", $option->getDescription())."\n\n" : '') .'* Accept value: '.($option->acceptValue() ? 'yes' : 'no')."\n" .'* Is value required: '.($option->isValueRequired() ? 'yes' : 'no')."\n" .'* Is multiple: '.($option->isArray() ? 'yes' : 'no')."\n" - .'* Description: '.preg_replace('/\s*[\r\n]\s*/', "\n ", $option->getDescription() ?: '<none>')."\n" .'* Default: `'.str_replace("\n", '', var_export($option->getDefault(), true)).'`' ); } @@ -64,7 +89,7 @@ class MarkdownDescriptor extends Descriptor protected function describeInputDefinition(InputDefinition $definition, array $options = array()) { if ($showArguments = count($definition->getArguments()) > 0) { - $this->write('### Arguments:'); + $this->write('### Arguments'); foreach ($definition->getArguments() as $argument) { $this->write("\n\n"); $this->write($this->describeInputArgument($argument)); @@ -76,7 +101,7 @@ class MarkdownDescriptor extends Descriptor $this->write("\n\n"); } - $this->write('### Options:'); + $this->write('### Options'); foreach ($definition->getOptions() as $option) { $this->write("\n\n"); $this->write($this->describeInputOption($option)); @@ -93,12 +118,12 @@ class MarkdownDescriptor extends Descriptor $command->mergeApplicationDefinition(false); $this->write( - $command->getName()."\n" - .str_repeat('-', strlen($command->getName()))."\n\n" - .'* Description: '.($command->getDescription() ?: '<none>')."\n" - .'* Usage:'."\n\n" + '`'.$command->getName()."`\n" + .str_repeat('-', Helper::strlen($command->getName()) + 2)."\n\n" + .($command->getDescription() ? $command->getDescription()."\n\n" : '') + .'### Usage'."\n\n" .array_reduce(array_merge(array($command->getSynopsis()), $command->getAliases(), $command->getUsages()), function ($carry, $usage) { - return $carry .= ' * `'.$usage.'`'."\n"; + return $carry.'* `'.$usage.'`'."\n"; }) ); @@ -120,8 +145,9 @@ class MarkdownDescriptor extends Descriptor { $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null; $description = new ApplicationDescription($application, $describedNamespace); + $title = $this->getApplicationTitle($application); - $this->write($application->getName()."\n".str_repeat('=', strlen($application->getName()))); + $this->write($title."\n".str_repeat('=', Helper::strlen($title))); foreach ($description->getNamespaces() as $namespace) { if (ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) { @@ -130,8 +156,8 @@ class MarkdownDescriptor extends Descriptor } $this->write("\n\n"); - $this->write(implode("\n", array_map(function ($commandName) { - return '* '.$commandName; + $this->write(implode("\n", array_map(function ($commandName) use ($description) { + return sprintf('* [`%s`](#%s)', $commandName, str_replace(':', '', $description->getCommand($commandName)->getName())); }, $namespace['commands']))); } @@ -140,4 +166,17 @@ class MarkdownDescriptor extends Descriptor $this->write($this->describeCommand($command)); } } + + private function getApplicationTitle(Application $application) + { + if ('UNKNOWN' !== $application->getName()) { + if ('UNKNOWN' !== $application->getVersion()) { + return sprintf('%s %s', $application->getName(), $application->getVersion()); + } + + return $application->getName(); + } + + return 'Console Tool'; + } } diff --git a/vendor/symfony/console/Descriptor/TextDescriptor.php b/vendor/symfony/console/Descriptor/TextDescriptor.php index 64b53971..a79df7e2 100644 --- a/vendor/symfony/console/Descriptor/TextDescriptor.php +++ b/vendor/symfony/console/Descriptor/TextDescriptor.php @@ -13,6 +13,8 @@ namespace Symfony\Component\Console\Descriptor; use Symfony\Component\Console\Application; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Formatter\OutputFormatter; +use Symfony\Component\Console\Helper\Helper; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputOption; @@ -37,14 +39,14 @@ class TextDescriptor extends Descriptor $default = ''; } - $totalWidth = isset($options['total_width']) ? $options['total_width'] : strlen($argument->getName()); - $spacingWidth = $totalWidth - strlen($argument->getName()) + 2; + $totalWidth = isset($options['total_width']) ? $options['total_width'] : Helper::strlen($argument->getName()); + $spacingWidth = $totalWidth - strlen($argument->getName()); - $this->writeText(sprintf(' <info>%s</info>%s%s%s', + $this->writeText(sprintf(' <info>%s</info> %s%s%s', $argument->getName(), str_repeat(' ', $spacingWidth), - // + 17 = 2 spaces + <info> + </info> + 2 spaces - preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 17), $argument->getDescription()), + // + 4 = 2 spaces before <info>, 2 spaces after </info> + preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $argument->getDescription()), $default ), $options); } @@ -75,13 +77,13 @@ class TextDescriptor extends Descriptor sprintf('--%s%s', $option->getName(), $value) ); - $spacingWidth = $totalWidth - strlen($synopsis) + 2; + $spacingWidth = $totalWidth - Helper::strlen($synopsis); - $this->writeText(sprintf(' <info>%s</info>%s%s%s%s', + $this->writeText(sprintf(' <info>%s</info> %s%s%s%s', $synopsis, str_repeat(' ', $spacingWidth), - // + 17 = 2 spaces + <info> + </info> + 2 spaces - preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 17), $option->getDescription()), + // + 4 = 2 spaces before <info>, 2 spaces after </info> + preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $option->getDescription()), $default, $option->isArray() ? '<comment> (multiple values allowed)</comment>' : '' ), $options); @@ -94,7 +96,7 @@ class TextDescriptor extends Descriptor { $totalWidth = $this->calculateTotalWidthForOptions($definition->getOptions()); foreach ($definition->getArguments() as $argument) { - $totalWidth = max($totalWidth, strlen($argument->getName())); + $totalWidth = max($totalWidth, Helper::strlen($argument->getName())); } if ($definition->getArguments()) { @@ -141,7 +143,7 @@ class TextDescriptor extends Descriptor $this->writeText('<comment>Usage:</comment>', $options); foreach (array_merge(array($command->getSynopsis(true)), $command->getAliases(), $command->getUsages()) as $usage) { $this->writeText("\n"); - $this->writeText(' '.$usage, $options); + $this->writeText(' '.OutputFormatter::escape($usage), $options); } $this->writeText("\n"); @@ -156,7 +158,7 @@ class TextDescriptor extends Descriptor $this->writeText("\n"); $this->writeText('<comment>Help:</comment>', $options); $this->writeText("\n"); - $this->writeText(' '.str_replace("\n", "\n ", $help), $options); + $this->writeText(' '.str_replace("\n", "\n ", $help), $options); $this->writeText("\n"); } } @@ -189,7 +191,20 @@ class TextDescriptor extends Descriptor $this->writeText("\n"); $this->writeText("\n"); - $width = $this->getColumnWidth($description->getCommands()); + $commands = $description->getCommands(); + $namespaces = $description->getNamespaces(); + if ($describedNamespace && $namespaces) { + // make sure all alias commands are included when describing a specific namespace + $describedNamespaceInfo = reset($namespaces); + foreach ($describedNamespaceInfo['commands'] as $name) { + $commands[$name] = $description->getCommand($name); + } + } + + // calculate max. width based on available commands per namespace + $width = $this->getColumnWidth(call_user_func_array('array_merge', array_map(function ($namespace) use ($commands) { + return array_intersect($namespace['commands'], array_keys($commands)); + }, $namespaces))); if ($describedNamespace) { $this->writeText(sprintf('<comment>Available commands for the "%s" namespace:</comment>', $describedNamespace), $options); @@ -197,8 +212,15 @@ class TextDescriptor extends Descriptor $this->writeText('<comment>Available commands:</comment>', $options); } - // add commands by namespace - foreach ($description->getNamespaces() as $namespace) { + foreach ($namespaces as $namespace) { + $namespace['commands'] = array_filter($namespace['commands'], function ($name) use ($commands) { + return isset($commands[$name]); + }); + + if (!$namespace['commands']) { + continue; + } + if (!$describedNamespace && ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) { $this->writeText("\n"); $this->writeText(' <comment>'.$namespace['id'].'</comment>', $options); @@ -206,8 +228,10 @@ class TextDescriptor extends Descriptor foreach ($namespace['commands'] as $name) { $this->writeText("\n"); - $spacingWidth = $width - strlen($name); - $this->writeText(sprintf(' <info>%s</info>%s%s', $name, str_repeat(' ', $spacingWidth), $description->getCommand($name)->getDescription()), $options); + $spacingWidth = $width - Helper::strlen($name); + $command = $commands[$name]; + $commandAliases = $name === $command->getName() ? $this->getCommandAliasesText($command) : ''; + $this->writeText(sprintf(' <info>%s</info>%s%s', $name, str_repeat(' ', $spacingWidth), $commandAliases.$command->getDescription()), $options); } } @@ -227,6 +251,23 @@ class TextDescriptor extends Descriptor } /** + * Formats command aliases to show them in the command description. + * + * @return string + */ + private function getCommandAliasesText(Command $command) + { + $text = ''; + $aliases = $command->getAliases(); + + if ($aliases) { + $text = '['.implode('|', $aliases).'] '; + } + + return $text; + } + + /** * Formats input option/argument default value. * * @param mixed $default @@ -235,15 +276,25 @@ class TextDescriptor extends Descriptor */ private function formatDefaultValue($default) { - if (PHP_VERSION_ID < 50400) { - return str_replace(array('\/', '\\\\'), array('/', '\\'), json_encode($default)); + if (INF === $default) { + return 'INF'; + } + + if (is_string($default)) { + $default = OutputFormatter::escape($default); + } elseif (is_array($default)) { + foreach ($default as $key => $value) { + if (is_string($value)) { + $default[$key] = OutputFormatter::escape($value); + } + } } return str_replace('\\\\', '\\', json_encode($default, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)); } /** - * @param Command[] $commands + * @param (Command|string)[] $commands * * @return int */ @@ -252,13 +303,17 @@ class TextDescriptor extends Descriptor $widths = array(); foreach ($commands as $command) { - $widths[] = strlen($command->getName()); - foreach ($command->getAliases() as $alias) { - $widths[] = strlen($alias); + if ($command instanceof Command) { + $widths[] = Helper::strlen($command->getName()); + foreach ($command->getAliases() as $alias) { + $widths[] = Helper::strlen($alias); + } + } else { + $widths[] = Helper::strlen($command); } } - return max($widths) + 2; + return $widths ? max($widths) + 2 : 0; } /** @@ -266,15 +321,15 @@ class TextDescriptor extends Descriptor * * @return int */ - private function calculateTotalWidthForOptions($options) + private function calculateTotalWidthForOptions(array $options) { $totalWidth = 0; foreach ($options as $option) { // "-" + shortcut + ", --" + name - $nameLength = 1 + max(strlen($option->getShortcut()), 1) + 4 + strlen($option->getName()); + $nameLength = 1 + max(Helper::strlen($option->getShortcut()), 1) + 4 + Helper::strlen($option->getName()); if ($option->acceptValue()) { - $valueLength = 1 + strlen($option->getName()); // = + value + $valueLength = 1 + Helper::strlen($option->getName()); // = + value $valueLength += $option->isValueOptional() ? 2 : 0; // [ + ] $nameLength += $valueLength; diff --git a/vendor/symfony/console/Descriptor/XmlDescriptor.php b/vendor/symfony/console/Descriptor/XmlDescriptor.php index b5676beb..f05756ca 100644 --- a/vendor/symfony/console/Descriptor/XmlDescriptor.php +++ b/vendor/symfony/console/Descriptor/XmlDescriptor.php @@ -27,8 +27,6 @@ use Symfony\Component\Console\Input\InputOption; class XmlDescriptor extends Descriptor { /** - * @param InputDefinition $definition - * * @return \DOMDocument */ public function getInputDefinitionDocument(InputDefinition $definition) @@ -50,8 +48,6 @@ class XmlDescriptor extends Descriptor } /** - * @param Command $command - * * @return \DOMDocument */ public function getCommandDocument(Command $command) @@ -64,6 +60,7 @@ class XmlDescriptor extends Descriptor $commandXML->setAttribute('id', $command->getName()); $commandXML->setAttribute('name', $command->getName()); + $commandXML->setAttribute('hidden', $command->isHidden() ? 1 : 0); $commandXML->appendChild($usagesXML = $dom->createElement('usages')); @@ -94,16 +91,16 @@ class XmlDescriptor extends Descriptor $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->appendChild($rootXml = $dom->createElement('symfony')); - if ($application->getName() !== 'UNKNOWN') { + if ('UNKNOWN' !== $application->getName()) { $rootXml->setAttribute('name', $application->getName()); - if ($application->getVersion() !== 'UNKNOWN') { + if ('UNKNOWN' !== $application->getVersion()) { $rootXml->setAttribute('version', $application->getVersion()); } } $rootXml->appendChild($commandsXML = $dom->createElement('commands')); - $description = new ApplicationDescription($application, $namespace); + $description = new ApplicationDescription($application, $namespace, true); if ($namespace) { $commandsXML->setAttribute('namespace', $namespace); @@ -172,9 +169,6 @@ class XmlDescriptor extends Descriptor /** * Appends document children to parent node. - * - * @param \DOMNode $parentNode - * @param \DOMNode $importedParent */ private function appendDocument(\DOMNode $parentNode, \DOMNode $importedParent) { @@ -186,8 +180,6 @@ class XmlDescriptor extends Descriptor /** * Writes DOM document. * - * @param \DOMDocument $dom - * * @return \DOMDocument|string */ private function writeDocument(\DOMDocument $dom) @@ -197,8 +189,6 @@ class XmlDescriptor extends Descriptor } /** - * @param InputArgument $argument - * * @return \DOMDocument */ private function getInputArgumentDocument(InputArgument $argument) @@ -223,8 +213,6 @@ class XmlDescriptor extends Descriptor } /** - * @param InputOption $option - * * @return \DOMDocument */ private function getInputOptionDocument(InputOption $option) diff --git a/vendor/symfony/console/Event/ConsoleCommandEvent.php b/vendor/symfony/console/Event/ConsoleCommandEvent.php index 92adf1ef..2f517c1d 100644 --- a/vendor/symfony/console/Event/ConsoleCommandEvent.php +++ b/vendor/symfony/console/Event/ConsoleCommandEvent.php @@ -25,8 +25,6 @@ class ConsoleCommandEvent extends ConsoleEvent /** * Indicates if the command should be run or skipped. - * - * @var bool */ private $commandShouldRun = true; diff --git a/vendor/symfony/console/Event/ConsoleErrorEvent.php b/vendor/symfony/console/Event/ConsoleErrorEvent.php new file mode 100644 index 00000000..0d05b9da --- /dev/null +++ b/vendor/symfony/console/Event/ConsoleErrorEvent.php @@ -0,0 +1,83 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Event; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Allows to handle throwables thrown while running a command. + * + * @author Wouter de Jong <wouter@wouterj.nl> + */ +final class ConsoleErrorEvent extends ConsoleEvent +{ + private $error; + private $exitCode; + + public function __construct(InputInterface $input, OutputInterface $output, $error, Command $command = null) + { + parent::__construct($command, $input, $output); + + $this->setError($error); + } + + /** + * Returns the thrown error/exception. + * + * @return \Throwable + */ + public function getError() + { + return $this->error; + } + + /** + * Replaces the thrown error/exception. + * + * @param \Throwable $error + */ + public function setError($error) + { + if (!$error instanceof \Throwable && !$error instanceof \Exception) { + throw new InvalidArgumentException(sprintf('The error passed to ConsoleErrorEvent must be an instance of \Throwable or \Exception, "%s" was passed instead.', is_object($error) ? get_class($error) : gettype($error))); + } + + $this->error = $error; + } + + /** + * Sets the exit code. + * + * @param int $exitCode The command exit code + */ + public function setExitCode($exitCode) + { + $this->exitCode = (int) $exitCode; + + $r = new \ReflectionProperty($this->error, 'code'); + $r->setAccessible(true); + $r->setValue($this->error, $this->exitCode); + } + + /** + * Gets the exit code. + * + * @return int The command exit code + */ + public function getExitCode() + { + return null !== $this->exitCode ? $this->exitCode : (is_int($this->error->getCode()) && 0 !== $this->error->getCode() ? $this->error->getCode() : 1); + } +} diff --git a/vendor/symfony/console/Event/ConsoleEvent.php b/vendor/symfony/console/Event/ConsoleEvent.php index ab620c46..5440da21 100644 --- a/vendor/symfony/console/Event/ConsoleEvent.php +++ b/vendor/symfony/console/Event/ConsoleEvent.php @@ -28,7 +28,7 @@ class ConsoleEvent extends Event private $input; private $output; - public function __construct(Command $command, InputInterface $input, OutputInterface $output) + public function __construct(Command $command = null, InputInterface $input, OutputInterface $output) { $this->command = $command; $this->input = $input; @@ -38,7 +38,7 @@ class ConsoleEvent extends Event /** * Gets the command that is executed. * - * @return Command A Command instance + * @return Command|null A Command instance */ public function getCommand() { diff --git a/vendor/symfony/console/Event/ConsoleExceptionEvent.php b/vendor/symfony/console/Event/ConsoleExceptionEvent.php index 603b7eed..a31797fa 100644 --- a/vendor/symfony/console/Event/ConsoleExceptionEvent.php +++ b/vendor/symfony/console/Event/ConsoleExceptionEvent.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Console\Event; +@trigger_error(sprintf('The "%s" class is deprecated since version 3.3 and will be removed in 4.0. Use the ConsoleErrorEvent instead.', ConsoleExceptionEvent::class), E_USER_DEPRECATED); + use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -19,6 +21,8 @@ use Symfony\Component\Console\Output\OutputInterface; * Allows to handle exception thrown in a command. * * @author Fabien Potencier <fabien@symfony.com> + * + * @deprecated since version 3.3, to be removed in 4.0. Use ConsoleErrorEvent instead. */ class ConsoleExceptionEvent extends ConsoleEvent { diff --git a/vendor/symfony/console/EventListener/ErrorListener.php b/vendor/symfony/console/EventListener/ErrorListener.php new file mode 100644 index 00000000..3774f9e6 --- /dev/null +++ b/vendor/symfony/console/EventListener/ErrorListener.php @@ -0,0 +1,91 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\EventListener; + +use Psr\Log\LoggerInterface; +use Symfony\Component\Console\ConsoleEvents; +use Symfony\Component\Console\Event\ConsoleErrorEvent; +use Symfony\Component\Console\Event\ConsoleEvent; +use Symfony\Component\Console\Event\ConsoleTerminateEvent; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; + +/** + * @author James Halsall <james.t.halsall@googlemail.com> + * @author Robin Chalas <robin.chalas@gmail.com> + */ +class ErrorListener implements EventSubscriberInterface +{ + private $logger; + + public function __construct(LoggerInterface $logger = null) + { + $this->logger = $logger; + } + + public function onConsoleError(ConsoleErrorEvent $event) + { + if (null === $this->logger) { + return; + } + + $error = $event->getError(); + + if (!$inputString = $this->getInputString($event)) { + return $this->logger->error('An error occurred while using the console. Message: "{message}"', array('error' => $error, 'message' => $error->getMessage())); + } + + $this->logger->error('Error thrown while running command "{command}". Message: "{message}"', array('error' => $error, 'command' => $inputString, 'message' => $error->getMessage())); + } + + public function onConsoleTerminate(ConsoleTerminateEvent $event) + { + if (null === $this->logger) { + return; + } + + $exitCode = $event->getExitCode(); + + if (0 === $exitCode) { + return; + } + + if (!$inputString = $this->getInputString($event)) { + return $this->logger->debug('The console exited with code "{code}"', array('code' => $exitCode)); + } + + $this->logger->debug('Command "{command}" exited with code "{code}"', array('command' => $inputString, 'code' => $exitCode)); + } + + public static function getSubscribedEvents() + { + return array( + ConsoleEvents::ERROR => array('onConsoleError', -128), + ConsoleEvents::TERMINATE => array('onConsoleTerminate', -128), + ); + } + + private static function getInputString(ConsoleEvent $event) + { + $commandName = $event->getCommand() ? $event->getCommand()->getName() : null; + $input = $event->getInput(); + + if (method_exists($input, '__toString')) { + if ($commandName) { + return str_replace(array("'$commandName'", "\"$commandName\""), $commandName, (string) $input); + } + + return (string) $input; + } + + return $commandName; + } +} diff --git a/vendor/symfony/console/Exception/CommandNotFoundException.php b/vendor/symfony/console/Exception/CommandNotFoundException.php index ce6fefe3..cb7d1131 100644 --- a/vendor/symfony/console/Exception/CommandNotFoundException.php +++ b/vendor/symfony/console/Exception/CommandNotFoundException.php @@ -21,10 +21,10 @@ class CommandNotFoundException extends \InvalidArgumentException implements Exce private $alternatives; /** - * @param string $message Exception message to throw. - * @param array $alternatives List of similar defined names. - * @param int $code Exception code. - * @param Exception $previous previous exception used for the exception chaining. + * @param string $message Exception message to throw + * @param array $alternatives List of similar defined names + * @param int $code Exception code + * @param \Exception $previous Previous exception used for the exception chaining */ public function __construct($message, array $alternatives = array(), $code = 0, \Exception $previous = null) { @@ -34,7 +34,7 @@ class CommandNotFoundException extends \InvalidArgumentException implements Exce } /** - * @return array A list of similar defined names. + * @return array A list of similar defined names */ public function getAlternatives() { diff --git a/vendor/symfony/console/Formatter/OutputFormatter.php b/vendor/symfony/console/Formatter/OutputFormatter.php index 56cd5e56..3f3ebfbc 100644 --- a/vendor/symfony/console/Formatter/OutputFormatter.php +++ b/vendor/symfony/console/Formatter/OutputFormatter.php @@ -35,10 +35,25 @@ class OutputFormatter implements OutputFormatterInterface { $text = preg_replace('/([^\\\\]?)</', '$1\\<', $text); + return self::escapeTrailingBackslash($text); + } + + /** + * Escapes trailing "\" in given text. + * + * @param string $text Text to escape + * + * @return string Escaped text + * + * @internal + */ + public static function escapeTrailingBackslash($text) + { if ('\\' === substr($text, -1)) { $len = strlen($text); $text = rtrim($text, '\\'); - $text .= str_repeat('<<', $len - strlen($text)); + $text = str_replace("\0", '', $text); + $text .= str_repeat("\0", $len - strlen($text)); } return $text; @@ -67,9 +82,7 @@ class OutputFormatter implements OutputFormatterInterface } /** - * Sets the decorated flag. - * - * @param bool $decorated Whether to decorate the messages or not + * {@inheritdoc} */ public function setDecorated($decorated) { @@ -77,9 +90,7 @@ class OutputFormatter implements OutputFormatterInterface } /** - * Gets the decorated flag. - * - * @return bool true if the output will decorate messages, false otherwise + * {@inheritdoc} */ public function isDecorated() { @@ -87,10 +98,7 @@ class OutputFormatter implements OutputFormatterInterface } /** - * Sets a new style. - * - * @param string $name The style name - * @param OutputFormatterStyleInterface $style The style instance + * {@inheritdoc} */ public function setStyle($name, OutputFormatterStyleInterface $style) { @@ -98,11 +106,7 @@ class OutputFormatter implements OutputFormatterInterface } /** - * Checks if output formatter has style with specified name. - * - * @param string $name - * - * @return bool + * {@inheritdoc} */ public function hasStyle($name) { @@ -110,13 +114,7 @@ class OutputFormatter implements OutputFormatterInterface } /** - * Gets style options from style with specified name. - * - * @param string $name - * - * @return OutputFormatterStyleInterface - * - * @throws InvalidArgumentException When style isn't defined + * {@inheritdoc} */ public function getStyle($name) { @@ -128,18 +126,14 @@ class OutputFormatter implements OutputFormatterInterface } /** - * Formats a message according to the given styles. - * - * @param string $message The message to style - * - * @return string The styled message + * {@inheritdoc} */ public function format($message) { $message = (string) $message; $offset = 0; $output = ''; - $tagRegex = '[a-z][a-z0-9_=;-]*+'; + $tagRegex = '[a-z][a-z0-9,_=;-]*+'; preg_match_all("#<(($tagRegex) | /($tagRegex)?)>#ix", $message, $matches, PREG_OFFSET_CAPTURE); foreach ($matches[0] as $i => $match) { $pos = $match[1]; @@ -174,8 +168,8 @@ class OutputFormatter implements OutputFormatterInterface $output .= $this->applyCurrentStyle(substr($message, $offset)); - if (false !== strpos($output, '<<')) { - return strtr($output, array('\\<' => '<', '<<' => '\\')); + if (false !== strpos($output, "\0")) { + return strtr($output, array("\0" => '\\', '\\<' => '<')); } return str_replace('\\<', '<', $output); @@ -194,7 +188,7 @@ class OutputFormatter implements OutputFormatterInterface * * @param string $string * - * @return OutputFormatterStyle|bool false if string is not format string + * @return OutputFormatterStyle|false false if string is not format string */ private function createStyleFromString($string) { @@ -202,7 +196,7 @@ class OutputFormatter implements OutputFormatterInterface return $this->styles[$string]; } - if (!preg_match_all('/([^=]+)=([^;]+)(;|$)/', strtolower($string), $matches, PREG_SET_ORDER)) { + if (!preg_match_all('/([^=]+)=([^;]+)(;|$)/', $string, $matches, PREG_SET_ORDER)) { return false; } @@ -214,12 +208,20 @@ class OutputFormatter implements OutputFormatterInterface $style->setForeground($match[1]); } elseif ('bg' == $match[0]) { $style->setBackground($match[1]); - } else { - try { - $style->setOption($match[1]); - } catch (\InvalidArgumentException $e) { - return false; + } elseif ('options' === $match[0]) { + preg_match_all('([^,;]+)', $match[1], $options); + $options = array_shift($options); + foreach ($options as $option) { + try { + $style->setOption($option); + } catch (\InvalidArgumentException $e) { + @trigger_error(sprintf('Unknown style options are deprecated since version 3.2 and will be removed in 4.0. Exception "%s".', $e->getMessage()), E_USER_DEPRECATED); + + return false; + } } + } else { + return false; } } diff --git a/vendor/symfony/console/Formatter/OutputFormatterInterface.php b/vendor/symfony/console/Formatter/OutputFormatterInterface.php index 5a52ba09..281e240c 100644 --- a/vendor/symfony/console/Formatter/OutputFormatterInterface.php +++ b/vendor/symfony/console/Formatter/OutputFormatterInterface.php @@ -55,6 +55,8 @@ interface OutputFormatterInterface * @param string $name * * @return OutputFormatterStyleInterface + * + * @throws \InvalidArgumentException When style isn't defined */ public function getStyle($name); diff --git a/vendor/symfony/console/Formatter/OutputFormatterStyle.php b/vendor/symfony/console/Formatter/OutputFormatterStyle.php index c7c6b4a0..7ada54f4 100644 --- a/vendor/symfony/console/Formatter/OutputFormatterStyle.php +++ b/vendor/symfony/console/Formatter/OutputFormatterStyle.php @@ -172,9 +172,7 @@ class OutputFormatterStyle implements OutputFormatterStyleInterface } /** - * Sets multiple style options at once. - * - * @param array $options + * {@inheritdoc} */ public function setOptions(array $options) { diff --git a/vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php b/vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php index c36fda80..4c7dc413 100644 --- a/vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php +++ b/vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php @@ -48,8 +48,6 @@ interface OutputFormatterStyleInterface /** * Sets multiple style options at once. - * - * @param array $options */ public function setOptions(array $options); diff --git a/vendor/symfony/console/Formatter/OutputFormatterStyleStack.php b/vendor/symfony/console/Formatter/OutputFormatterStyleStack.php index e5d14ea3..bf0beb70 100644 --- a/vendor/symfony/console/Formatter/OutputFormatterStyleStack.php +++ b/vendor/symfony/console/Formatter/OutputFormatterStyleStack.php @@ -23,16 +23,8 @@ class OutputFormatterStyleStack */ private $styles; - /** - * @var OutputFormatterStyleInterface - */ private $emptyStyle; - /** - * Constructor. - * - * @param OutputFormatterStyleInterface|null $emptyStyle - */ public function __construct(OutputFormatterStyleInterface $emptyStyle = null) { $this->emptyStyle = $emptyStyle ?: new OutputFormatterStyle(); @@ -49,8 +41,6 @@ class OutputFormatterStyleStack /** * Pushes a style in the stack. - * - * @param OutputFormatterStyleInterface $style */ public function push(OutputFormatterStyleInterface $style) { @@ -60,8 +50,6 @@ class OutputFormatterStyleStack /** * Pops a style from the stack. * - * @param OutputFormatterStyleInterface|null $style - * * @return OutputFormatterStyleInterface * * @throws InvalidArgumentException When style tags incorrectly nested @@ -102,9 +90,7 @@ class OutputFormatterStyleStack } /** - * @param OutputFormatterStyleInterface $emptyStyle - * - * @return OutputFormatterStyleStack + * @return $this */ public function setEmptyStyle(OutputFormatterStyleInterface $emptyStyle) { diff --git a/vendor/symfony/console/Helper/DescriptorHelper.php b/vendor/symfony/console/Helper/DescriptorHelper.php index a53b476b..6f5c8183 100644 --- a/vendor/symfony/console/Helper/DescriptorHelper.php +++ b/vendor/symfony/console/Helper/DescriptorHelper.php @@ -31,9 +31,6 @@ class DescriptorHelper extends Helper */ private $descriptors = array(); - /** - * Constructor. - */ public function __construct() { $this @@ -78,7 +75,7 @@ class DescriptorHelper extends Helper * @param string $format * @param DescriptorInterface $descriptor * - * @return DescriptorHelper + * @return $this */ public function register($format, DescriptorInterface $descriptor) { diff --git a/vendor/symfony/console/Helper/DialogHelper.php b/vendor/symfony/console/Helper/DialogHelper.php deleted file mode 100644 index 9ce9f661..00000000 --- a/vendor/symfony/console/Helper/DialogHelper.php +++ /dev/null @@ -1,502 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Exception\RuntimeException; -use Symfony\Component\Console\Output\ConsoleOutputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Formatter\OutputFormatterStyle; - -/** - * The Dialog class provides helpers to interact with the user. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @deprecated since version 2.5, to be removed in 3.0. - * Use {@link \Symfony\Component\Console\Helper\QuestionHelper} instead. - */ -class DialogHelper extends InputAwareHelper -{ - private $inputStream; - private static $shell; - private static $stty; - - public function __construct($triggerDeprecationError = true) - { - if ($triggerDeprecationError) { - @trigger_error('"Symfony\Component\Console\Helper\DialogHelper" is deprecated since version 2.5 and will be removed in 3.0. Use "Symfony\Component\Console\Helper\QuestionHelper" instead.', E_USER_DEPRECATED); - } - } - - /** - * Asks the user to select a value. - * - * @param OutputInterface $output An Output instance - * @param string|array $question The question to ask - * @param array $choices List of choices to pick from - * @param bool|string $default The default answer if the user enters nothing - * @param bool|int $attempts Max number of times to ask before giving up (false by default, which means infinite) - * @param string $errorMessage Message which will be shown if invalid value from choice list would be picked - * @param bool $multiselect Select more than one value separated by comma - * - * @return int|string|array The selected value or values (the key of the choices array) - * - * @throws InvalidArgumentException - */ - public function select(OutputInterface $output, $question, $choices, $default = null, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false) - { - if ($output instanceof ConsoleOutputInterface) { - $output = $output->getErrorOutput(); - } - - $width = max(array_map('strlen', array_keys($choices))); - - $messages = (array) $question; - foreach ($choices as $key => $value) { - $messages[] = sprintf(" [<info>%-{$width}s</info>] %s", $key, $value); - } - - $output->writeln($messages); - - $result = $this->askAndValidate($output, '> ', function ($picked) use ($choices, $errorMessage, $multiselect) { - // Collapse all spaces. - $selectedChoices = str_replace(' ', '', $picked); - - if ($multiselect) { - // Check for a separated comma values - if (!preg_match('/^[a-zA-Z0-9_-]+(?:,[a-zA-Z0-9_-]+)*$/', $selectedChoices, $matches)) { - throw new InvalidArgumentException(sprintf($errorMessage, $picked)); - } - $selectedChoices = explode(',', $selectedChoices); - } else { - $selectedChoices = array($picked); - } - - $multiselectChoices = array(); - - foreach ($selectedChoices as $value) { - if (empty($choices[$value])) { - throw new InvalidArgumentException(sprintf($errorMessage, $value)); - } - $multiselectChoices[] = $value; - } - - if ($multiselect) { - return $multiselectChoices; - } - - return $picked; - }, $attempts, $default); - - return $result; - } - - /** - * Asks a question to the user. - * - * @param OutputInterface $output An Output instance - * @param string|array $question The question to ask - * @param string $default The default answer if none is given by the user - * @param array $autocomplete List of values to autocomplete - * - * @return string The user answer - * - * @throws RuntimeException If there is no data to read in the input stream - */ - public function ask(OutputInterface $output, $question, $default = null, array $autocomplete = null) - { - if ($this->input && !$this->input->isInteractive()) { - return $default; - } - - if ($output instanceof ConsoleOutputInterface) { - $output = $output->getErrorOutput(); - } - - $output->write($question); - - $inputStream = $this->inputStream ?: STDIN; - - if (null === $autocomplete || !$this->hasSttyAvailable()) { - $ret = fgets($inputStream, 4096); - if (false === $ret) { - throw new RuntimeException('Aborted'); - } - $ret = trim($ret); - } else { - $ret = ''; - - $i = 0; - $ofs = -1; - $matches = $autocomplete; - $numMatches = count($matches); - - $sttyMode = shell_exec('stty -g'); - - // Disable icanon (so we can fread each keypress) and echo (we'll do echoing here instead) - shell_exec('stty -icanon -echo'); - - // Add highlighted text style - $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white')); - - // Read a keypress - while (!feof($inputStream)) { - $c = fread($inputStream, 1); - - // Backspace Character - if ("\177" === $c) { - if (0 === $numMatches && 0 !== $i) { - --$i; - // Move cursor backwards - $output->write("\033[1D"); - } - - if ($i === 0) { - $ofs = -1; - $matches = $autocomplete; - $numMatches = count($matches); - } else { - $numMatches = 0; - } - - // Pop the last character off the end of our string - $ret = substr($ret, 0, $i); - } elseif ("\033" === $c) { - // Did we read an escape sequence? - $c .= fread($inputStream, 2); - - // A = Up Arrow. B = Down Arrow - if (isset($c[2]) && ('A' === $c[2] || 'B' === $c[2])) { - if ('A' === $c[2] && -1 === $ofs) { - $ofs = 0; - } - - if (0 === $numMatches) { - continue; - } - - $ofs += ('A' === $c[2]) ? -1 : 1; - $ofs = ($numMatches + $ofs) % $numMatches; - } - } elseif (ord($c) < 32) { - if ("\t" === $c || "\n" === $c) { - if ($numMatches > 0 && -1 !== $ofs) { - $ret = $matches[$ofs]; - // Echo out remaining chars for current match - $output->write(substr($ret, $i)); - $i = strlen($ret); - } - - if ("\n" === $c) { - $output->write($c); - break; - } - - $numMatches = 0; - } - - continue; - } else { - $output->write($c); - $ret .= $c; - ++$i; - - $numMatches = 0; - $ofs = 0; - - foreach ($autocomplete as $value) { - // If typed characters match the beginning chunk of value (e.g. [AcmeDe]moBundle) - if (0 === strpos($value, $ret) && $i !== strlen($value)) { - $matches[$numMatches++] = $value; - } - } - } - - // Erase characters from cursor to end of line - $output->write("\033[K"); - - if ($numMatches > 0 && -1 !== $ofs) { - // Save cursor position - $output->write("\0337"); - // Write highlighted text - $output->write('<hl>'.substr($matches[$ofs], $i).'</hl>'); - // Restore cursor position - $output->write("\0338"); - } - } - - // Reset stty so it behaves normally again - shell_exec(sprintf('stty %s', $sttyMode)); - } - - return strlen($ret) > 0 ? $ret : $default; - } - - /** - * Asks a confirmation to the user. - * - * The question will be asked until the user answers by nothing, yes, or no. - * - * @param OutputInterface $output An Output instance - * @param string|array $question The question to ask - * @param bool $default The default answer if the user enters nothing - * - * @return bool true if the user has confirmed, false otherwise - */ - public function askConfirmation(OutputInterface $output, $question, $default = true) - { - $answer = 'z'; - while ($answer && !in_array(strtolower($answer[0]), array('y', 'n'))) { - $answer = $this->ask($output, $question); - } - - if (false === $default) { - return $answer && 'y' == strtolower($answer[0]); - } - - return !$answer || 'y' == strtolower($answer[0]); - } - - /** - * Asks a question to the user, the response is hidden. - * - * @param OutputInterface $output An Output instance - * @param string|array $question The question - * @param bool $fallback In case the response can not be hidden, whether to fallback on non-hidden question or not - * - * @return string The answer - * - * @throws RuntimeException In case the fallback is deactivated and the response can not be hidden - */ - public function askHiddenResponse(OutputInterface $output, $question, $fallback = true) - { - if ($output instanceof ConsoleOutputInterface) { - $output = $output->getErrorOutput(); - } - - if ('\\' === DIRECTORY_SEPARATOR) { - $exe = __DIR__.'/../Resources/bin/hiddeninput.exe'; - - // handle code running from a phar - if ('phar:' === substr(__FILE__, 0, 5)) { - $tmpExe = sys_get_temp_dir().'/hiddeninput.exe'; - copy($exe, $tmpExe); - $exe = $tmpExe; - } - - $output->write($question); - $value = rtrim(shell_exec($exe)); - $output->writeln(''); - - if (isset($tmpExe)) { - unlink($tmpExe); - } - - return $value; - } - - if ($this->hasSttyAvailable()) { - $output->write($question); - - $sttyMode = shell_exec('stty -g'); - - shell_exec('stty -echo'); - $value = fgets($this->inputStream ?: STDIN, 4096); - shell_exec(sprintf('stty %s', $sttyMode)); - - if (false === $value) { - throw new RuntimeException('Aborted'); - } - - $value = trim($value); - $output->writeln(''); - - return $value; - } - - if (false !== $shell = $this->getShell()) { - $output->write($question); - $readCmd = $shell === 'csh' ? 'set mypassword = $<' : 'read -r mypassword'; - $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd); - $value = rtrim(shell_exec($command)); - $output->writeln(''); - - return $value; - } - - if ($fallback) { - return $this->ask($output, $question); - } - - throw new RuntimeException('Unable to hide the response'); - } - - /** - * Asks for a value and validates the response. - * - * The validator receives the data to validate. It must return the - * validated data when the data is valid and throw an exception - * otherwise. - * - * @param OutputInterface $output An Output instance - * @param string|array $question The question to ask - * @param callable $validator A PHP callback - * @param int|false $attempts Max number of times to ask before giving up (false by default, which means infinite) - * @param string $default The default answer if none is given by the user - * @param array $autocomplete List of values to autocomplete - * - * @return mixed - * - * @throws \Exception When any of the validators return an error - */ - public function askAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $default = null, array $autocomplete = null) - { - $that = $this; - - $interviewer = function () use ($output, $question, $default, $autocomplete, $that) { - return $that->ask($output, $question, $default, $autocomplete); - }; - - return $this->validateAttempts($interviewer, $output, $validator, $attempts); - } - - /** - * Asks for a value, hide and validates the response. - * - * The validator receives the data to validate. It must return the - * validated data when the data is valid and throw an exception - * otherwise. - * - * @param OutputInterface $output An Output instance - * @param string|array $question The question to ask - * @param callable $validator A PHP callback - * @param int|false $attempts Max number of times to ask before giving up (false by default, which means infinite) - * @param bool $fallback In case the response can not be hidden, whether to fallback on non-hidden question or not - * - * @return string The response - * - * @throws \Exception When any of the validators return an error - * @throws RuntimeException In case the fallback is deactivated and the response can not be hidden - */ - public function askHiddenResponseAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $fallback = true) - { - $that = $this; - - $interviewer = function () use ($output, $question, $fallback, $that) { - return $that->askHiddenResponse($output, $question, $fallback); - }; - - return $this->validateAttempts($interviewer, $output, $validator, $attempts); - } - - /** - * Sets the input stream to read from when interacting with the user. - * - * This is mainly useful for testing purpose. - * - * @param resource $stream The input stream - */ - public function setInputStream($stream) - { - $this->inputStream = $stream; - } - - /** - * Returns the helper's input stream. - * - * @return resource|null The input stream or null if the default STDIN is used - */ - public function getInputStream() - { - return $this->inputStream; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return 'dialog'; - } - - /** - * Return a valid Unix shell. - * - * @return string|bool The valid shell name, false in case no valid shell is found - */ - private function getShell() - { - if (null !== self::$shell) { - return self::$shell; - } - - self::$shell = false; - - if (file_exists('/usr/bin/env')) { - // handle other OSs with bash/zsh/ksh/csh if available to hide the answer - $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null"; - foreach (array('bash', 'zsh', 'ksh', 'csh') as $sh) { - if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) { - self::$shell = $sh; - break; - } - } - } - - return self::$shell; - } - - private function hasSttyAvailable() - { - if (null !== self::$stty) { - return self::$stty; - } - - exec('stty 2>&1', $output, $exitcode); - - return self::$stty = $exitcode === 0; - } - - /** - * Validate an attempt. - * - * @param callable $interviewer A callable that will ask for a question and return the result - * @param OutputInterface $output An Output instance - * @param callable $validator A PHP callback - * @param int|false $attempts Max number of times to ask before giving up; false will ask infinitely - * - * @return string The validated response - * - * @throws \Exception In case the max number of attempts has been reached and no valid response has been given - */ - private function validateAttempts($interviewer, OutputInterface $output, $validator, $attempts) - { - if ($output instanceof ConsoleOutputInterface) { - $output = $output->getErrorOutput(); - } - - $e = null; - while (false === $attempts || $attempts--) { - if (null !== $e) { - $output->writeln($this->getHelperSet()->get('formatter')->formatBlock($e->getMessage(), 'error')); - } - - try { - return call_user_func($validator, $interviewer()); - } catch (\Exception $e) { - } - } - - throw $e; - } -} diff --git a/vendor/symfony/console/Helper/FormatterHelper.php b/vendor/symfony/console/Helper/FormatterHelper.php index ac736f98..6a48a77f 100644 --- a/vendor/symfony/console/Helper/FormatterHelper.php +++ b/vendor/symfony/console/Helper/FormatterHelper.php @@ -73,6 +73,30 @@ class FormatterHelper extends Helper } /** + * Truncates a message to the given length. + * + * @param string $message + * @param int $length + * @param string $suffix + * + * @return string + */ + public function truncate($message, $length, $suffix = '...') + { + $computedLength = $length - $this->strlen($suffix); + + if ($computedLength > $this->strlen($message)) { + return $message; + } + + if (false === $encoding = mb_detect_encoding($message, null, true)) { + return substr($message, 0, $length).$suffix; + } + + return mb_substr($message, 0, $length, $encoding).$suffix; + } + + /** * {@inheritdoc} */ public function getName() diff --git a/vendor/symfony/console/Helper/Helper.php b/vendor/symfony/console/Helper/Helper.php index 43f9a169..0954bad6 100644 --- a/vendor/symfony/console/Helper/Helper.php +++ b/vendor/symfony/console/Helper/Helper.php @@ -23,9 +23,7 @@ abstract class Helper implements HelperInterface protected $helperSet = null; /** - * Sets the helper set associated with this helper. - * - * @param HelperSet $helperSet A HelperSet instance + * {@inheritdoc} */ public function setHelperSet(HelperSet $helperSet = null) { @@ -33,9 +31,7 @@ abstract class Helper implements HelperInterface } /** - * Gets the helper set associated with this helper. - * - * @return HelperSet A HelperSet instance + * {@inheritdoc} */ public function getHelperSet() { @@ -58,6 +54,24 @@ abstract class Helper implements HelperInterface return mb_strwidth($string, $encoding); } + /** + * Returns the subset of a string, using mb_substr if it is available. + * + * @param string $string String to subset + * @param int $from Start offset + * @param int|null $length Length to read + * + * @return string The string subset + */ + public static function substr($string, $from, $length = null) + { + if (false === $encoding = mb_detect_encoding($string, null, true)) { + return substr($string, $from, $length); + } + + return mb_substr($string, $from, $length, $encoding); + } + public static function formatTime($secs) { static $timeFormats = array( @@ -106,6 +120,11 @@ abstract class Helper implements HelperInterface public static function strlenWithoutDecoration(OutputFormatterInterface $formatter, $string) { + return self::strlen(self::removeDecoration($formatter, $string)); + } + + public static function removeDecoration(OutputFormatterInterface $formatter, $string) + { $isDecorated = $formatter->isDecorated(); $formatter->setDecorated(false); // remove <...> formatting @@ -114,6 +133,6 @@ abstract class Helper implements HelperInterface $string = preg_replace("/\033\[[^m]*m/", '', $string); $formatter->setDecorated($isDecorated); - return self::strlen($string); + return $string; } } diff --git a/vendor/symfony/console/Helper/HelperInterface.php b/vendor/symfony/console/Helper/HelperInterface.php index 5a923e0a..1ce82358 100644 --- a/vendor/symfony/console/Helper/HelperInterface.php +++ b/vendor/symfony/console/Helper/HelperInterface.php @@ -20,8 +20,6 @@ interface HelperInterface { /** * Sets the helper set associated with this helper. - * - * @param HelperSet $helperSet A HelperSet instance */ public function setHelperSet(HelperSet $helperSet = null); diff --git a/vendor/symfony/console/Helper/HelperSet.php b/vendor/symfony/console/Helper/HelperSet.php index 27fedcf7..24ce18fb 100644 --- a/vendor/symfony/console/Helper/HelperSet.php +++ b/vendor/symfony/console/Helper/HelperSet.php @@ -21,13 +21,14 @@ use Symfony\Component\Console\Exception\InvalidArgumentException; */ class HelperSet implements \IteratorAggregate { + /** + * @var Helper[] + */ private $helpers = array(); private $command; /** - * Constructor. - * - * @param Helper[] $helpers An array of helper. + * @param Helper[] $helpers An array of helper */ public function __construct(array $helpers = array()) { @@ -79,22 +80,9 @@ class HelperSet implements \IteratorAggregate throw new InvalidArgumentException(sprintf('The helper "%s" is not defined.', $name)); } - if ('dialog' === $name && $this->helpers[$name] instanceof DialogHelper) { - @trigger_error('"Symfony\Component\Console\Helper\DialogHelper" is deprecated since version 2.5 and will be removed in 3.0. Use "Symfony\Component\Console\Helper\QuestionHelper" instead.', E_USER_DEPRECATED); - } elseif ('progress' === $name && $this->helpers[$name] instanceof ProgressHelper) { - @trigger_error('"Symfony\Component\Console\Helper\ProgressHelper" is deprecated since version 2.5 and will be removed in 3.0. Use "Symfony\Component\Console\Helper\ProgressBar" instead.', E_USER_DEPRECATED); - } elseif ('table' === $name && $this->helpers[$name] instanceof TableHelper) { - @trigger_error('"Symfony\Component\Console\Helper\TableHelper" is deprecated since version 2.5 and will be removed in 3.0. Use "Symfony\Component\Console\Helper\Table" instead.', E_USER_DEPRECATED); - } - return $this->helpers[$name]; } - /** - * Sets the command associated with this helper set. - * - * @param Command $command A Command instance - */ public function setCommand(Command $command = null) { $this->command = $command; @@ -110,6 +98,9 @@ class HelperSet implements \IteratorAggregate return $this->command; } + /** + * @return Helper[] + */ public function getIterator() { return new \ArrayIterator($this->helpers); diff --git a/vendor/symfony/console/Helper/ProcessHelper.php b/vendor/symfony/console/Helper/ProcessHelper.php index a811eb48..82935bae 100644 --- a/vendor/symfony/console/Helper/ProcessHelper.php +++ b/vendor/symfony/console/Helper/ProcessHelper.php @@ -15,7 +15,6 @@ use Symfony\Component\Console\Output\ConsoleOutputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Process\Exception\ProcessFailedException; use Symfony\Component\Process\Process; -use Symfony\Component\Process\ProcessBuilder; /** * The ProcessHelper class provides helpers to run external processes. @@ -36,7 +35,7 @@ class ProcessHelper extends Helper * * @return Process The process that ran */ - public function run(OutputInterface $output, $cmd, $error = null, $callback = null, $verbosity = OutputInterface::VERBOSITY_VERY_VERBOSE) + public function run(OutputInterface $output, $cmd, $error = null, callable $callback = null, $verbosity = OutputInterface::VERBOSITY_VERY_VERBOSE) { if ($output instanceof ConsoleOutputInterface) { $output = $output->getErrorOutput(); @@ -44,9 +43,7 @@ class ProcessHelper extends Helper $formatter = $this->getHelperSet()->get('debug_formatter'); - if (is_array($cmd)) { - $process = ProcessBuilder::create($cmd)->getProcess(); - } elseif ($cmd instanceof Process) { + if ($cmd instanceof Process) { $process = $cmd; } else { $process = new Process($cmd); @@ -92,7 +89,7 @@ class ProcessHelper extends Helper * * @see run() */ - public function mustRun(OutputInterface $output, $cmd, $error = null, $callback = null) + public function mustRun(OutputInterface $output, $cmd, $error = null, callable $callback = null) { $process = $this->run($output, $cmd, $error, $callback); @@ -112,7 +109,7 @@ class ProcessHelper extends Helper * * @return callable */ - public function wrapCallback(OutputInterface $output, Process $process, $callback = null) + public function wrapCallback(OutputInterface $output, Process $process, callable $callback = null) { if ($output instanceof ConsoleOutputInterface) { $output = $output->getErrorOutput(); @@ -120,10 +117,8 @@ class ProcessHelper extends Helper $formatter = $this->getHelperSet()->get('debug_formatter'); - $that = $this; - - return function ($type, $buffer) use ($output, $process, $callback, $formatter, $that) { - $output->write($formatter->progress(spl_object_hash($process), $that->escapeString($buffer), Process::ERR === $type)); + return function ($type, $buffer) use ($output, $process, $callback, $formatter) { + $output->write($formatter->progress(spl_object_hash($process), $this->escapeString($buffer), Process::ERR === $type)); if (null !== $callback) { call_user_func($callback, $type, $buffer); @@ -131,12 +126,7 @@ class ProcessHelper extends Helper }; } - /** - * This method is public for PHP 5.3 compatibility, it should be private. - * - * @internal - */ - public function escapeString($str) + private function escapeString($str) { return str_replace('<', '\\<', $str); } diff --git a/vendor/symfony/console/Helper/ProgressBar.php b/vendor/symfony/console/Helper/ProgressBar.php index e7717a52..247b5913 100644 --- a/vendor/symfony/console/Helper/ProgressBar.php +++ b/vendor/symfony/console/Helper/ProgressBar.php @@ -14,6 +14,7 @@ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Output\ConsoleOutputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Exception\LogicException; +use Symfony\Component\Console\Terminal; /** * The ProgressBar provides helpers to display progress output. @@ -21,9 +22,8 @@ use Symfony\Component\Console\Exception\LogicException; * @author Fabien Potencier <fabien@symfony.com> * @author Chris Jones <leeked@gmail.com> */ -class ProgressBar +final class ProgressBar { - // options private $barWidth = 28; private $barChar; private $emptyBarChar = '-'; @@ -31,10 +31,6 @@ class ProgressBar private $format; private $internalFormat; private $redrawFreq = 1; - - /** - * @var OutputInterface - */ private $output; private $step = 0; private $max; @@ -42,15 +38,15 @@ class ProgressBar private $stepWidth; private $percent = 0.0; private $formatLineCount; - private $messages; + private $messages = array(); private $overwrite = true; + private $terminal; + private $firstRun = true; private static $formatters; private static $formats; /** - * Constructor. - * * @param OutputInterface $output An OutputInterface instance * @param int $max Maximum steps (0 if unknown) */ @@ -62,6 +58,7 @@ class ProgressBar $this->output = $output; $this->setMaxSteps($max); + $this->terminal = new Terminal(); if (!$this->output->isDecorated()) { // disable overwrite when output does not support ANSI codes. @@ -82,7 +79,7 @@ class ProgressBar * @param string $name The placeholder name (including the delimiter char like %) * @param callable $callable A PHP callable */ - public static function setPlaceholderFormatterDefinition($name, $callable) + public static function setPlaceholderFormatterDefinition($name, callable $callable) { if (!self::$formatters) { self::$formatters = self::initPlaceholderFormatters(); @@ -140,6 +137,16 @@ class ProgressBar return isset(self::$formats[$name]) ? self::$formats[$name] : null; } + /** + * Associates a text with a named placeholder. + * + * The text is displayed when the progress bar is rendered but only + * when the corresponding placeholder is part of the custom format line + * (by wrapping the name with %). + * + * @param string $message The text to associate with the placeholder + * @param string $name The name of the placeholder + */ public function setMessage($message, $name = 'message') { $this->messages[$name] = $message; @@ -171,20 +178,6 @@ class ProgressBar } /** - * Gets the progress bar step. - * - * @deprecated since version 2.6, to be removed in 3.0. Use {@link getProgress()} instead. - * - * @return int The progress bar step - */ - public function getStep() - { - @trigger_error('The '.__METHOD__.' method is deprecated since version 2.6 and will be removed in 3.0. Use the getProgress() method instead.', E_USER_DEPRECATED); - - return $this->getProgress(); - } - - /** * Gets the current step position. * * @return int The progress bar step @@ -197,11 +190,9 @@ class ProgressBar /** * Gets the progress bar step width. * - * @internal This method is public for PHP 5.3 compatibility, it should not be used. - * * @return int The progress bar step width */ - public function getStepWidth() + private function getStepWidth() { return $this->stepWidth; } @@ -223,7 +214,7 @@ class ProgressBar */ public function setBarWidth($size) { - $this->barWidth = (int) $size; + $this->barWidth = max(1, (int) $size); } /** @@ -343,8 +334,6 @@ class ProgressBar * Advances the progress output X steps. * * @param int $step Number of steps to advance - * - * @throws LogicException */ public function advance($step = 1) { @@ -352,22 +341,6 @@ class ProgressBar } /** - * Sets the current progress. - * - * @deprecated since version 2.6, to be removed in 3.0. Use {@link setProgress()} instead. - * - * @param int $step The current progress - * - * @throws LogicException - */ - public function setCurrent($step) - { - @trigger_error('The '.__METHOD__.' method is deprecated since version 2.6 and will be removed in 3.0. Use the setProgress() method instead.', E_USER_DEPRECATED); - - $this->setProgress($step); - } - - /** * Sets whether to overwrite the progressbar, false for new line. * * @param bool $overwrite @@ -381,18 +354,15 @@ class ProgressBar * Sets the current progress. * * @param int $step The current progress - * - * @throws LogicException */ public function setProgress($step) { $step = (int) $step; - if ($step < $this->step) { - throw new LogicException('You can\'t regress the progress bar.'); - } if ($this->max && $step > $this->max) { $this->max = $step; + } elseif ($step < 0) { + $step = 0; } $prevPeriod = (int) ($this->step / $this->redrawFreq); @@ -434,25 +404,7 @@ class ProgressBar $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat()); } - // these 3 variables can be removed in favor of using $this in the closure when support for PHP 5.3 will be dropped. - $self = $this; - $output = $this->output; - $messages = $this->messages; - $this->overwrite(preg_replace_callback("{%([a-z\-_]+)(?:\:([^%]+))?%}i", function ($matches) use ($self, $output, $messages) { - if ($formatter = $self::getPlaceholderFormatterDefinition($matches[1])) { - $text = call_user_func($formatter, $self, $output); - } elseif (isset($messages[$matches[1]])) { - $text = $messages[$matches[1]]; - } else { - return $matches[0]; - } - - if (isset($matches[2])) { - $text = sprintf('%'.$matches[2], $text); - } - - return $text; - }, $this->format)); + $this->overwrite($this->buildLine()); } /** @@ -513,20 +465,24 @@ class ProgressBar private function overwrite($message) { if ($this->overwrite) { - // Move the cursor to the beginning of the line - $this->output->write("\x0D"); + if (!$this->firstRun) { + // Move the cursor to the beginning of the line + $this->output->write("\x0D"); - // Erase the line - $this->output->write("\x1B[2K"); + // Erase the line + $this->output->write("\x1B[2K"); - // Erase previous lines - if ($this->formatLineCount > 0) { - $this->output->write(str_repeat("\x1B[1A\x1B[2K", $this->formatLineCount)); + // Erase previous lines + if ($this->formatLineCount > 0) { + $this->output->write(str_repeat("\x1B[1A\x1B[2K", $this->formatLineCount)); + } } } elseif ($this->step > 0) { $this->output->writeln(''); } + $this->firstRun = false; + $this->output->write($message); } @@ -618,4 +574,44 @@ class ProgressBar 'debug_nomax' => ' %current% [%bar%] %elapsed:6s% %memory:6s%', ); } + + /** + * @return string + */ + private function buildLine() + { + $regex = "{%([a-z\-_]+)(?:\:([^%]+))?%}i"; + $callback = function ($matches) { + if ($formatter = $this::getPlaceholderFormatterDefinition($matches[1])) { + $text = call_user_func($formatter, $this, $this->output); + } elseif (isset($this->messages[$matches[1]])) { + $text = $this->messages[$matches[1]]; + } else { + return $matches[0]; + } + + if (isset($matches[2])) { + $text = sprintf('%'.$matches[2], $text); + } + + return $text; + }; + $line = preg_replace_callback($regex, $callback, $this->format); + + // gets string length for each sub line with multiline format + $linesLength = array_map(function ($subLine) { + return Helper::strlenWithoutDecoration($this->output->getFormatter(), rtrim($subLine, "\r")); + }, explode("\n", $line)); + + $linesWidth = max($linesLength); + + $terminalWidth = $this->terminal->getWidth(); + if ($linesWidth <= $terminalWidth) { + return $line; + } + + $this->setBarWidth($this->barWidth - $linesWidth + $terminalWidth); + + return preg_replace_callback($regex, $callback, $this->format); + } } diff --git a/vendor/symfony/console/Helper/ProgressHelper.php b/vendor/symfony/console/Helper/ProgressHelper.php deleted file mode 100644 index 96b6202c..00000000 --- a/vendor/symfony/console/Helper/ProgressHelper.php +++ /dev/null @@ -1,471 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -use Symfony\Component\Console\Output\NullOutput; -use Symfony\Component\Console\Output\ConsoleOutputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Exception\LogicException; - -/** - * The Progress class provides helpers to display progress output. - * - * @author Chris Jones <leeked@gmail.com> - * @author Fabien Potencier <fabien@symfony.com> - * - * @deprecated since version 2.5, to be removed in 3.0 - * Use {@link ProgressBar} instead. - */ -class ProgressHelper extends Helper -{ - const FORMAT_QUIET = ' %percent%%'; - const FORMAT_NORMAL = ' %current%/%max% [%bar%] %percent%%'; - const FORMAT_VERBOSE = ' %current%/%max% [%bar%] %percent%% Elapsed: %elapsed%'; - const FORMAT_QUIET_NOMAX = ' %current%'; - const FORMAT_NORMAL_NOMAX = ' %current% [%bar%]'; - const FORMAT_VERBOSE_NOMAX = ' %current% [%bar%] Elapsed: %elapsed%'; - - // options - private $barWidth = 28; - private $barChar = '='; - private $emptyBarChar = '-'; - private $progressChar = '>'; - private $format = null; - private $redrawFreq = 1; - - private $lastMessagesLength; - private $barCharOriginal; - - /** - * @var OutputInterface - */ - private $output; - - /** - * Current step. - * - * @var int - */ - private $current; - - /** - * Maximum number of steps. - * - * @var int - */ - private $max; - - /** - * Start time of the progress bar. - * - * @var int - */ - private $startTime; - - /** - * List of formatting variables. - * - * @var array - */ - private $defaultFormatVars = array( - 'current', - 'max', - 'bar', - 'percent', - 'elapsed', - ); - - /** - * Available formatting variables. - * - * @var array - */ - private $formatVars; - - /** - * Stored format part widths (used for padding). - * - * @var array - */ - private $widths = array( - 'current' => 4, - 'max' => 4, - 'percent' => 3, - 'elapsed' => 6, - ); - - /** - * Various time formats. - * - * @var array - */ - private $timeFormats = array( - array(0, '???'), - array(2, '1 sec'), - array(59, 'secs', 1), - array(60, '1 min'), - array(3600, 'mins', 60), - array(5400, '1 hr'), - array(86400, 'hrs', 3600), - array(129600, '1 day'), - array(604800, 'days', 86400), - ); - - public function __construct($triggerDeprecationError = true) - { - if ($triggerDeprecationError) { - @trigger_error('The '.__CLASS__.' class is deprecated since version 2.5 and will be removed in 3.0. Use the Symfony\Component\Console\Helper\ProgressBar class instead.', E_USER_DEPRECATED); - } - } - - /** - * Sets the progress bar width. - * - * @param int $size The progress bar size - */ - public function setBarWidth($size) - { - $this->barWidth = (int) $size; - } - - /** - * Sets the bar character. - * - * @param string $char A character - */ - public function setBarCharacter($char) - { - $this->barChar = $char; - } - - /** - * Sets the empty bar character. - * - * @param string $char A character - */ - public function setEmptyBarCharacter($char) - { - $this->emptyBarChar = $char; - } - - /** - * Sets the progress bar character. - * - * @param string $char A character - */ - public function setProgressCharacter($char) - { - $this->progressChar = $char; - } - - /** - * Sets the progress bar format. - * - * @param string $format The format - */ - public function setFormat($format) - { - $this->format = $format; - } - - /** - * Sets the redraw frequency. - * - * @param int $freq The frequency in steps - */ - public function setRedrawFrequency($freq) - { - $this->redrawFreq = (int) $freq; - } - - /** - * Starts the progress output. - * - * @param OutputInterface $output An Output instance - * @param int|null $max Maximum steps - */ - public function start(OutputInterface $output, $max = null) - { - if ($output instanceof ConsoleOutputInterface) { - $output = $output->getErrorOutput(); - } - - $this->startTime = time(); - $this->current = 0; - $this->max = (int) $max; - - // Disabling output when it does not support ANSI codes as it would result in a broken display anyway. - $this->output = $output->isDecorated() ? $output : new NullOutput(); - $this->lastMessagesLength = 0; - $this->barCharOriginal = ''; - - if (null === $this->format) { - switch ($output->getVerbosity()) { - case OutputInterface::VERBOSITY_QUIET: - $this->format = self::FORMAT_QUIET_NOMAX; - if ($this->max > 0) { - $this->format = self::FORMAT_QUIET; - } - break; - case OutputInterface::VERBOSITY_VERBOSE: - case OutputInterface::VERBOSITY_VERY_VERBOSE: - case OutputInterface::VERBOSITY_DEBUG: - $this->format = self::FORMAT_VERBOSE_NOMAX; - if ($this->max > 0) { - $this->format = self::FORMAT_VERBOSE; - } - break; - default: - $this->format = self::FORMAT_NORMAL_NOMAX; - if ($this->max > 0) { - $this->format = self::FORMAT_NORMAL; - } - break; - } - } - - $this->initialize(); - } - - /** - * Advances the progress output X steps. - * - * @param int $step Number of steps to advance - * @param bool $redraw Whether to redraw or not - * - * @throws LogicException - */ - public function advance($step = 1, $redraw = false) - { - $this->setCurrent($this->current + $step, $redraw); - } - - /** - * Sets the current progress. - * - * @param int $current The current progress - * @param bool $redraw Whether to redraw or not - * - * @throws LogicException - */ - public function setCurrent($current, $redraw = false) - { - if (null === $this->startTime) { - throw new LogicException('You must start the progress bar before calling setCurrent().'); - } - - $current = (int) $current; - - if ($current < $this->current) { - throw new LogicException('You can\'t regress the progress bar'); - } - - if (0 === $this->current) { - $redraw = true; - } - - $prevPeriod = (int) ($this->current / $this->redrawFreq); - - $this->current = $current; - - $currPeriod = (int) ($this->current / $this->redrawFreq); - if ($redraw || $prevPeriod !== $currPeriod || $this->max === $this->current) { - $this->display(); - } - } - - /** - * Outputs the current progress string. - * - * @param bool $finish Forces the end result - * - * @throws LogicException - */ - public function display($finish = false) - { - if (null === $this->startTime) { - throw new LogicException('You must start the progress bar before calling display().'); - } - - $message = $this->format; - foreach ($this->generate($finish) as $name => $value) { - $message = str_replace("%{$name}%", $value, $message); - } - $this->overwrite($this->output, $message); - } - - /** - * Removes the progress bar from the current line. - * - * This is useful if you wish to write some output - * while a progress bar is running. - * Call display() to show the progress bar again. - */ - public function clear() - { - $this->overwrite($this->output, ''); - } - - /** - * Finishes the progress output. - */ - public function finish() - { - if (null === $this->startTime) { - throw new LogicException('You must start the progress bar before calling finish().'); - } - - if (null !== $this->startTime) { - if (!$this->max) { - $this->barChar = $this->barCharOriginal; - $this->display(true); - } - $this->startTime = null; - $this->output->writeln(''); - $this->output = null; - } - } - - /** - * Initializes the progress helper. - */ - private function initialize() - { - $this->formatVars = array(); - foreach ($this->defaultFormatVars as $var) { - if (false !== strpos($this->format, "%{$var}%")) { - $this->formatVars[$var] = true; - } - } - - if ($this->max > 0) { - $this->widths['max'] = $this->strlen($this->max); - $this->widths['current'] = $this->widths['max']; - } else { - $this->barCharOriginal = $this->barChar; - $this->barChar = $this->emptyBarChar; - } - } - - /** - * Generates the array map of format variables to values. - * - * @param bool $finish Forces the end result - * - * @return array Array of format vars and values - */ - private function generate($finish = false) - { - $vars = array(); - $percent = 0; - if ($this->max > 0) { - $percent = (float) $this->current / $this->max; - } - - if (isset($this->formatVars['bar'])) { - $completeBars = 0; - - if ($this->max > 0) { - $completeBars = floor($percent * $this->barWidth); - } else { - if (!$finish) { - $completeBars = floor($this->current % $this->barWidth); - } else { - $completeBars = $this->barWidth; - } - } - - $emptyBars = $this->barWidth - $completeBars - $this->strlen($this->progressChar); - $bar = str_repeat($this->barChar, $completeBars); - if ($completeBars < $this->barWidth) { - $bar .= $this->progressChar; - $bar .= str_repeat($this->emptyBarChar, $emptyBars); - } - - $vars['bar'] = $bar; - } - - if (isset($this->formatVars['elapsed'])) { - $elapsed = time() - $this->startTime; - $vars['elapsed'] = str_pad($this->humaneTime($elapsed), $this->widths['elapsed'], ' ', STR_PAD_LEFT); - } - - if (isset($this->formatVars['current'])) { - $vars['current'] = str_pad($this->current, $this->widths['current'], ' ', STR_PAD_LEFT); - } - - if (isset($this->formatVars['max'])) { - $vars['max'] = $this->max; - } - - if (isset($this->formatVars['percent'])) { - $vars['percent'] = str_pad(floor($percent * 100), $this->widths['percent'], ' ', STR_PAD_LEFT); - } - - return $vars; - } - - /** - * Converts seconds into human-readable format. - * - * @param int $secs Number of seconds - * - * @return string Time in readable format - */ - private function humaneTime($secs) - { - $text = ''; - foreach ($this->timeFormats as $format) { - if ($secs < $format[0]) { - if (count($format) == 2) { - $text = $format[1]; - break; - } else { - $text = ceil($secs / $format[2]).' '.$format[1]; - break; - } - } - } - - return $text; - } - - /** - * Overwrites a previous message to the output. - * - * @param OutputInterface $output An Output instance - * @param string $message The message - */ - private function overwrite(OutputInterface $output, $message) - { - $length = $this->strlen($message); - - // append whitespace to match the last line's length - if (null !== $this->lastMessagesLength && $this->lastMessagesLength > $length) { - $message = str_pad($message, $this->lastMessagesLength, "\x20", STR_PAD_RIGHT); - } - - // carriage return - $output->write("\x0D"); - $output->write($message); - - $this->lastMessagesLength = $this->strlen($message); - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return 'progress'; - } -} diff --git a/vendor/symfony/console/Helper/ProgressIndicator.php b/vendor/symfony/console/Helper/ProgressIndicator.php index ccf9771b..d441accd 100644 --- a/vendor/symfony/console/Helper/ProgressIndicator.php +++ b/vendor/symfony/console/Helper/ProgressIndicator.php @@ -28,7 +28,6 @@ class ProgressIndicator private $indicatorCurrent; private $indicatorChangeInterval; private $indicatorUpdateTime; - private $lastMessagesLength; private $started = false; private static $formatters; @@ -77,42 +76,6 @@ class ProgressIndicator } /** - * Gets the current indicator message. - * - * @return string|null - * - * @internal for PHP 5.3 compatibility - */ - public function getMessage() - { - return $this->message; - } - - /** - * Gets the progress bar start time. - * - * @return int The progress bar start time - * - * @internal for PHP 5.3 compatibility - */ - public function getStartTime() - { - return $this->startTime; - } - - /** - * Gets the current animated indicator character. - * - * @return string - * - * @internal for PHP 5.3 compatibility - */ - public function getCurrentValue() - { - return $this->indicatorValues[$this->indicatorCurrent % count($this->indicatorValues)]; - } - - /** * Starts the indicator output. * * @param $message @@ -125,7 +88,6 @@ class ProgressIndicator $this->message = $message; $this->started = true; - $this->lastMessagesLength = 0; $this->startTime = time(); $this->indicatorUpdateTime = $this->getCurrentTimeInMilliseconds() + $this->indicatorChangeInterval; $this->indicatorCurrent = 0; @@ -262,27 +224,12 @@ class ProgressIndicator */ private function overwrite($message) { - // append whitespace to match the line's length - if (null !== $this->lastMessagesLength) { - if ($this->lastMessagesLength > Helper::strlenWithoutDecoration($this->output->getFormatter(), $message)) { - $message = str_pad($message, $this->lastMessagesLength, "\x20", STR_PAD_RIGHT); - } - } - if ($this->output->isDecorated()) { - $this->output->write("\x0D"); + $this->output->write("\x0D\x1B[2K"); $this->output->write($message); } else { $this->output->writeln($message); } - - $this->lastMessagesLength = 0; - - $len = Helper::strlenWithoutDecoration($this->output->getFormatter(), $message); - - if ($len > $this->lastMessagesLength) { - $this->lastMessagesLength = $len; - } } private function getCurrentTimeInMilliseconds() @@ -294,13 +241,13 @@ class ProgressIndicator { return array( 'indicator' => function (ProgressIndicator $indicator) { - return $indicator->getCurrentValue(); + return $indicator->indicatorValues[$indicator->indicatorCurrent % count($indicator->indicatorValues)]; }, 'message' => function (ProgressIndicator $indicator) { - return $indicator->getMessage(); + return $indicator->message; }, 'elapsed' => function (ProgressIndicator $indicator) { - return Helper::formatTime(time() - $indicator->getStartTime()); + return Helper::formatTime(time() - $indicator->startTime); }, 'memory' => function () { return Helper::formatMemory(memory_get_usage(true)); diff --git a/vendor/symfony/console/Helper/QuestionHelper.php b/vendor/symfony/console/Helper/QuestionHelper.php index 5bb30df8..f0f37a09 100644 --- a/vendor/symfony/console/Helper/QuestionHelper.php +++ b/vendor/symfony/console/Helper/QuestionHelper.php @@ -13,10 +13,12 @@ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Exception\InvalidArgumentException; use Symfony\Component\Console\Exception\RuntimeException; +use Symfony\Component\Console\Formatter\OutputFormatter; +use Symfony\Component\Console\Formatter\OutputFormatterStyle; use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\StreamableInputInterface; use Symfony\Component\Console\Output\ConsoleOutputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Formatter\OutputFormatterStyle; use Symfony\Component\Console\Question\Question; use Symfony\Component\Console\Question\ChoiceQuestion; @@ -34,11 +36,7 @@ class QuestionHelper extends Helper /** * Asks a question to the user. * - * @param InputInterface $input An InputInterface instance - * @param OutputInterface $output An OutputInterface instance - * @param Question $question The question to ask - * - * @return string The user answer + * @return mixed The user answer * * @throws RuntimeException If there is no data to read in the input stream */ @@ -52,14 +50,16 @@ class QuestionHelper extends Helper return $question->getDefault(); } + if ($input instanceof StreamableInputInterface && $stream = $input->getStream()) { + $this->inputStream = $stream; + } + if (!$question->getValidator()) { return $this->doAsk($output, $question); } - $that = $this; - - $interviewer = function () use ($output, $question, $that) { - return $that->doAsk($output, $question); + $interviewer = function () use ($output, $question) { + return $this->doAsk($output, $question); }; return $this->validateAttempts($interviewer, $output, $question); @@ -70,12 +70,17 @@ class QuestionHelper extends Helper * * This is mainly useful for testing purpose. * + * @deprecated since version 3.2, to be removed in 4.0. Use + * StreamableInputInterface::setStream() instead. + * * @param resource $stream The input stream * * @throws InvalidArgumentException In case the stream is not a resource */ public function setInputStream($stream) { + @trigger_error(sprintf('The %s() method is deprecated since version 3.2 and will be removed in 4.0. Use %s::setStream() instead.', __METHOD__, StreamableInputInterface::class), E_USER_DEPRECATED); + if (!is_resource($stream)) { throw new InvalidArgumentException('Input stream must be a valid resource.'); } @@ -86,10 +91,17 @@ class QuestionHelper extends Helper /** * Returns the helper's input stream. * + * @deprecated since version 3.2, to be removed in 4.0. Use + * StreamableInputInterface::getStream() instead. + * * @return resource */ public function getInputStream() { + if (0 === func_num_args() || func_get_arg(0)) { + @trigger_error(sprintf('The %s() method is deprecated since version 3.2 and will be removed in 4.0. Use %s::getStream() instead.', __METHOD__, StreamableInputInterface::class), E_USER_DEPRECATED); + } + return $this->inputStream; } @@ -102,19 +114,21 @@ class QuestionHelper extends Helper } /** + * Prevents usage of stty. + */ + public static function disableStty() + { + self::$stty = false; + } + + /** * Asks the question to the user. * - * This method is public for PHP 5.3 compatibility, it should be private. - * - * @param OutputInterface $output - * @param Question $question - * * @return bool|mixed|null|string * - * @throws \Exception - * @throws \RuntimeException + * @throws RuntimeException In case the fallback is deactivated and the response cannot be hidden */ - public function doAsk(OutputInterface $output, Question $question) + private function doAsk(OutputInterface $output, Question $question) { $this->writePrompt($output, $question); @@ -126,7 +140,7 @@ class QuestionHelper extends Helper if ($question->isHidden()) { try { $ret = trim($this->getHiddenResponse($output, $inputStream)); - } catch (\RuntimeException $e) { + } catch (RuntimeException $e) { if (!$question->isHiddenFallback()) { throw $e; } @@ -136,12 +150,12 @@ class QuestionHelper extends Helper if (false === $ret) { $ret = fgets($inputStream, 4096); if (false === $ret) { - throw new \RuntimeException('Aborted'); + throw new RuntimeException('Aborted'); } $ret = trim($ret); } } else { - $ret = trim($this->autocomplete($output, $question, $inputStream)); + $ret = trim($this->autocomplete($output, $question, $inputStream, is_array($autocomplete) ? $autocomplete : iterator_to_array($autocomplete, false))); } $ret = strlen($ret) > 0 ? $ret : $question->getDefault(); @@ -155,9 +169,6 @@ class QuestionHelper extends Helper /** * Outputs the question prompt. - * - * @param OutputInterface $output - * @param Question $question */ protected function writePrompt(OutputInterface $output, Question $question) { @@ -182,9 +193,6 @@ class QuestionHelper extends Helper /** * Outputs an error message. - * - * @param OutputInterface $output - * @param \Exception $error */ protected function writeError(OutputInterface $output, \Exception $error) { @@ -202,12 +210,13 @@ class QuestionHelper extends Helper * * @param OutputInterface $output * @param Question $question + * @param resource $inputStream + * @param array $autocomplete * * @return string */ - private function autocomplete(OutputInterface $output, Question $question, $inputStream) + private function autocomplete(OutputInterface $output, Question $question, $inputStream, array $autocomplete) { - $autocomplete = $question->getAutocompleterValues(); $ret = ''; $i = 0; @@ -235,7 +244,7 @@ class QuestionHelper extends Helper $output->write("\033[1D"); } - if ($i === 0) { + if (0 === $i) { $ofs = -1; $matches = $autocomplete; $numMatches = count($matches); @@ -303,7 +312,7 @@ class QuestionHelper extends Helper // Save cursor position $output->write("\0337"); // Write highlighted text - $output->write('<hl>'.substr($matches[$ofs], $i).'</hl>'); + $output->write('<hl>'.OutputFormatter::escapeTrailingBackslash(substr($matches[$ofs], $i)).'</hl>'); // Restore cursor position $output->write("\0338"); } @@ -318,7 +327,8 @@ class QuestionHelper extends Helper /** * Gets a hidden response from user. * - * @param OutputInterface $output An Output instance + * @param OutputInterface $output An Output instance + * @param resource $inputStream The handler resource * * @return string The answer * @@ -364,7 +374,7 @@ class QuestionHelper extends Helper } if (false !== $shell = $this->getShell()) { - $readCmd = $shell === 'csh' ? 'set mypassword = $<' : 'read -r mypassword'; + $readCmd = 'csh' === $shell ? 'set mypassword = $<' : 'read -r mypassword'; $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd); $value = rtrim(shell_exec($command)); $output->writeln(''); @@ -382,11 +392,11 @@ class QuestionHelper extends Helper * @param OutputInterface $output An Output instance * @param Question $question A Question instance * - * @return string The validated response + * @return mixed The validated response * * @throws \Exception In case the max number of attempts has been reached and no valid response has been given */ - private function validateAttempts($interviewer, OutputInterface $output, Question $question) + private function validateAttempts(callable $interviewer, OutputInterface $output, Question $question) { $error = null; $attempts = $question->getMaxAttempts(); @@ -397,6 +407,8 @@ class QuestionHelper extends Helper try { return call_user_func($question->getValidator(), $interviewer()); + } catch (RuntimeException $e) { + throw $e; } catch (\Exception $error) { } } @@ -444,6 +456,6 @@ class QuestionHelper extends Helper exec('stty 2>&1', $output, $exitcode); - return self::$stty = $exitcode === 0; + return self::$stty = 0 === $exitcode; } } diff --git a/vendor/symfony/console/Helper/SymfonyQuestionHelper.php b/vendor/symfony/console/Helper/SymfonyQuestionHelper.php index 942278bd..cf071d59 100644 --- a/vendor/symfony/console/Helper/SymfonyQuestionHelper.php +++ b/vendor/symfony/console/Helper/SymfonyQuestionHelper.php @@ -18,6 +18,7 @@ use Symfony\Component\Console\Question\ChoiceQuestion; use Symfony\Component\Console\Question\ConfirmationQuestion; use Symfony\Component\Console\Question\Question; use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\Console\Formatter\OutputFormatter; /** * Symfony Style Guide compliant question helper. @@ -28,6 +29,8 @@ class SymfonyQuestionHelper extends QuestionHelper { /** * {@inheritdoc} + * + * To be removed in 4.0 */ public function ask(InputInterface $input, OutputInterface $output, Question $question) { @@ -35,11 +38,13 @@ class SymfonyQuestionHelper extends QuestionHelper $question->setValidator(function ($value) use ($validator) { if (null !== $validator) { $value = $validator($value); - } + } else { + // make required + if (!is_array($value) && !is_bool($value) && 0 === strlen($value)) { + @trigger_error('The default question validator is deprecated since Symfony 3.3 and will not be used anymore in version 4.0. Set a custom question validator if needed.', E_USER_DEPRECATED); - // make required - if (!is_array($value) && !is_bool($value) && 0 === strlen($value)) { - throw new LogicException('A value is required.'); + throw new LogicException('A value is required.'); + } } return $value; @@ -53,7 +58,7 @@ class SymfonyQuestionHelper extends QuestionHelper */ protected function writePrompt(OutputInterface $output, Question $question) { - $text = $question->getQuestion(); + $text = OutputFormatter::escapeTrailingBackslash($question->getQuestion()); $default = $question->getDefault(); switch (true) { @@ -67,14 +72,26 @@ class SymfonyQuestionHelper extends QuestionHelper break; + case $question instanceof ChoiceQuestion && $question->isMultiselect(): + $choices = $question->getChoices(); + $default = explode(',', $default); + + foreach ($default as $key => $value) { + $default[$key] = $choices[trim($value)]; + } + + $text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape(implode(', ', $default))); + + break; + case $question instanceof ChoiceQuestion: $choices = $question->getChoices(); - $text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, $choices[$default]); + $text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape($choices[$default])); break; default: - $text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, $default); + $text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape($default)); } $output->writeln($text); diff --git a/vendor/symfony/console/Helper/Table.php b/vendor/symfony/console/Helper/Table.php index 13e4c3cf..905f7b87 100644 --- a/vendor/symfony/console/Helper/Table.php +++ b/vendor/symfony/console/Helper/Table.php @@ -26,29 +26,23 @@ class Table { /** * Table headers. - * - * @var array */ private $headers = array(); /** * Table rows. - * - * @var array */ private $rows = array(); /** * Column widths cache. - * - * @var array */ - private $columnWidths = array(); + private $effectiveColumnWidths = array(); /** * Number of columns cache. * - * @var array + * @var int */ private $numberOfColumns; @@ -67,6 +61,13 @@ class Table */ private $columnStyles = array(); + /** + * User set column widths. + * + * @var array + */ + private $columnWidths = array(); + private static $styles; public function __construct(OutputInterface $output) @@ -100,7 +101,7 @@ class Table * * @param string $name The style name * - * @return TableStyle A TableStyle instance + * @return TableStyle */ public static function getStyleDefinition($name) { @@ -108,11 +109,11 @@ class Table self::$styles = self::initStyles(); } - if (!self::$styles[$name]) { - throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name)); + if (isset(self::$styles[$name])) { + return self::$styles[$name]; } - return self::$styles[$name]; + throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name)); } /** @@ -120,17 +121,11 @@ class Table * * @param TableStyle|string $name The style name or a TableStyle instance * - * @return Table + * @return $this */ public function setStyle($name) { - if ($name instanceof TableStyle) { - $this->style = $name; - } elseif (isset(self::$styles[$name])) { - $this->style = self::$styles[$name]; - } else { - throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name)); - } + $this->style = $this->resolveStyle($name); return $this; } @@ -151,19 +146,13 @@ class Table * @param int $columnIndex Column index * @param TableStyle|string $name The style name or a TableStyle instance * - * @return Table + * @return $this */ public function setColumnStyle($columnIndex, $name) { - $columnIndex = intval($columnIndex); + $columnIndex = (int) $columnIndex; - if ($name instanceof TableStyle) { - $this->columnStyles[$columnIndex] = $name; - } elseif (isset(self::$styles[$name])) { - $this->columnStyles[$columnIndex] = self::$styles[$name]; - } else { - throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name)); - } + $this->columnStyles[$columnIndex] = $this->resolveStyle($name); return $this; } @@ -186,6 +175,38 @@ class Table return $this->getStyle(); } + /** + * Sets the minimum width of a column. + * + * @param int $columnIndex Column index + * @param int $width Minimum column width in characters + * + * @return $this + */ + public function setColumnWidth($columnIndex, $width) + { + $this->columnWidths[(int) $columnIndex] = (int) $width; + + return $this; + } + + /** + * Sets the minimum width of all columns. + * + * @param array $widths + * + * @return $this + */ + public function setColumnWidths(array $widths) + { + $this->columnWidths = array(); + foreach ($widths as $index => $width) { + $this->setColumnWidth($index, $width); + } + + return $this; + } + public function setHeaders(array $headers) { $headers = array_values($headers); @@ -242,6 +263,7 @@ class Table * Renders table to output. * * Example: + * <code> * +---------------+-----------------------+------------------+ * | ISBN | Title | Author | * +---------------+-----------------------+------------------+ @@ -249,6 +271,7 @@ class Table * | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | * | 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien | * +---------------+-----------------------+------------------+ + * </code> */ public function render() { @@ -282,7 +305,7 @@ class Table /** * Renders horizontal header separator. * - * Example: +-----+-----------+-------+ + * Example: <code>+-----+-----------+-------+</code> */ private function renderRowSeparator() { @@ -296,7 +319,7 @@ class Table $markup = $this->style->getCrossingChar(); for ($column = 0; $column < $count; ++$column) { - $markup .= str_repeat($this->style->getHorizontalBorderChar(), $this->columnWidths[$column]).$this->style->getCrossingChar(); + $markup .= str_repeat($this->style->getHorizontalBorderChar(), $this->effectiveColumnWidths[$column]).$this->style->getCrossingChar(); } $this->output->writeln(sprintf($this->style->getBorderFormat(), $markup)); @@ -313,7 +336,7 @@ class Table /** * Renders table row. * - * Example: | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | + * Example: <code>| 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens |</code> * * @param array $row * @param string $cellFormat @@ -342,11 +365,11 @@ class Table private function renderCell(array $row, $column, $cellFormat) { $cell = isset($row[$column]) ? $row[$column] : ''; - $width = $this->columnWidths[$column]; + $width = $this->effectiveColumnWidths[$column]; if ($cell instanceof TableCell && $cell->getColspan() > 1) { // add the width of the following columns(numbers of colspan). foreach (range($column + 1, $column + $cell->getColspan() - 1) as $nextColumn) { - $width += $this->getColumnSeparatorWidth() + $this->columnWidths[$nextColumn]; + $width += $this->getColumnSeparatorWidth() + $this->effectiveColumnWidths[$nextColumn]; } } @@ -399,7 +422,7 @@ class Table if (!strstr($cell, "\n")) { continue; } - $lines = explode("\n", $cell); + $lines = explode("\n", str_replace("\n", "<fg=default;bg=default>\n</>", $cell)); foreach ($lines as $lineKey => $line) { if ($cell instanceof TableCell) { $line = new TableCell($line, array('colspan' => $cell->getColspan())); @@ -432,7 +455,7 @@ class Table * * @return array */ - private function fillNextRows($rows, $line) + private function fillNextRows(array $rows, $line) { $unmergedRows = array(); foreach ($rows[$line] as $column => $cell) { @@ -440,7 +463,7 @@ class Table $nbLines = $cell->getRowspan() - 1; $lines = array($cell); if (strstr($cell, "\n")) { - $lines = explode("\n", $cell); + $lines = explode("\n", str_replace("\n", "<fg=default;bg=default>\n</>", $cell)); $nbLines = count($lines) > $nbLines ? substr_count($cell, "\n") : $nbLines; $rows[$line][$column] = new TableCell($lines[0], array('colspan' => $cell->getColspan())); @@ -448,10 +471,13 @@ class Table } // create a two dimensional array (rowspan x colspan) - $unmergedRows = array_replace_recursive(array_fill($line + 1, $nbLines, ''), $unmergedRows); + $unmergedRows = array_replace_recursive(array_fill($line + 1, $nbLines, array()), $unmergedRows); foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) { $value = isset($lines[$unmergedRowKey - $line]) ? $lines[$unmergedRowKey - $line] : ''; $unmergedRows[$unmergedRowKey][$column] = new TableCell($value, array('colspan' => $cell->getColspan())); + if ($nbLines === $unmergedRowKey - $line) { + break; + } } } } @@ -480,8 +506,6 @@ class Table /** * fill cells for a row that contains colspan > 1. * - * @param array $row - * * @return array */ private function fillCells($row) @@ -506,7 +530,7 @@ class Table * * @return array */ - private function copyRow($rows, $line) + private function copyRow(array $rows, $line) { $row = $rows[$line]; foreach ($row as $cellKey => $cellValue) { @@ -522,8 +546,6 @@ class Table /** * Gets number of columns by row. * - * @param array $row - * * @return int */ private function getNumberOfColumns(array $row) @@ -539,11 +561,9 @@ class Table /** * Gets list of columns for the given row. * - * @param array $row - * * @return array */ - private function getRowColumns($row) + private function getRowColumns(array $row) { $columns = range(0, $this->numberOfColumns - 1); foreach ($row as $cellKey => $cell) { @@ -558,10 +578,8 @@ class Table /** * Calculates columns widths. - * - * @param array $rows */ - private function calculateColumnsWidth($rows) + private function calculateColumnsWidth(array $rows) { for ($column = 0; $column < $this->numberOfColumns; ++$column) { $lengths = array(); @@ -572,9 +590,10 @@ class Table foreach ($row as $i => $cell) { if ($cell instanceof TableCell) { - $textLength = strlen($cell); + $textContent = Helper::removeDecoration($this->output->getFormatter(), $cell); + $textLength = Helper::strlen($textContent); if ($textLength > 0) { - $contentColumns = str_split($cell, ceil($textLength / $cell->getColspan())); + $contentColumns = str_split($textContent, ceil($textLength / $cell->getColspan())); foreach ($contentColumns as $position => $content) { $row[$i + $position] = $content; } @@ -585,7 +604,7 @@ class Table $lengths[] = $this->getCellWidth($row, $column); } - $this->columnWidths[$column] = max($lengths) + strlen($this->style->getCellRowContentFormat()) - 2; + $this->effectiveColumnWidths[$column] = max($lengths) + strlen($this->style->getCellRowContentFormat()) - 2; } } @@ -609,14 +628,16 @@ class Table */ private function getCellWidth(array $row, $column) { + $cellWidth = 0; + if (isset($row[$column])) { $cell = $row[$column]; $cellWidth = Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell); - - return $cellWidth; } - return 0; + $columnWidth = isset($this->columnWidths[$column]) ? $this->columnWidths[$column] : 0; + + return max($cellWidth, $columnWidth); } /** @@ -624,7 +645,7 @@ class Table */ private function cleanup() { - $this->columnWidths = array(); + $this->effectiveColumnWidths = array(); $this->numberOfColumns = null; } @@ -660,4 +681,17 @@ class Table 'symfony-style-guide' => $styleGuide, ); } + + private function resolveStyle($name) + { + if ($name instanceof TableStyle) { + return $name; + } + + if (isset(self::$styles[$name])) { + return self::$styles[$name]; + } + + throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name)); + } } diff --git a/vendor/symfony/console/Helper/TableCell.php b/vendor/symfony/console/Helper/TableCell.php index 69442d42..6fc7d3b9 100644 --- a/vendor/symfony/console/Helper/TableCell.php +++ b/vendor/symfony/console/Helper/TableCell.php @@ -18,14 +18,7 @@ use Symfony\Component\Console\Exception\InvalidArgumentException; */ class TableCell { - /** - * @var string - */ private $value; - - /** - * @var array - */ private $options = array( 'rowspan' => 1, 'colspan' => 1, @@ -37,6 +30,10 @@ class TableCell */ public function __construct($value = '', array $options = array()) { + if (is_numeric($value) && !is_string($value)) { + $value = (string) $value; + } + $this->value = $value; // check option names diff --git a/vendor/symfony/console/Helper/TableHelper.php b/vendor/symfony/console/Helper/TableHelper.php deleted file mode 100644 index 3c7a1a78..00000000 --- a/vendor/symfony/console/Helper/TableHelper.php +++ /dev/null @@ -1,269 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Output\NullOutput; -use Symfony\Component\Console\Exception\InvalidArgumentException; - -/** - * Provides helpers to display table output. - * - * @author Саша Стаменковић <umpirsky@gmail.com> - * @author Fabien Potencier <fabien@symfony.com> - * - * @deprecated since version 2.5, to be removed in 3.0 - * Use {@link Table} instead. - */ -class TableHelper extends Helper -{ - const LAYOUT_DEFAULT = 0; - const LAYOUT_BORDERLESS = 1; - const LAYOUT_COMPACT = 2; - - /** - * @var Table - */ - private $table; - - public function __construct($triggerDeprecationError = true) - { - if ($triggerDeprecationError) { - @trigger_error('The '.__CLASS__.' class is deprecated since version 2.5 and will be removed in 3.0. Use the Symfony\Component\Console\Helper\Table class instead.', E_USER_DEPRECATED); - } - - $this->table = new Table(new NullOutput()); - } - - /** - * Sets table layout type. - * - * @param int $layout self::LAYOUT_* - * - * @return TableHelper - * - * @throws InvalidArgumentException when the table layout is not known - */ - public function setLayout($layout) - { - switch ($layout) { - case self::LAYOUT_BORDERLESS: - $this->table->setStyle('borderless'); - break; - - case self::LAYOUT_COMPACT: - $this->table->setStyle('compact'); - break; - - case self::LAYOUT_DEFAULT: - $this->table->setStyle('default'); - break; - - default: - throw new InvalidArgumentException(sprintf('Invalid table layout "%s".', $layout)); - } - - return $this; - } - - public function setHeaders(array $headers) - { - $this->table->setHeaders($headers); - - return $this; - } - - public function setRows(array $rows) - { - $this->table->setRows($rows); - - return $this; - } - - public function addRows(array $rows) - { - $this->table->addRows($rows); - - return $this; - } - - public function addRow(array $row) - { - $this->table->addRow($row); - - return $this; - } - - public function setRow($column, array $row) - { - $this->table->setRow($column, $row); - - return $this; - } - - /** - * Sets padding character, used for cell padding. - * - * @param string $paddingChar - * - * @return TableHelper - */ - public function setPaddingChar($paddingChar) - { - $this->table->getStyle()->setPaddingChar($paddingChar); - - return $this; - } - - /** - * Sets horizontal border character. - * - * @param string $horizontalBorderChar - * - * @return TableHelper - */ - public function setHorizontalBorderChar($horizontalBorderChar) - { - $this->table->getStyle()->setHorizontalBorderChar($horizontalBorderChar); - - return $this; - } - - /** - * Sets vertical border character. - * - * @param string $verticalBorderChar - * - * @return TableHelper - */ - public function setVerticalBorderChar($verticalBorderChar) - { - $this->table->getStyle()->setVerticalBorderChar($verticalBorderChar); - - return $this; - } - - /** - * Sets crossing character. - * - * @param string $crossingChar - * - * @return TableHelper - */ - public function setCrossingChar($crossingChar) - { - $this->table->getStyle()->setCrossingChar($crossingChar); - - return $this; - } - - /** - * Sets header cell format. - * - * @param string $cellHeaderFormat - * - * @return TableHelper - */ - public function setCellHeaderFormat($cellHeaderFormat) - { - $this->table->getStyle()->setCellHeaderFormat($cellHeaderFormat); - - return $this; - } - - /** - * Sets row cell format. - * - * @param string $cellRowFormat - * - * @return TableHelper - */ - public function setCellRowFormat($cellRowFormat) - { - $this->table->getStyle()->setCellHeaderFormat($cellRowFormat); - - return $this; - } - - /** - * Sets row cell content format. - * - * @param string $cellRowContentFormat - * - * @return TableHelper - */ - public function setCellRowContentFormat($cellRowContentFormat) - { - $this->table->getStyle()->setCellRowContentFormat($cellRowContentFormat); - - return $this; - } - - /** - * Sets table border format. - * - * @param string $borderFormat - * - * @return TableHelper - */ - public function setBorderFormat($borderFormat) - { - $this->table->getStyle()->setBorderFormat($borderFormat); - - return $this; - } - - /** - * Sets cell padding type. - * - * @param int $padType STR_PAD_* - * - * @return TableHelper - */ - public function setPadType($padType) - { - $this->table->getStyle()->setPadType($padType); - - return $this; - } - - /** - * Renders table to output. - * - * Example: - * +---------------+-----------------------+------------------+ - * | ISBN | Title | Author | - * +---------------+-----------------------+------------------+ - * | 99921-58-10-7 | Divine Comedy | Dante Alighieri | - * | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | - * | 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien | - * +---------------+-----------------------+------------------+ - * - * @param OutputInterface $output - */ - public function render(OutputInterface $output) - { - $p = new \ReflectionProperty($this->table, 'output'); - $p->setAccessible(true); - $p->setValue($this->table, $output); - - $this->table->render(); - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return 'table'; - } -} diff --git a/vendor/symfony/console/Helper/TableSeparator.php b/vendor/symfony/console/Helper/TableSeparator.php index 8cbbc661..c7b8dc9c 100644 --- a/vendor/symfony/console/Helper/TableSeparator.php +++ b/vendor/symfony/console/Helper/TableSeparator.php @@ -18,10 +18,6 @@ namespace Symfony\Component\Console\Helper; */ class TableSeparator extends TableCell { - /** - * @param string $value - * @param array $options - */ public function __construct(array $options = array()) { parent::__construct('', $options); diff --git a/vendor/symfony/console/Helper/TableStyle.php b/vendor/symfony/console/Helper/TableStyle.php index d7e28ff2..2999c76f 100644 --- a/vendor/symfony/console/Helper/TableStyle.php +++ b/vendor/symfony/console/Helper/TableStyle.php @@ -37,7 +37,7 @@ class TableStyle * * @param string $paddingChar * - * @return TableStyle + * @return $this */ public function setPaddingChar($paddingChar) { @@ -65,7 +65,7 @@ class TableStyle * * @param string $horizontalBorderChar * - * @return TableStyle + * @return $this */ public function setHorizontalBorderChar($horizontalBorderChar) { @@ -89,7 +89,7 @@ class TableStyle * * @param string $verticalBorderChar * - * @return TableStyle + * @return $this */ public function setVerticalBorderChar($verticalBorderChar) { @@ -113,7 +113,7 @@ class TableStyle * * @param string $crossingChar * - * @return TableStyle + * @return $this */ public function setCrossingChar($crossingChar) { @@ -137,7 +137,7 @@ class TableStyle * * @param string $cellHeaderFormat * - * @return TableStyle + * @return $this */ public function setCellHeaderFormat($cellHeaderFormat) { @@ -161,7 +161,7 @@ class TableStyle * * @param string $cellRowFormat * - * @return TableStyle + * @return $this */ public function setCellRowFormat($cellRowFormat) { @@ -185,7 +185,7 @@ class TableStyle * * @param string $cellRowContentFormat * - * @return TableStyle + * @return $this */ public function setCellRowContentFormat($cellRowContentFormat) { @@ -209,7 +209,7 @@ class TableStyle * * @param string $borderFormat * - * @return TableStyle + * @return $this */ public function setBorderFormat($borderFormat) { @@ -233,7 +233,7 @@ class TableStyle * * @param int $padType STR_PAD_* * - * @return TableStyle + * @return $this */ public function setPadType($padType) { diff --git a/vendor/symfony/console/Input/ArgvInput.php b/vendor/symfony/console/Input/ArgvInput.php index 02d4cdb3..b576cf42 100644 --- a/vendor/symfony/console/Input/ArgvInput.php +++ b/vendor/symfony/console/Input/ArgvInput.php @@ -44,10 +44,8 @@ class ArgvInput extends Input private $parsed; /** - * Constructor. - * - * @param array $argv An array of parameters from the CLI (in the argv format) - * @param InputDefinition $definition A InputDefinition instance + * @param array|null $argv An array of parameters from the CLI (in the argv format) + * @param InputDefinition|null $definition A InputDefinition instance */ public function __construct(array $argv = null, InputDefinition $definition = null) { @@ -69,7 +67,7 @@ class ArgvInput extends Input } /** - * Processes command line arguments. + * {@inheritdoc} */ protected function parse() { @@ -93,7 +91,7 @@ class ArgvInput extends Input /** * Parses a short option. * - * @param string $token The current token. + * @param string $token The current token */ private function parseShortOption($token) { @@ -147,7 +145,15 @@ class ArgvInput extends Input $name = substr($token, 2); if (false !== $pos = strpos($name, '=')) { - $this->addLongOption(substr($name, 0, $pos), substr($name, $pos + 1)); + if (0 === strlen($value = substr($name, $pos + 1))) { + // if no value after "=" then substr() returns "" since php7 only, false before + // see http://php.net/manual/fr/migration70.incompatible.php#119151 + if (\PHP_VERSION_ID < 70000 && false === $value) { + $value = ''; + } + array_unshift($this->parsed, $value); + } + $this->addLongOption(substr($name, 0, $pos), $value); } else { $this->addLongOption($name, null); } @@ -176,7 +182,12 @@ class ArgvInput extends Input // unexpected argument } else { - throw new RuntimeException('Too many arguments.'); + $all = $this->definition->getArguments(); + if (count($all)) { + throw new RuntimeException(sprintf('Too many arguments, expected arguments "%s".', implode('" "', array_keys($all)))); + } + + throw new RuntimeException(sprintf('No arguments expected, got "%s".', $token)); } } @@ -213,23 +224,16 @@ class ArgvInput extends Input $option = $this->definition->getOption($name); - // Convert empty values to null - if (!isset($value[0])) { - $value = null; - } - if (null !== $value && !$option->acceptValue()) { throw new RuntimeException(sprintf('The "--%s" option does not accept a value.', $name)); } - if (null === $value && $option->acceptValue() && count($this->parsed)) { + if (in_array($value, array('', null), true) && $option->acceptValue() && count($this->parsed)) { // if option accepts an optional or mandatory argument // let's see if there is one provided $next = array_shift($this->parsed); - if (isset($next[0]) && '-' !== $next[0]) { + if ((isset($next[0]) && '-' !== $next[0]) || in_array($next, array('', null), true)) { $value = $next; - } elseif (empty($next)) { - $value = ''; } else { array_unshift($this->parsed, $next); } @@ -240,8 +244,8 @@ class ArgvInput extends Input throw new RuntimeException(sprintf('The "--%s" option requires a value.', $name)); } - if (!$option->isArray()) { - $value = $option->isValueOptional() ? $option->getDefault() : true; + if (!$option->isArray() && !$option->isValueOptional()) { + $value = true; } } @@ -253,9 +257,7 @@ class ArgvInput extends Input } /** - * Returns the first argument from the raw parameters (not parsed). - * - * @return string The value of the first argument or null otherwise + * {@inheritdoc} */ public function getFirstArgument() { @@ -269,24 +271,30 @@ class ArgvInput extends Input } /** - * Returns true if the raw parameters (not parsed) contain a value. - * - * This method is to be used to introspect the input parameters - * before they have been validated. It must be used carefully. - * - * @param string|array $values The value(s) to look for in the raw parameters (can be an array) - * - * @return bool true if the value is contained in the raw parameters + * {@inheritdoc} */ - public function hasParameterOption($values) + public function hasParameterOption($values, $onlyParams = false) { $values = (array) $values; foreach ($this->tokens as $token) { + if ($onlyParams && '--' === $token) { + return false; + } foreach ($values as $value) { if ($token === $value || 0 === strpos($token, $value.'=')) { return true; } + + if (0 === strpos($token, '-') && 0 !== strpos($token, '--')) { + $noValue = explode('=', $token); + $token = $noValue[0]; + $searchableToken = str_replace('-', '', $token); + $searchableValue = str_replace('-', '', $value); + if ('' !== $searchableToken && '' !== $searchableValue && false !== strpos($searchableToken, $searchableValue)) { + return true; + } + } } } @@ -294,23 +302,18 @@ class ArgvInput extends Input } /** - * Returns the value of a raw option (not parsed). - * - * This method is to be used to introspect the input parameters - * before they have been validated. It must be used carefully. - * - * @param string|array $values The value(s) to look for in the raw parameters (can be an array) - * @param mixed $default The default value to return if no result is found - * - * @return mixed The option value + * {@inheritdoc} */ - public function getParameterOption($values, $default = false) + public function getParameterOption($values, $default = false, $onlyParams = false) { $values = (array) $values; $tokens = $this->tokens; while (0 < count($tokens)) { $token = array_shift($tokens); + if ($onlyParams && '--' === $token) { + return false; + } foreach ($values as $value) { if ($token === $value || 0 === strpos($token, $value.'=')) { @@ -333,14 +336,13 @@ class ArgvInput extends Input */ public function __toString() { - $self = $this; - $tokens = array_map(function ($token) use ($self) { + $tokens = array_map(function ($token) { if (preg_match('{^(-[^=]+=)(.+)}', $token, $match)) { - return $match[1].$self->escapeToken($match[2]); + return $match[1].$this->escapeToken($match[2]); } - if ($token && $token[0] !== '-') { - return $self->escapeToken($token); + if ($token && '-' !== $token[0]) { + return $this->escapeToken($token); } return $token; diff --git a/vendor/symfony/console/Input/ArrayInput.php b/vendor/symfony/console/Input/ArrayInput.php index 8cedbb37..e6c28de9 100644 --- a/vendor/symfony/console/Input/ArrayInput.php +++ b/vendor/symfony/console/Input/ArrayInput.php @@ -27,12 +27,6 @@ class ArrayInput extends Input { private $parameters; - /** - * Constructor. - * - * @param array $parameters An array of parameters - * @param InputDefinition $definition A InputDefinition instance - */ public function __construct(array $parameters, InputDefinition $definition = null) { $this->parameters = $parameters; @@ -41,9 +35,7 @@ class ArrayInput extends Input } /** - * Returns the first argument from the raw parameters (not parsed). - * - * @return string The value of the first argument or null otherwise + * {@inheritdoc} */ public function getFirstArgument() { @@ -57,16 +49,9 @@ class ArrayInput extends Input } /** - * Returns true if the raw parameters (not parsed) contain a value. - * - * This method is to be used to introspect the input parameters - * before they have been validated. It must be used carefully. - * - * @param string|array $values The values to look for in the raw parameters (can be an array) - * - * @return bool true if the value is contained in the raw parameters + * {@inheritdoc} */ - public function hasParameterOption($values) + public function hasParameterOption($values, $onlyParams = false) { $values = (array) $values; @@ -75,6 +60,10 @@ class ArrayInput extends Input $v = $k; } + if ($onlyParams && '--' === $v) { + return false; + } + if (in_array($v, $values)) { return true; } @@ -84,21 +73,17 @@ class ArrayInput extends Input } /** - * Returns the value of a raw option (not parsed). - * - * This method is to be used to introspect the input parameters - * before they have been validated. It must be used carefully. - * - * @param string|array $values The value(s) to look for in the raw parameters (can be an array) - * @param mixed $default The default value to return if no result is found - * - * @return mixed The option value + * {@inheritdoc} */ - public function getParameterOption($values, $default = false) + public function getParameterOption($values, $default = false, $onlyParams = false) { $values = (array) $values; foreach ($this->parameters as $k => $v) { + if ($onlyParams && ('--' === $k || (is_int($k) && '--' === $v))) { + return false; + } + if (is_int($k)) { if (in_array($v, $values)) { return true; @@ -121,9 +106,15 @@ class ArrayInput extends Input $params = array(); foreach ($this->parameters as $param => $val) { if ($param && '-' === $param[0]) { - $params[] = $param.('' != $val ? '='.$this->escapeToken($val) : ''); + if (is_array($val)) { + foreach ($val as $v) { + $params[] = $param.('' != $v ? '='.$this->escapeToken($v) : ''); + } + } else { + $params[] = $param.('' != $val ? '='.$this->escapeToken($val) : ''); + } } else { - $params[] = $this->escapeToken($val); + $params[] = is_array($val) ? array_map(array($this, 'escapeToken'), $val) : $this->escapeToken($val); } } @@ -131,11 +122,14 @@ class ArrayInput extends Input } /** - * Processes command line arguments. + * {@inheritdoc} */ protected function parse() { foreach ($this->parameters as $key => $value) { + if ('--' === $key) { + return; + } if (0 === strpos($key, '--')) { $this->addLongOption(substr($key, 2), $value); } elseif ('-' === $key[0]) { @@ -185,7 +179,9 @@ class ArrayInput extends Input throw new InvalidOptionException(sprintf('The "--%s" option requires a value.', $name)); } - $value = $option->isValueOptional() ? $option->getDefault() : true; + if (!$option->isValueOptional()) { + $value = true; + } } $this->options[$name] = $value; diff --git a/vendor/symfony/console/Input/Input.php b/vendor/symfony/console/Input/Input.php index 85499fc4..41413252 100644 --- a/vendor/symfony/console/Input/Input.php +++ b/vendor/symfony/console/Input/Input.php @@ -25,21 +25,14 @@ use Symfony\Component\Console\Exception\RuntimeException; * * @author Fabien Potencier <fabien@symfony.com> */ -abstract class Input implements InputInterface +abstract class Input implements InputInterface, StreamableInputInterface { - /** - * @var InputDefinition - */ protected $definition; + protected $stream; protected $options = array(); protected $arguments = array(); protected $interactive = true; - /** - * Constructor. - * - * @param InputDefinition $definition A InputDefinition instance - */ public function __construct(InputDefinition $definition = null) { if (null === $definition) { @@ -51,9 +44,7 @@ abstract class Input implements InputInterface } /** - * Binds the current Input instance with the given arguments and options. - * - * @param InputDefinition $definition A InputDefinition instance + * {@inheritdoc} */ public function bind(InputDefinition $definition) { @@ -70,9 +61,7 @@ abstract class Input implements InputInterface abstract protected function parse(); /** - * Validates the input. - * - * @throws RuntimeException When not enough arguments are given + * {@inheritdoc} */ public function validate() { @@ -89,9 +78,7 @@ abstract class Input implements InputInterface } /** - * Checks if the input is interactive. - * - * @return bool Returns true if the input is interactive + * {@inheritdoc} */ public function isInteractive() { @@ -99,9 +86,7 @@ abstract class Input implements InputInterface } /** - * Sets the input interactivity. - * - * @param bool $interactive If the input should be interactive + * {@inheritdoc} */ public function setInteractive($interactive) { @@ -109,9 +94,7 @@ abstract class Input implements InputInterface } /** - * Returns the argument values. - * - * @return array An array of argument values + * {@inheritdoc} */ public function getArguments() { @@ -119,13 +102,7 @@ abstract class Input implements InputInterface } /** - * Returns the argument value for a given argument name. - * - * @param string $name The argument name - * - * @return mixed The argument value - * - * @throws InvalidArgumentException When argument given doesn't exist + * {@inheritdoc} */ public function getArgument($name) { @@ -137,12 +114,7 @@ abstract class Input implements InputInterface } /** - * Sets an argument value by name. - * - * @param string $name The argument name - * @param string $value The argument value - * - * @throws InvalidArgumentException When argument given doesn't exist + * {@inheritdoc} */ public function setArgument($name, $value) { @@ -154,11 +126,7 @@ abstract class Input implements InputInterface } /** - * Returns true if an InputArgument object exists by name or position. - * - * @param string|int $name The InputArgument name or position - * - * @return bool true if the InputArgument object exists, false otherwise + * {@inheritdoc} */ public function hasArgument($name) { @@ -166,9 +134,7 @@ abstract class Input implements InputInterface } /** - * Returns the options values. - * - * @return array An array of option values + * {@inheritdoc} */ public function getOptions() { @@ -176,13 +142,7 @@ abstract class Input implements InputInterface } /** - * Returns the option value for a given option name. - * - * @param string $name The option name - * - * @return mixed The option value - * - * @throws InvalidArgumentException When option given doesn't exist + * {@inheritdoc} */ public function getOption($name) { @@ -190,16 +150,11 @@ abstract class Input implements InputInterface throw new InvalidArgumentException(sprintf('The "%s" option does not exist.', $name)); } - return isset($this->options[$name]) ? $this->options[$name] : $this->definition->getOption($name)->getDefault(); + return array_key_exists($name, $this->options) ? $this->options[$name] : $this->definition->getOption($name)->getDefault(); } /** - * Sets an option value by name. - * - * @param string $name The option name - * @param string|bool $value The option value - * - * @throws InvalidArgumentException When option given doesn't exist + * {@inheritdoc} */ public function setOption($name, $value) { @@ -211,11 +166,7 @@ abstract class Input implements InputInterface } /** - * Returns true if an InputOption object exists by name. - * - * @param string $name The InputOption name - * - * @return bool true if the InputOption object exists, false otherwise + * {@inheritdoc} */ public function hasOption($name) { @@ -233,4 +184,20 @@ abstract class Input implements InputInterface { return preg_match('{^[\w-]+$}', $token) ? $token : escapeshellarg($token); } + + /** + * {@inheritdoc} + */ + public function setStream($stream) + { + $this->stream = $stream; + } + + /** + * {@inheritdoc} + */ + public function getStream() + { + return $this->stream; + } } diff --git a/vendor/symfony/console/Input/InputArgument.php b/vendor/symfony/console/Input/InputArgument.php index 048ee4ff..a969d2c5 100644 --- a/vendor/symfony/console/Input/InputArgument.php +++ b/vendor/symfony/console/Input/InputArgument.php @@ -31,8 +31,6 @@ class InputArgument private $description; /** - * Constructor. - * * @param string $name The argument name * @param int $mode The argument mode: self::REQUIRED or self::OPTIONAL * @param string $description A description text diff --git a/vendor/symfony/console/Input/InputDefinition.php b/vendor/symfony/console/Input/InputDefinition.php index bd64163b..d5b99ab3 100644 --- a/vendor/symfony/console/Input/InputDefinition.php +++ b/vendor/symfony/console/Input/InputDefinition.php @@ -11,9 +11,6 @@ namespace Symfony\Component\Console\Input; -use Symfony\Component\Console\Descriptor\TextDescriptor; -use Symfony\Component\Console\Descriptor\XmlDescriptor; -use Symfony\Component\Console\Output\BufferedOutput; use Symfony\Component\Console\Exception\InvalidArgumentException; use Symfony\Component\Console\Exception\LogicException; @@ -39,8 +36,6 @@ class InputDefinition private $shortcuts; /** - * Constructor. - * * @param array $definition An array of InputArgument and InputOption instance */ public function __construct(array $definition = array()) @@ -50,8 +45,6 @@ class InputDefinition /** * Sets the definition of the input. - * - * @param array $definition The definition array */ public function setDefinition(array $definition) { @@ -98,10 +91,6 @@ class InputDefinition } /** - * Adds an InputArgument object. - * - * @param InputArgument $argument An InputArgument object - * * @throws LogicException When incorrect argument is given */ public function addArgument(InputArgument $argument) @@ -235,10 +224,6 @@ class InputDefinition } /** - * Adds an InputOption object. - * - * @param InputOption $option An InputOption object - * * @throws LogicException When option given already exist */ public function addOption(InputOption $option) @@ -284,6 +269,9 @@ class InputDefinition /** * Returns true if an InputOption object exists by name. * + * This method can't be used to check if the user included the option when + * executing the command (use getOption() instead). + * * @param string $name The InputOption name * * @return bool true if the InputOption object exists, false otherwise @@ -318,7 +306,7 @@ class InputDefinition /** * Gets an InputOption by shortcut. * - * @param string $shortcut the Shortcut name + * @param string $shortcut The Shortcut name * * @return InputOption An InputOption object */ @@ -411,47 +399,4 @@ class InputDefinition return implode(' ', $elements); } - - /** - * Returns a textual representation of the InputDefinition. - * - * @return string A string representing the InputDefinition - * - * @deprecated since version 2.3, to be removed in 3.0. - */ - public function asText() - { - @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0.', E_USER_DEPRECATED); - - $descriptor = new TextDescriptor(); - $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true); - $descriptor->describe($output, $this, array('raw_output' => true)); - - return $output->fetch(); - } - - /** - * Returns an XML representation of the InputDefinition. - * - * @param bool $asDom Whether to return a DOM or an XML string - * - * @return string|\DOMDocument An XML string representing the InputDefinition - * - * @deprecated since version 2.3, to be removed in 3.0. - */ - public function asXml($asDom = false) - { - @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0.', E_USER_DEPRECATED); - - $descriptor = new XmlDescriptor(); - - if ($asDom) { - return $descriptor->getInputDefinitionDocument($this); - } - - $output = new BufferedOutput(); - $descriptor->describe($output, $this); - - return $output->fetch(); - } } diff --git a/vendor/symfony/console/Input/InputInterface.php b/vendor/symfony/console/Input/InputInterface.php index f83b8856..e2412d71 100644 --- a/vendor/symfony/console/Input/InputInterface.php +++ b/vendor/symfony/console/Input/InputInterface.php @@ -11,6 +11,9 @@ namespace Symfony\Component\Console\Input; +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\RuntimeException; + /** * InputInterface is the interface implemented by all input classes. * @@ -31,11 +34,12 @@ interface InputInterface * This method is to be used to introspect the input parameters * before they have been validated. It must be used carefully. * - * @param string|array $values The values to look for in the raw parameters (can be an array) + * @param string|array $values The values to look for in the raw parameters (can be an array) + * @param bool $onlyParams Only check real parameters, skip those following an end of options (--) signal * * @return bool true if the value is contained in the raw parameters */ - public function hasParameterOption($values); + public function hasParameterOption($values, $onlyParams = false); /** * Returns the value of a raw option (not parsed). @@ -43,26 +47,23 @@ interface InputInterface * This method is to be used to introspect the input parameters * before they have been validated. It must be used carefully. * - * @param string|array $values The value(s) to look for in the raw parameters (can be an array) - * @param mixed $default The default value to return if no result is found + * @param string|array $values The value(s) to look for in the raw parameters (can be an array) + * @param mixed $default The default value to return if no result is found + * @param bool $onlyParams Only check real parameters, skip those following an end of options (--) signal * * @return mixed The option value */ - public function getParameterOption($values, $default = false); + public function getParameterOption($values, $default = false, $onlyParams = false); /** * Binds the current Input instance with the given arguments and options. - * - * @param InputDefinition $definition A InputDefinition instance */ public function bind(InputDefinition $definition); /** - * Validates if arguments given are correct. + * Validates the input. * - * Throws an exception when not enough arguments are given. - * - * @throws \RuntimeException + * @throws RuntimeException When not enough arguments are given */ public function validate(); @@ -74,11 +75,13 @@ interface InputInterface public function getArguments(); /** - * Gets argument by name. + * Returns the argument value for a given argument name. + * + * @param string $name The argument name * - * @param string $name The name of the argument + * @return mixed The argument value * - * @return mixed + * @throws InvalidArgumentException When argument given doesn't exist */ public function getArgument($name); @@ -109,11 +112,13 @@ interface InputInterface public function getOptions(); /** - * Gets an option by name. + * Returns the option value for a given option name. + * + * @param string $name The option name * - * @param string $name The name of the option + * @return mixed The option value * - * @return mixed + * @throws InvalidArgumentException When option given doesn't exist */ public function getOption($name); diff --git a/vendor/symfony/console/Input/InputOption.php b/vendor/symfony/console/Input/InputOption.php index f08c5f26..3af8077c 100644 --- a/vendor/symfony/console/Input/InputOption.php +++ b/vendor/symfony/console/Input/InputOption.php @@ -33,8 +33,6 @@ class InputOption private $description; /** - * Constructor. - * * @param string $name The option name * @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 @@ -195,8 +193,6 @@ class InputOption /** * Checks whether the given option equals this one. * - * @param InputOption $option option to compare - * * @return bool */ public function equals(InputOption $option) diff --git a/vendor/symfony/console/Input/StreamableInputInterface.php b/vendor/symfony/console/Input/StreamableInputInterface.php new file mode 100644 index 00000000..d7e462f2 --- /dev/null +++ b/vendor/symfony/console/Input/StreamableInputInterface.php @@ -0,0 +1,37 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Input; + +/** + * StreamableInputInterface is the interface implemented by all input classes + * that have an input stream. + * + * @author Robin Chalas <robin.chalas@gmail.com> + */ +interface StreamableInputInterface extends InputInterface +{ + /** + * Sets the input stream to read from when interacting with the user. + * + * This is mainly useful for testing purpose. + * + * @param resource $stream The input stream + */ + public function setStream($stream); + + /** + * Returns the input stream. + * + * @return resource|null + */ + public function getStream(); +} diff --git a/vendor/symfony/console/Input/StringInput.php b/vendor/symfony/console/Input/StringInput.php index a40ddba3..d3630fc0 100644 --- a/vendor/symfony/console/Input/StringInput.php +++ b/vendor/symfony/console/Input/StringInput.php @@ -28,26 +28,13 @@ class StringInput extends ArgvInput const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\')'; /** - * Constructor. - * - * @param string $input An array of parameters from the CLI (in the argv format) - * @param InputDefinition $definition A InputDefinition instance - * - * @deprecated The second argument is deprecated as it does not work (will be removed in 3.0), use 'bind' method instead + * @param string $input An array of parameters from the CLI (in the argv format) */ - public function __construct($input, InputDefinition $definition = null) + public function __construct($input) { - if ($definition) { - @trigger_error('The $definition argument of the '.__METHOD__.' method is deprecated and will be removed in 3.0. Set this parameter with the bind() method instead.', E_USER_DEPRECATED); - } - - parent::__construct(array(), null); + parent::__construct(array()); $this->setTokens($this->tokenize($input)); - - if (null !== $definition) { - $this->bind($definition); - } } /** diff --git a/vendor/symfony/console/LICENSE b/vendor/symfony/console/LICENSE index 12a74531..17d16a13 100644 --- a/vendor/symfony/console/LICENSE +++ b/vendor/symfony/console/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2016 Fabien Potencier +Copyright (c) 2004-2017 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/symfony/console/Logger/ConsoleLogger.php b/vendor/symfony/console/Logger/ConsoleLogger.php index 1f7417ea..05dd3b96 100644 --- a/vendor/symfony/console/Logger/ConsoleLogger.php +++ b/vendor/symfony/console/Logger/ConsoleLogger.php @@ -22,20 +22,14 @@ use Symfony\Component\Console\Output\ConsoleOutputInterface; * * @author Kévin Dunglas <dunglas@gmail.com> * - * @link http://www.php-fig.org/psr/psr-3/ + * @see http://www.php-fig.org/psr/psr-3/ */ class ConsoleLogger extends AbstractLogger { const INFO = 'info'; const ERROR = 'error'; - /** - * @var OutputInterface - */ private $output; - /** - * @var array - */ private $verbosityLevelMap = array( LogLevel::EMERGENCY => OutputInterface::VERBOSITY_NORMAL, LogLevel::ALERT => OutputInterface::VERBOSITY_NORMAL, @@ -46,9 +40,6 @@ class ConsoleLogger extends AbstractLogger LogLevel::INFO => OutputInterface::VERBOSITY_VERY_VERBOSE, LogLevel::DEBUG => OutputInterface::VERBOSITY_DEBUG, ); - /** - * @var array - */ private $formatLevelMap = array( LogLevel::EMERGENCY => self::ERROR, LogLevel::ALERT => self::ERROR, @@ -59,12 +50,8 @@ class ConsoleLogger extends AbstractLogger LogLevel::INFO => self::INFO, LogLevel::DEBUG => self::INFO, ); + private $errored = false; - /** - * @param OutputInterface $output - * @param array $verbosityLevelMap - * @param array $formatLevelMap - */ public function __construct(OutputInterface $output, array $verbosityLevelMap = array(), array $formatLevelMap = array()) { $this->output = $output; @@ -81,19 +68,34 @@ class ConsoleLogger extends AbstractLogger throw new InvalidArgumentException(sprintf('The log level "%s" does not exist.', $level)); } + $output = $this->output; + // Write to the error output if necessary and available - if ($this->formatLevelMap[$level] === self::ERROR && $this->output instanceof ConsoleOutputInterface) { - $output = $this->output->getErrorOutput(); - } else { - $output = $this->output; + if (self::ERROR === $this->formatLevelMap[$level]) { + if ($this->output instanceof ConsoleOutputInterface) { + $output = $output->getErrorOutput(); + } + $this->errored = true; } + // the if condition check isn't necessary -- it's the same one that $output will do internally anyway. + // We only do it for efficiency here as the message formatting is relatively expensive. if ($output->getVerbosity() >= $this->verbosityLevelMap[$level]) { - $output->writeln(sprintf('<%1$s>[%2$s] %3$s</%1$s>', $this->formatLevelMap[$level], $level, $this->interpolate($message, $context))); + $output->writeln(sprintf('<%1$s>[%2$s] %3$s</%1$s>', $this->formatLevelMap[$level], $level, $this->interpolate($message, $context)), $this->verbosityLevelMap[$level]); } } /** + * Returns true when any messages have been logged at error levels. + * + * @return bool + */ + public function hasErrored() + { + return $this->errored; + } + + /** * Interpolates context values into the message placeholders. * * @author PHP Framework Interoperability Group @@ -105,15 +107,23 @@ class ConsoleLogger extends AbstractLogger */ private function interpolate($message, array $context) { - // build a replacement array with braces around the context keys - $replace = array(); + if (false === strpos($message, '{')) { + return $message; + } + + $replacements = array(); foreach ($context as $key => $val) { - if (!is_array($val) && (!is_object($val) || method_exists($val, '__toString'))) { - $replace[sprintf('{%s}', $key)] = $val; + if (null === $val || is_scalar($val) || (\is_object($val) && method_exists($val, '__toString'))) { + $replacements["{{$key}}"] = $val; + } elseif ($val instanceof \DateTimeInterface) { + $replacements["{{$key}}"] = $val->format(\DateTime::RFC3339); + } elseif (\is_object($val)) { + $replacements["{{$key}}"] = '[object '.\get_class($val).']'; + } else { + $replacements["{{$key}}"] = '['.\gettype($val).']'; } } - // interpolate replacement values into the message and return - return strtr($message, $replace); + return strtr($message, $replacements); } } diff --git a/vendor/symfony/console/Output/BufferedOutput.php b/vendor/symfony/console/Output/BufferedOutput.php index 5682fc24..8afc8931 100644 --- a/vendor/symfony/console/Output/BufferedOutput.php +++ b/vendor/symfony/console/Output/BufferedOutput.php @@ -16,9 +16,6 @@ namespace Symfony\Component\Console\Output; */ class BufferedOutput extends Output { - /** - * @var string - */ private $buffer = ''; /** @@ -42,7 +39,7 @@ class BufferedOutput extends Output $this->buffer .= $message; if ($newline) { - $this->buffer .= "\n"; + $this->buffer .= PHP_EOL; } } } diff --git a/vendor/symfony/console/Output/ConsoleOutput.php b/vendor/symfony/console/Output/ConsoleOutput.php index f666c793..edef356c 100644 --- a/vendor/symfony/console/Output/ConsoleOutput.php +++ b/vendor/symfony/console/Output/ConsoleOutput.php @@ -14,28 +14,24 @@ namespace Symfony\Component\Console\Output; use Symfony\Component\Console\Formatter\OutputFormatterInterface; /** - * ConsoleOutput is the default class for all CLI output. It uses STDOUT. + * ConsoleOutput is the default class for all CLI output. It uses STDOUT and STDERR. * - * This class is a convenient wrapper around `StreamOutput`. + * This class is a convenient wrapper around `StreamOutput` for both STDOUT and STDERR. * * $output = new ConsoleOutput(); * * This is equivalent to: * * $output = new StreamOutput(fopen('php://stdout', 'w')); + * $stdErr = new StreamOutput(fopen('php://stderr', 'w')); * * @author Fabien Potencier <fabien@symfony.com> */ class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface { - /** - * @var StreamOutput - */ private $stderr; /** - * Constructor. - * * @param int $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface) * @param bool|null $decorated Whether to decorate messages (null for auto-guessing) * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter) @@ -139,9 +135,11 @@ class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface */ private function openOutputStream() { - $outputStream = $this->hasStdoutSupport() ? 'php://stdout' : 'php://output'; + if (!$this->hasStdoutSupport()) { + return fopen('php://output', 'w'); + } - return @fopen($outputStream, 'w') ?: fopen('php://output', 'w'); + return @fopen('php://stdout', 'w') ?: fopen('php://output', 'w'); } /** @@ -149,8 +147,6 @@ class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface */ private function openErrorStream() { - $errorStream = $this->hasStderrSupport() ? 'php://stderr' : 'php://output'; - - return fopen($errorStream, 'w'); + return fopen($this->hasStderrSupport() ? 'php://stderr' : 'php://output', 'w'); } } diff --git a/vendor/symfony/console/Output/ConsoleOutputInterface.php b/vendor/symfony/console/Output/ConsoleOutputInterface.php index 5eb4fc7a..b44ea7e0 100644 --- a/vendor/symfony/console/Output/ConsoleOutputInterface.php +++ b/vendor/symfony/console/Output/ConsoleOutputInterface.php @@ -26,10 +26,5 @@ interface ConsoleOutputInterface extends OutputInterface */ public function getErrorOutput(); - /** - * Sets the OutputInterface used for errors. - * - * @param OutputInterface $error - */ public function setErrorOutput(OutputInterface $error); } diff --git a/vendor/symfony/console/Output/NullOutput.php b/vendor/symfony/console/Output/NullOutput.php index 682f9a4d..218f285b 100644 --- a/vendor/symfony/console/Output/NullOutput.php +++ b/vendor/symfony/console/Output/NullOutput.php @@ -73,21 +73,33 @@ class NullOutput implements OutputInterface return self::VERBOSITY_QUIET; } + /** + * {@inheritdoc} + */ public function isQuiet() { return true; } + /** + * {@inheritdoc} + */ public function isVerbose() { return false; } + /** + * {@inheritdoc} + */ public function isVeryVerbose() { return false; } + /** + * {@inheritdoc} + */ public function isDebug() { return false; diff --git a/vendor/symfony/console/Output/Output.php b/vendor/symfony/console/Output/Output.php index 4476ffb5..371735e1 100644 --- a/vendor/symfony/console/Output/Output.php +++ b/vendor/symfony/console/Output/Output.php @@ -33,8 +33,6 @@ abstract class Output implements OutputInterface private $formatter; /** - * Constructor. - * * @param int $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface) * @param bool $decorated Whether to decorate messages * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter) @@ -94,21 +92,33 @@ abstract class Output implements OutputInterface return $this->verbosity; } + /** + * {@inheritdoc} + */ public function isQuiet() { return self::VERBOSITY_QUIET === $this->verbosity; } + /** + * {@inheritdoc} + */ public function isVerbose() { return self::VERBOSITY_VERBOSE <= $this->verbosity; } + /** + * {@inheritdoc} + */ public function isVeryVerbose() { return self::VERBOSITY_VERY_VERBOSE <= $this->verbosity; } + /** + * {@inheritdoc} + */ public function isDebug() { return self::VERBOSITY_DEBUG <= $this->verbosity; diff --git a/vendor/symfony/console/Output/OutputInterface.php b/vendor/symfony/console/Output/OutputInterface.php index 9a8290bd..cddfbb49 100644 --- a/vendor/symfony/console/Output/OutputInterface.php +++ b/vendor/symfony/console/Output/OutputInterface.php @@ -62,6 +62,34 @@ interface OutputInterface public function getVerbosity(); /** + * Returns whether verbosity is quiet (-q). + * + * @return bool true if verbosity is set to VERBOSITY_QUIET, false otherwise + */ + public function isQuiet(); + + /** + * Returns whether verbosity is verbose (-v). + * + * @return bool true if verbosity is set to VERBOSITY_VERBOSE, false otherwise + */ + public function isVerbose(); + + /** + * Returns whether verbosity is very verbose (-vv). + * + * @return bool true if verbosity is set to VERBOSITY_VERY_VERBOSE, false otherwise + */ + public function isVeryVerbose(); + + /** + * Returns whether verbosity is debug (-vvv). + * + * @return bool true if verbosity is set to VERBOSITY_DEBUG, false otherwise + */ + public function isDebug(); + + /** * Sets the decorated flag. * * @param bool $decorated Whether to decorate the messages @@ -75,11 +103,6 @@ interface OutputInterface */ public function isDecorated(); - /** - * Sets output formatter. - * - * @param OutputFormatterInterface $formatter - */ public function setFormatter(OutputFormatterInterface $formatter); /** diff --git a/vendor/symfony/console/Output/StreamOutput.php b/vendor/symfony/console/Output/StreamOutput.php index 9e6b7481..51cad9b1 100644 --- a/vendor/symfony/console/Output/StreamOutput.php +++ b/vendor/symfony/console/Output/StreamOutput.php @@ -33,8 +33,6 @@ class StreamOutput extends Output private $stream; /** - * Constructor. - * * @param resource $stream A stream resource * @param int $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface) * @param bool|null $decorated Whether to decorate messages (null for auto-guessing) @@ -85,7 +83,7 @@ class StreamOutput extends Output * * Colorization is disabled if not supported by the stream: * - * - Windows before 10.0.10586 without Ansicon, ConEmu or Mintty + * - Windows != 10.0.10586 without Ansicon, ConEmu or Mintty * - non tty consoles * * @return bool true if the stream supports colorization, false otherwise @@ -94,7 +92,7 @@ class StreamOutput extends Output { if (DIRECTORY_SEPARATOR === '\\') { return - 0 >= version_compare('10.0.10586', PHP_WINDOWS_VERSION_MAJOR.'.'.PHP_WINDOWS_VERSION_MINOR.'.'.PHP_WINDOWS_VERSION_BUILD) + '10.0.10586' === PHP_WINDOWS_VERSION_MAJOR.'.'.PHP_WINDOWS_VERSION_MINOR.'.'.PHP_WINDOWS_VERSION_BUILD || false !== getenv('ANSICON') || 'ON' === getenv('ConEmuANSI') || 'xterm' === getenv('TERM'); diff --git a/vendor/symfony/console/Question/ChoiceQuestion.php b/vendor/symfony/console/Question/ChoiceQuestion.php index 2c40638d..46cc72a3 100644 --- a/vendor/symfony/console/Question/ChoiceQuestion.php +++ b/vendor/symfony/console/Question/ChoiceQuestion.php @@ -26,14 +26,16 @@ class ChoiceQuestion extends Question private $errorMessage = 'Value "%s" is invalid'; /** - * Constructor. - * * @param string $question The question to ask to the user * @param array $choices The list of available choices * @param mixed $default The default answer to return */ public function __construct($question, array $choices, $default = null) { + if (!$choices) { + throw new \LogicException('Choice question must have at least 1 choice available.'); + } + parent::__construct($question, $default); $this->choices = $choices; @@ -58,7 +60,7 @@ class ChoiceQuestion extends Question * * @param bool $multiselect * - * @return ChoiceQuestion The current instance + * @return $this */ public function setMultiselect($multiselect) { @@ -69,6 +71,16 @@ class ChoiceQuestion extends Question } /** + * Returns whether the choices are multiselect. + * + * @return bool + */ + public function isMultiselect() + { + return $this->multiselect; + } + + /** * Gets the prompt for choices. * * @return string @@ -83,7 +95,7 @@ class ChoiceQuestion extends Question * * @param string $prompt * - * @return ChoiceQuestion The current instance + * @return $this */ public function setPrompt($prompt) { @@ -99,7 +111,7 @@ class ChoiceQuestion extends Question * * @param string $errorMessage * - * @return ChoiceQuestion The current instance + * @return $this */ public function setErrorMessage($errorMessage) { @@ -127,7 +139,7 @@ class ChoiceQuestion extends Question if ($multiselect) { // Check for a separated comma values - if (!preg_match('/^[a-zA-Z0-9_-]+(?:,[a-zA-Z0-9_-]+)*$/', $selectedChoices, $matches)) { + if (!preg_match('/^[^,]+(?:,[^,]+)*$/', $selectedChoices, $matches)) { throw new InvalidArgumentException(sprintf($errorMessage, $selected)); } $selectedChoices = explode(',', $selectedChoices); diff --git a/vendor/symfony/console/Question/ConfirmationQuestion.php b/vendor/symfony/console/Question/ConfirmationQuestion.php index 29d98879..40f54b4e 100644 --- a/vendor/symfony/console/Question/ConfirmationQuestion.php +++ b/vendor/symfony/console/Question/ConfirmationQuestion.php @@ -21,8 +21,6 @@ class ConfirmationQuestion extends Question private $trueAnswerRegex; /** - * Constructor. - * * @param string $question The question to ask to the user * @param bool $default The default answer to return, true or false * @param string $trueAnswerRegex A regex to match the "yes" answer diff --git a/vendor/symfony/console/Question/Question.php b/vendor/symfony/console/Question/Question.php index ab415c26..63afbc4c 100644 --- a/vendor/symfony/console/Question/Question.php +++ b/vendor/symfony/console/Question/Question.php @@ -31,8 +31,6 @@ class Question private $normalizer; /** - * Constructor. - * * @param string $question The question to ask to the user * @param mixed $default The default answer to return if the user enters nothing */ @@ -77,7 +75,7 @@ class Question * * @param bool $hidden * - * @return Question The current instance + * @return $this * * @throws LogicException In case the autocompleter is also used */ @@ -107,7 +105,7 @@ class Question * * @param bool $fallback * - * @return Question The current instance + * @return $this */ public function setHiddenFallback($fallback) { @@ -119,7 +117,7 @@ class Question /** * Gets values for the autocompleter. * - * @return null|array|\Traversable + * @return null|iterable */ public function getAutocompleterValues() { @@ -129,9 +127,9 @@ class Question /** * Sets values for the autocompleter. * - * @param null|array|\Traversable $values + * @param null|iterable $values * - * @return Question The current instance + * @return $this * * @throws InvalidArgumentException * @throws LogicException @@ -142,10 +140,8 @@ class Question $values = $this->isAssoc($values) ? array_merge(array_keys($values), array_values($values)) : array_values($values); } - if (null !== $values && !is_array($values)) { - 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.'); - } + if (null !== $values && !is_array($values) && !$values instanceof \Traversable) { + throw new InvalidArgumentException('Autocompleter values can be either an array, `null` or a `Traversable` object.'); } if ($this->hidden) { @@ -162,9 +158,9 @@ class Question * * @param null|callable $validator * - * @return Question The current instance + * @return $this */ - public function setValidator($validator) + public function setValidator(callable $validator = null) { $this->validator = $validator; @@ -188,9 +184,9 @@ class Question * * @param null|int $attempts * - * @return Question The current instance + * @return $this * - * @throws InvalidArgumentException In case the number of attempts is invalid. + * @throws InvalidArgumentException in case the number of attempts is invalid */ public function setMaxAttempts($attempts) { @@ -222,9 +218,9 @@ class Question * * @param callable $normalizer * - * @return Question The current instance + * @return $this */ - public function setNormalizer($normalizer) + public function setNormalizer(callable $normalizer) { $this->normalizer = $normalizer; diff --git a/vendor/symfony/console/Shell.php b/vendor/symfony/console/Shell.php deleted file mode 100644 index dacdf223..00000000 --- a/vendor/symfony/console/Shell.php +++ /dev/null @@ -1,233 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console; - -use Symfony\Component\Console\Exception\RuntimeException; -use Symfony\Component\Console\Input\StringInput; -use Symfony\Component\Console\Output\ConsoleOutput; -use Symfony\Component\Process\ProcessBuilder; -use Symfony\Component\Process\PhpExecutableFinder; - -/** - * A Shell wraps an Application to add shell capabilities to it. - * - * Support for history and completion only works with a PHP compiled - * with readline support (either --with-readline or --with-libedit) - * - * @deprecated since version 2.8, to be removed in 3.0. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Martin Hasoň <martin.hason@gmail.com> - */ -class Shell -{ - private $application; - private $history; - private $output; - private $hasReadline; - private $processIsolation = false; - - /** - * Constructor. - * - * If there is no readline support for the current PHP executable - * a \RuntimeException exception is thrown. - * - * @param Application $application An application instance - */ - public function __construct(Application $application) - { - @trigger_error('The '.__CLASS__.' class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED); - - $this->hasReadline = function_exists('readline'); - $this->application = $application; - $this->history = getenv('HOME').'/.history_'.$application->getName(); - $this->output = new ConsoleOutput(); - } - - /** - * Runs the shell. - */ - public function run() - { - $this->application->setAutoExit(false); - $this->application->setCatchExceptions(true); - - if ($this->hasReadline) { - readline_read_history($this->history); - readline_completion_function(array($this, 'autocompleter')); - } - - $this->output->writeln($this->getHeader()); - $php = null; - if ($this->processIsolation) { - $finder = new PhpExecutableFinder(); - $php = $finder->find(); - $this->output->writeln(<<<'EOF' -<info>Running with process isolation, you should consider this:</info> - * each command is executed as separate process, - * commands don't support interactivity, all params must be passed explicitly, - * commands output is not colorized. - -EOF - ); - } - - while (true) { - $command = $this->readline(); - - if (false === $command) { - $this->output->writeln("\n"); - - break; - } - - if ($this->hasReadline) { - readline_add_history($command); - readline_write_history($this->history); - } - - if ($this->processIsolation) { - $pb = new ProcessBuilder(); - - $process = $pb - ->add($php) - ->add($_SERVER['argv'][0]) - ->add($command) - ->inheritEnvironmentVariables(true) - ->getProcess() - ; - - $output = $this->output; - $process->run(function ($type, $data) use ($output) { - $output->writeln($data); - }); - - $ret = $process->getExitCode(); - } else { - $ret = $this->application->run(new StringInput($command), $this->output); - } - - if (0 !== $ret) { - $this->output->writeln(sprintf('<error>The command terminated with an error status (%s)</error>', $ret)); - } - } - } - - /** - * Returns the shell header. - * - * @return string The header string - */ - protected function getHeader() - { - return <<<EOF - -Welcome to the <info>{$this->application->getName()}</info> shell (<comment>{$this->application->getVersion()}</comment>). - -At the prompt, type <comment>help</comment> for some help, -or <comment>list</comment> to get a list of available commands. - -To exit the shell, type <comment>^D</comment>. - -EOF; - } - - /** - * Renders a prompt. - * - * @return string The prompt - */ - protected function getPrompt() - { - // using the formatter here is required when using readline - return $this->output->getFormatter()->format($this->application->getName().' > '); - } - - protected function getOutput() - { - return $this->output; - } - - protected function getApplication() - { - return $this->application; - } - - /** - * Tries to return autocompletion for the current entered text. - * - * @param string $text The last segment of the entered text - * - * @return bool|array A list of guessed strings or true - */ - private function autocompleter($text) - { - $info = readline_info(); - $text = substr($info['line_buffer'], 0, $info['end']); - - if ($info['point'] !== $info['end']) { - return true; - } - - // task name? - if (false === strpos($text, ' ') || !$text) { - return array_keys($this->application->all()); - } - - // options and arguments? - try { - $command = $this->application->find(substr($text, 0, strpos($text, ' '))); - } catch (\Exception $e) { - return true; - } - - $list = array('--help'); - foreach ($command->getDefinition()->getOptions() as $option) { - $list[] = '--'.$option->getName(); - } - - return $list; - } - - /** - * Reads a single line from standard input. - * - * @return string The single line from standard input - */ - private function readline() - { - if ($this->hasReadline) { - $line = readline($this->getPrompt()); - } else { - $this->output->write($this->getPrompt()); - $line = fgets(STDIN, 1024); - $line = (false === $line || '' === $line) ? false : rtrim($line); - } - - return $line; - } - - public function getProcessIsolation() - { - return $this->processIsolation; - } - - public function setProcessIsolation($processIsolation) - { - $this->processIsolation = (bool) $processIsolation; - - if ($this->processIsolation && !class_exists('Symfony\\Component\\Process\\Process')) { - throw new RuntimeException('Unable to isolate processes as the Symfony Process Component is not installed.'); - } - } -} diff --git a/vendor/symfony/console/Style/OutputStyle.php b/vendor/symfony/console/Style/OutputStyle.php index 8371bb53..ad886411 100644 --- a/vendor/symfony/console/Style/OutputStyle.php +++ b/vendor/symfony/console/Style/OutputStyle.php @@ -14,6 +14,7 @@ namespace Symfony\Component\Console\Style; use Symfony\Component\Console\Formatter\OutputFormatterInterface; use Symfony\Component\Console\Helper\ProgressBar; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Output\ConsoleOutputInterface; /** * Decorates output to add console style guide helpers. @@ -24,9 +25,6 @@ abstract class OutputStyle implements OutputInterface, StyleInterface { private $output; - /** - * @param OutputInterface $output - */ public function __construct(OutputInterface $output) { $this->output = $output; @@ -113,4 +111,45 @@ abstract class OutputStyle implements OutputInterface, StyleInterface { return $this->output->getFormatter(); } + + /** + * {@inheritdoc} + */ + public function isQuiet() + { + return $this->output->isQuiet(); + } + + /** + * {@inheritdoc} + */ + public function isVerbose() + { + return $this->output->isVerbose(); + } + + /** + * {@inheritdoc} + */ + public function isVeryVerbose() + { + return $this->output->isVeryVerbose(); + } + + /** + * {@inheritdoc} + */ + public function isDebug() + { + return $this->output->isDebug(); + } + + protected function getErrorOutput() + { + if (!$this->output instanceof ConsoleOutputInterface) { + return $this->output; + } + + return $this->output->getErrorOutput(); + } } diff --git a/vendor/symfony/console/Style/StyleInterface.php b/vendor/symfony/console/Style/StyleInterface.php index 2448547f..a9205e5a 100644 --- a/vendor/symfony/console/Style/StyleInterface.php +++ b/vendor/symfony/console/Style/StyleInterface.php @@ -34,8 +34,6 @@ interface StyleInterface /** * Formats a list. - * - * @param array $elements */ public function listing(array $elements); @@ -83,9 +81,6 @@ interface StyleInterface /** * Formats a table. - * - * @param array $headers - * @param array $rows */ public function table(array $headers, array $rows); diff --git a/vendor/symfony/console/Style/SymfonyStyle.php b/vendor/symfony/console/Style/SymfonyStyle.php index 53a7951e..3717f880 100644 --- a/vendor/symfony/console/Style/SymfonyStyle.php +++ b/vendor/symfony/console/Style/SymfonyStyle.php @@ -11,20 +11,19 @@ namespace Symfony\Component\Console\Style; -use Symfony\Component\Console\Application; use Symfony\Component\Console\Exception\RuntimeException; use Symfony\Component\Console\Formatter\OutputFormatter; use Symfony\Component\Console\Helper\Helper; use Symfony\Component\Console\Helper\ProgressBar; use Symfony\Component\Console\Helper\SymfonyQuestionHelper; use Symfony\Component\Console\Helper\Table; -use Symfony\Component\Console\Helper\TableCell; 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; use Symfony\Component\Console\Question\Question; +use Symfony\Component\Console\Terminal; /** * Output decorator helpers for the Symfony Style Guide. @@ -41,16 +40,13 @@ class SymfonyStyle extends OutputStyle private $lineLength; private $bufferedOutput; - /** - * @param InputInterface $input - * @param OutputInterface $output - */ public function __construct(InputInterface $input, OutputInterface $output) { $this->input = $input; $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); + $width = (new Terminal())->getWidth() ?: self::MAX_LINE_LENGTH; + $this->lineLength = min($width - (int) (DIRECTORY_SEPARATOR === '\\'), self::MAX_LINE_LENGTH); parent::__construct($output); } @@ -63,56 +59,14 @@ class SymfonyStyle extends OutputStyle * @param string|null $style The style to apply to the whole block * @param string $prefix The prefix for the block * @param bool $padding Whether to add vertical padding + * @param bool $escape Whether to escape the message */ - public function block($messages, $type = null, $style = null, $prefix = ' ', $padding = false) + public function block($messages, $type = null, $style = null, $prefix = ' ', $padding = false, $escape = true) { - $this->autoPrependBlock(); $messages = is_array($messages) ? array_values($messages) : array($messages); - $indentLength = 0; - $lines = array(); - - if (null !== $type) { - $typePrefix = sprintf('[%s] ', $type); - $indentLength = strlen($typePrefix); - $lineIndentation = str_repeat(' ', $indentLength); - } - - // wrap and add newlines for each element - foreach ($messages as $key => $message) { - $message = OutputFormatter::escape($message); - $lines = array_merge($lines, explode(PHP_EOL, wordwrap($message, $this->lineLength - Helper::strlen($prefix) - $indentLength, PHP_EOL, true))); - - // prefix each line with a number of spaces equivalent to the type length - if (null !== $type) { - foreach ($lines as &$line) { - $line = $lineIndentation === substr($line, 0, $indentLength) ? $line : $lineIndentation.$line; - } - } - if (count($messages) > 1 && $key < count($messages) - 1) { - $lines[] = ''; - } - } - - if (null !== $type) { - $lines[0] = substr_replace($lines[0], $typePrefix, 0, $indentLength); - } - - if ($padding && $this->isDecorated()) { - array_unshift($lines, ''); - $lines[] = ''; - } - - foreach ($lines as &$line) { - $line = sprintf('%s%s', $prefix, $line); - $line .= str_repeat(' ', $this->lineLength - Helper::strlenWithoutDecoration($this->getFormatter(), $line)); - - if ($style) { - $line = sprintf('<%s>%s</>', $style, $line); - } - } - - $this->writeln($lines); + $this->autoPrependBlock(); + $this->writeln($this->createBlock($messages, $type, $style, $prefix, $padding, $escape)); $this->newLine(); } @@ -123,7 +77,7 @@ class SymfonyStyle extends OutputStyle { $this->autoPrependBlock(); $this->writeln(array( - sprintf('<comment>%s</>', $message), + sprintf('<comment>%s</>', OutputFormatter::escapeTrailingBackslash($message)), sprintf('<comment>%s</>', str_repeat('=', Helper::strlenWithoutDecoration($this->getFormatter(), $message))), )); $this->newLine(); @@ -136,7 +90,7 @@ class SymfonyStyle extends OutputStyle { $this->autoPrependBlock(); $this->writeln(array( - sprintf('<comment>%s</>', $message), + sprintf('<comment>%s</>', OutputFormatter::escapeTrailingBackslash($message)), sprintf('<comment>%s</>', str_repeat('-', Helper::strlenWithoutDecoration($this->getFormatter(), $message))), )); $this->newLine(); @@ -176,12 +130,7 @@ class SymfonyStyle extends OutputStyle */ public function comment($message) { - $messages = is_array($message) ? array_values($message) : array($message); - foreach ($messages as &$message) { - $message = $this->getFormatter()->format($message); - } - - $this->block($messages, null, null, ' // '); + $this->block($message, null, null, '<fg=default;bg=default> // </>', false, false); } /** @@ -229,21 +178,13 @@ class SymfonyStyle extends OutputStyle */ public function table(array $headers, array $rows) { - array_walk_recursive($headers, function (&$value) { - if ($value instanceof TableCell) { - $value = new TableCell(sprintf('<info>%s</>', $value), array( - 'colspan' => $value->getColspan(), - 'rowspan' => $value->getRowspan(), - )); - } else { - $value = sprintf('<info>%s</>', $value); - } - }); + $style = clone Table::getStyleDefinition('symfony-style-guide'); + $style->setCellHeaderFormat('<info>%s</info>'); $table = new Table($this); $table->setHeaders($headers); $table->setRows($rows); - $table->setStyle('symfony-style-guide'); + $table->setStyle($style); $table->render(); $this->newLine(); @@ -338,8 +279,6 @@ class SymfonyStyle extends OutputStyle } /** - * @param Question $question - * * @return string */ public function askQuestion(Question $question) @@ -390,6 +329,16 @@ class SymfonyStyle extends OutputStyle } /** + * Returns a new instance which makes use of stderr if available. + * + * @return self + */ + public function getErrorStyle() + { + return new self($this->input, $this->getErrorOutput()); + } + + /** * @return ProgressBar */ private function getProgressBar() @@ -401,14 +350,6 @@ class SymfonyStyle extends OutputStyle return $this->progressBar; } - private function getTerminalWidth() - { - $application = new Application(); - $dimensions = $application->getTerminalDimensions(); - - return $dimensions[0] ?: self::MAX_LINE_LENGTH; - } - private function autoPrependBlock() { $chars = substr(str_replace(PHP_EOL, "\n", $this->bufferedOutput->fetch()), -2); @@ -437,4 +378,52 @@ class SymfonyStyle extends OutputStyle return substr($value, -4); }, array_merge(array($this->bufferedOutput->fetch()), (array) $messages)); } + + private function createBlock($messages, $type = null, $style = null, $prefix = ' ', $padding = false, $escape = false) + { + $indentLength = 0; + $prefixLength = Helper::strlenWithoutDecoration($this->getFormatter(), $prefix); + $lines = array(); + + if (null !== $type) { + $type = sprintf('[%s] ', $type); + $indentLength = strlen($type); + $lineIndentation = str_repeat(' ', $indentLength); + } + + // wrap and add newlines for each element + foreach ($messages as $key => $message) { + if ($escape) { + $message = OutputFormatter::escape($message); + } + + $lines = array_merge($lines, explode(PHP_EOL, wordwrap($message, $this->lineLength - $prefixLength - $indentLength, PHP_EOL, true))); + + if (count($messages) > 1 && $key < count($messages) - 1) { + $lines[] = ''; + } + } + + $firstLineIndex = 0; + if ($padding && $this->isDecorated()) { + $firstLineIndex = 1; + array_unshift($lines, ''); + $lines[] = ''; + } + + foreach ($lines as $i => &$line) { + if (null !== $type) { + $line = $firstLineIndex === $i ? $type.$line : $lineIndentation.$line; + } + + $line = $prefix.$line; + $line .= str_repeat(' ', $this->lineLength - Helper::strlenWithoutDecoration($this->getFormatter(), $line)); + + if ($style) { + $line = sprintf('<%s>%s</>', $style, $line); + } + } + + return $lines; + } } diff --git a/vendor/symfony/console/Terminal.php b/vendor/symfony/console/Terminal.php new file mode 100644 index 00000000..927dfc4d --- /dev/null +++ b/vendor/symfony/console/Terminal.php @@ -0,0 +1,137 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console; + +class Terminal +{ + private static $width; + private static $height; + + /** + * Gets the terminal width. + * + * @return int + */ + public function getWidth() + { + $width = getenv('COLUMNS'); + if (false !== $width) { + return (int) trim($width); + } + + if (null === self::$width) { + self::initDimensions(); + } + + return self::$width ?: 80; + } + + /** + * Gets the terminal height. + * + * @return int + */ + public function getHeight() + { + $height = getenv('LINES'); + if (false !== $height) { + return (int) trim($height); + } + + if (null === self::$height) { + self::initDimensions(); + } + + return self::$height ?: 50; + } + + private static function initDimensions() + { + if ('\\' === DIRECTORY_SEPARATOR) { + if (preg_match('/^(\d+)x(\d+)(?: \((\d+)x(\d+)\))?$/', trim(getenv('ANSICON')), $matches)) { + // extract [w, H] from "wxh (WxH)" + // or [w, h] from "wxh" + self::$width = (int) $matches[1]; + self::$height = isset($matches[4]) ? (int) $matches[4] : (int) $matches[2]; + } elseif (null !== $dimensions = self::getConsoleMode()) { + // extract [w, h] from "wxh" + self::$width = (int) $dimensions[0]; + self::$height = (int) $dimensions[1]; + } + } elseif ($sttyString = self::getSttyColumns()) { + if (preg_match('/rows.(\d+);.columns.(\d+);/i', $sttyString, $matches)) { + // extract [w, h] from "rows h; columns w;" + self::$width = (int) $matches[2]; + self::$height = (int) $matches[1]; + } elseif (preg_match('/;.(\d+).rows;.(\d+).columns/i', $sttyString, $matches)) { + // extract [w, h] from "; h rows; w columns" + self::$width = (int) $matches[2]; + self::$height = (int) $matches[1]; + } + } + } + + /** + * Runs and parses mode CON if it's available, suppressing any error output. + * + * @return int[]|null An array composed of the width and the height or null if it could not be parsed + */ + private static function getConsoleMode() + { + if (!function_exists('proc_open')) { + return; + } + + $descriptorspec = array( + 1 => array('pipe', 'w'), + 2 => array('pipe', 'w'), + ); + $process = proc_open('mode CON', $descriptorspec, $pipes, null, null, array('suppress_errors' => true)); + if (is_resource($process)) { + $info = stream_get_contents($pipes[1]); + fclose($pipes[1]); + fclose($pipes[2]); + proc_close($process); + + if (preg_match('/--------+\r?\n.+?(\d+)\r?\n.+?(\d+)\r?\n/', $info, $matches)) { + return array((int) $matches[2], (int) $matches[1]); + } + } + } + + /** + * Runs and parses stty -a if it's available, suppressing any error output. + * + * @return string|null + */ + private static function getSttyColumns() + { + if (!function_exists('proc_open')) { + return; + } + + $descriptorspec = array( + 1 => array('pipe', 'w'), + 2 => array('pipe', 'w'), + ); + + $process = proc_open('stty -a | grep columns', $descriptorspec, $pipes, null, null, array('suppress_errors' => true)); + if (is_resource($process)) { + $info = stream_get_contents($pipes[1]); + fclose($pipes[1]); + fclose($pipes[2]); + proc_close($process); + + return $info; + } + } +} diff --git a/vendor/symfony/console/Tester/ApplicationTester.php b/vendor/symfony/console/Tester/ApplicationTester.php index da8a19ce..c0f8c720 100644 --- a/vendor/symfony/console/Tester/ApplicationTester.php +++ b/vendor/symfony/console/Tester/ApplicationTester.php @@ -14,6 +14,7 @@ namespace Symfony\Component\Console\Tester; use Symfony\Component\Console\Application; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\ConsoleOutput; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\StreamOutput; @@ -31,14 +32,13 @@ class ApplicationTester { private $application; private $input; - private $output; private $statusCode; - /** - * Constructor. - * - * @param Application $application An Application instance to test. + * @var OutputInterface */ + private $output; + private $captureStreamsIndependently = false; + public function __construct(Application $application) { $this->application = $application; @@ -49,9 +49,10 @@ class ApplicationTester * * Available options: * - * * interactive: Sets the input interactive flag - * * decorated: Sets the output decorated flag - * * verbosity: Sets the output verbosity flag + * * interactive: Sets the input interactive flag + * * decorated: Sets the output decorated flag + * * verbosity: Sets the output verbosity flag + * * capture_stderr_separately: Make output of stdOut and stdErr separately available * * @param array $input An array of arguments and options * @param array $options An array of options @@ -65,12 +66,35 @@ class ApplicationTester $this->input->setInteractive($options['interactive']); } - $this->output = new StreamOutput(fopen('php://memory', 'w', false)); - if (isset($options['decorated'])) { - $this->output->setDecorated($options['decorated']); - } - if (isset($options['verbosity'])) { - $this->output->setVerbosity($options['verbosity']); + $this->captureStreamsIndependently = array_key_exists('capture_stderr_separately', $options) && $options['capture_stderr_separately']; + if (!$this->captureStreamsIndependently) { + $this->output = new StreamOutput(fopen('php://memory', 'w', false)); + if (isset($options['decorated'])) { + $this->output->setDecorated($options['decorated']); + } + if (isset($options['verbosity'])) { + $this->output->setVerbosity($options['verbosity']); + } + } else { + $this->output = new ConsoleOutput( + isset($options['verbosity']) ? $options['verbosity'] : ConsoleOutput::VERBOSITY_NORMAL, + isset($options['decorated']) ? $options['decorated'] : null + ); + + $errorOutput = new StreamOutput(fopen('php://memory', 'w', false)); + $errorOutput->setFormatter($this->output->getFormatter()); + $errorOutput->setVerbosity($this->output->getVerbosity()); + $errorOutput->setDecorated($this->output->isDecorated()); + + $reflectedOutput = new \ReflectionObject($this->output); + $strErrProperty = $reflectedOutput->getProperty('stderr'); + $strErrProperty->setAccessible(true); + $strErrProperty->setValue($this->output, $errorOutput); + + $reflectedParent = $reflectedOutput->getParentClass(); + $streamProperty = $reflectedParent->getProperty('stream'); + $streamProperty->setAccessible(true); + $streamProperty->setValue($this->output, fopen('php://memory', 'w', false)); } return $this->statusCode = $this->application->run($this->input, $this->output); @@ -97,6 +121,30 @@ class ApplicationTester } /** + * Gets the output written to STDERR by the application. + * + * @param bool $normalize Whether to normalize end of lines to \n or not + * + * @return string + */ + public function getErrorOutput($normalize = false) + { + if (!$this->captureStreamsIndependently) { + throw new \LogicException('The error output is not available when the tester is run without "capture_stderr_separately" option set.'); + } + + rewind($this->output->getErrorOutput()->getStream()); + + $display = stream_get_contents($this->output->getErrorOutput()->getStream()); + + if ($normalize) { + $display = str_replace(PHP_EOL, "\n", $display); + } + + return $display; + } + + /** * Gets the input instance used by the last execution of the application. * * @return InputInterface The current input instance diff --git a/vendor/symfony/console/Tester/CommandTester.php b/vendor/symfony/console/Tester/CommandTester.php index 8d6486e1..39723b26 100644 --- a/vendor/symfony/console/Tester/CommandTester.php +++ b/vendor/symfony/console/Tester/CommandTester.php @@ -21,19 +21,16 @@ use Symfony\Component\Console\Output\OutputInterface; * Eases the testing of console commands. * * @author Fabien Potencier <fabien@symfony.com> + * @author Robin Chalas <robin.chalas@gmail.com> */ class CommandTester { private $command; private $input; private $output; + private $inputs = array(); private $statusCode; - /** - * Constructor. - * - * @param Command $command A Command instance to test. - */ public function __construct(Command $command) { $this->command = $command; @@ -65,14 +62,16 @@ class CommandTester } $this->input = new ArrayInput($input); + if ($this->inputs) { + $this->input->setStream(self::createStream($this->inputs)); + } + if (isset($options['interactive'])) { $this->input->setInteractive($options['interactive']); } $this->output = new StreamOutput(fopen('php://memory', 'w', false)); - if (isset($options['decorated'])) { - $this->output->setDecorated($options['decorated']); - } + $this->output->setDecorated(isset($options['decorated']) ? $options['decorated'] : false); if (isset($options['verbosity'])) { $this->output->setVerbosity($options['verbosity']); } @@ -129,4 +128,29 @@ class CommandTester { return $this->statusCode; } + + /** + * Sets the user inputs. + * + * @param array $inputs An array of strings representing each input + * passed to the command input stream + * + * @return CommandTester + */ + public function setInputs(array $inputs) + { + $this->inputs = $inputs; + + return $this; + } + + private static function createStream(array $inputs) + { + $stream = fopen('php://memory', 'r+', false); + + fwrite($stream, implode(PHP_EOL, $inputs)); + rewind($stream); + + return $stream; + } } diff --git a/vendor/symfony/console/Tests/ApplicationTest.php b/vendor/symfony/console/Tests/ApplicationTest.php index 927fa0bd..4e1f8811 100644 --- a/vendor/symfony/console/Tests/ApplicationTest.php +++ b/vendor/symfony/console/Tests/ApplicationTest.php @@ -11,7 +11,11 @@ namespace Symfony\Component\Console\Tests; +use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Application; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\CommandLoader\FactoryCommandLoader; +use Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass; use Symfony\Component\Console\Helper\HelperSet; use Symfony\Component\Console\Helper\FormatterHelper; use Symfony\Component\Console\Input\ArgvInput; @@ -26,11 +30,14 @@ use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\StreamOutput; use Symfony\Component\Console\Tester\ApplicationTester; use Symfony\Component\Console\Event\ConsoleCommandEvent; +use Symfony\Component\Console\Event\ConsoleErrorEvent; use Symfony\Component\Console\Event\ConsoleExceptionEvent; use Symfony\Component\Console\Event\ConsoleTerminateEvent; +use Symfony\Component\Console\Exception\CommandNotFoundException; +use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\EventDispatcher\EventDispatcher; -class ApplicationTest extends \PHPUnit_Framework_TestCase +class ApplicationTest extends TestCase { protected static $fixturesPath; @@ -38,11 +45,14 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase { self::$fixturesPath = realpath(__DIR__.'/Fixtures/'); require_once self::$fixturesPath.'/FooCommand.php'; + require_once self::$fixturesPath.'/FooOptCommand.php'; require_once self::$fixturesPath.'/Foo1Command.php'; require_once self::$fixturesPath.'/Foo2Command.php'; require_once self::$fixturesPath.'/Foo3Command.php'; require_once self::$fixturesPath.'/Foo4Command.php'; require_once self::$fixturesPath.'/Foo5Command.php'; + require_once self::$fixturesPath.'/FooSameCaseUppercaseCommand.php'; + require_once self::$fixturesPath.'/FooSameCaseLowercaseCommand.php'; require_once self::$fixturesPath.'/FoobarCommand.php'; require_once self::$fixturesPath.'/BarBucCommand.php'; require_once self::$fixturesPath.'/FooSubnamespaced1Command.php'; @@ -91,7 +101,7 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase public function testGetLongVersion() { $application = new Application('foo', 'bar'); - $this->assertEquals('<info>foo</info> version <comment>bar</comment>', $application->getLongVersion(), '->getLongVersion() returns the long version of the application'); + $this->assertEquals('foo <info>bar</info>', $application->getLongVersion(), '->getLongVersion() returns the long version of the application'); } public function testHelp() @@ -111,6 +121,25 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase $this->assertCount(1, $commands, '->all() takes a namespace as its first argument'); } + public function testAllWithCommandLoader() + { + $application = new Application(); + $commands = $application->all(); + $this->assertInstanceOf('Symfony\\Component\\Console\\Command\\HelpCommand', $commands['help'], '->all() returns the registered commands'); + + $application->add(new \FooCommand()); + $commands = $application->all('foo'); + $this->assertCount(1, $commands, '->all() takes a namespace as its first argument'); + + $application->setCommandLoader(new FactoryCommandLoader(array( + 'foo:bar1' => function () { return new \Foo1Command(); }, + ))); + $commands = $application->all('foo'); + $this->assertCount(2, $commands, '->all() takes a namespace as its first argument'); + $this->assertInstanceOf(\FooCommand::class, $commands['foo:bar'], '->all() returns the registered commands'); + $this->assertInstanceOf(\Foo1Command::class, $commands['foo:bar1'], '->all() returns the registered commands'); + } + public function testRegister() { $application = new Application(); @@ -163,6 +192,30 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase $this->assertInstanceOf('Symfony\Component\Console\Command\HelpCommand', $command, '->get() returns the help command if --help is provided as the input'); } + public function testHasGetWithCommandLoader() + { + $application = new Application(); + $this->assertTrue($application->has('list'), '->has() returns true if a named command is registered'); + $this->assertFalse($application->has('afoobar'), '->has() returns false if a named command is not registered'); + + $application->add($foo = new \FooCommand()); + $this->assertTrue($application->has('afoobar'), '->has() returns true if an alias is registered'); + $this->assertEquals($foo, $application->get('foo:bar'), '->get() returns a command by name'); + $this->assertEquals($foo, $application->get('afoobar'), '->get() returns a command by alias'); + + $application->setCommandLoader(new FactoryCommandLoader(array( + 'foo:bar1' => function () { return new \Foo1Command(); }, + ))); + + $this->assertTrue($application->has('afoobar'), '->has() returns true if an instance is registered for an alias even with command loader'); + $this->assertEquals($foo, $application->get('foo:bar'), '->get() returns an instance by name even with command loader'); + $this->assertEquals($foo, $application->get('afoobar'), '->get() returns an instance by alias even with command loader'); + $this->assertTrue($application->has('foo:bar1'), '->has() returns true for commands registered in the loader'); + $this->assertInstanceOf(\Foo1Command::class, $foo1 = $application->get('foo:bar1'), '->get() returns a command by name from the command loader'); + $this->assertTrue($application->has('afoobar1'), '->has() returns true for commands registered in the loader'); + $this->assertEquals($foo1, $application->get('afoobar1'), '->get() returns a command by name from the command loader'); + } + public function testSilentHelp() { $application = new Application(); @@ -176,7 +229,7 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase } /** - * @expectedException Symfony\Component\Console\Exception\CommandNotFoundException + * @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException * @expectedExceptionMessage The command "foofoo" does not exist. */ public function testGetInvalidCommand() @@ -211,21 +264,27 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase $this->assertEquals('foo', $application->findNamespace('foo'), '->findNamespace() returns commands even if the commands are only contained in subnamespaces'); } - /** - * @expectedException Symfony\Component\Console\Exception\CommandNotFoundException - * @expectedExceptionMessage The namespace "f" is ambiguous (foo, foo1). - */ public function testFindAmbiguousNamespace() { $application = new Application(); $application->add(new \BarBucCommand()); $application->add(new \FooCommand()); $application->add(new \Foo2Command()); + + $expectedMsg = "The namespace \"f\" is ambiguous.\nDid you mean one of these?\n foo\n foo1"; + + if (method_exists($this, 'expectException')) { + $this->expectException(CommandNotFoundException::class); + $this->expectExceptionMessage($expectedMsg); + } else { + $this->setExpectedException(CommandNotFoundException::class, $expectedMsg); + } + $application->findNamespace('f'); } /** - * @expectedException Symfony\Component\Console\Exception\CommandNotFoundException + * @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException * @expectedExceptionMessage There are no commands defined in the "bar" namespace. */ public function testFindInvalidNamespace() @@ -235,7 +294,7 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase } /** - * @expectedException Symfony\Component\Console\Exception\CommandNotFoundException + * @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException * @expectedExceptionMessage Command "foo1" is not defined */ public function testFindUniqueNameButNamespaceName() @@ -260,12 +319,66 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase $this->assertInstanceOf('FooCommand', $application->find('a'), '->find() returns a command if the abbreviation exists for an alias'); } + public function testFindCaseSensitiveFirst() + { + $application = new Application(); + $application->add(new \FooSameCaseUppercaseCommand()); + $application->add(new \FooSameCaseLowercaseCommand()); + + $this->assertInstanceOf('FooSameCaseUppercaseCommand', $application->find('f:B'), '->find() returns a command if the abbreviation is the correct case'); + $this->assertInstanceOf('FooSameCaseUppercaseCommand', $application->find('f:BAR'), '->find() returns a command if the abbreviation is the correct case'); + $this->assertInstanceOf('FooSameCaseLowercaseCommand', $application->find('f:b'), '->find() returns a command if the abbreviation is the correct case'); + $this->assertInstanceOf('FooSameCaseLowercaseCommand', $application->find('f:bar'), '->find() returns a command if the abbreviation is the correct case'); + } + + public function testFindCaseInsensitiveAsFallback() + { + $application = new Application(); + $application->add(new \FooSameCaseLowercaseCommand()); + + $this->assertInstanceOf('FooSameCaseLowercaseCommand', $application->find('f:b'), '->find() returns a command if the abbreviation is the correct case'); + $this->assertInstanceOf('FooSameCaseLowercaseCommand', $application->find('f:B'), '->find() will fallback to case insensitivity'); + $this->assertInstanceOf('FooSameCaseLowercaseCommand', $application->find('FoO:BaR'), '->find() will fallback to case insensitivity'); + } + + /** + * @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException + * @expectedExceptionMessage Command "FoO:BaR" is ambiguous + */ + public function testFindCaseInsensitiveSuggestions() + { + $application = new Application(); + $application->add(new \FooSameCaseLowercaseCommand()); + $application->add(new \FooSameCaseUppercaseCommand()); + + $this->assertInstanceOf('FooSameCaseLowercaseCommand', $application->find('FoO:BaR'), '->find() will find two suggestions with case insensitivity'); + } + + public function testFindWithCommandLoader() + { + $application = new Application(); + $application->setCommandLoader(new FactoryCommandLoader(array( + 'foo:bar' => $f = function () { return new \FooCommand(); }, + ))); + + $this->assertInstanceOf('FooCommand', $application->find('foo:bar'), '->find() returns a command if its name exists'); + $this->assertInstanceOf('Symfony\Component\Console\Command\HelpCommand', $application->find('h'), '->find() returns a command if its name exists'); + $this->assertInstanceOf('FooCommand', $application->find('f:bar'), '->find() returns a command if the abbreviation for the namespace exists'); + $this->assertInstanceOf('FooCommand', $application->find('f:b'), '->find() returns a command if the abbreviation for the namespace and the command name exist'); + $this->assertInstanceOf('FooCommand', $application->find('a'), '->find() returns a command if the abbreviation exists for an alias'); + } + /** * @dataProvider provideAmbiguousAbbreviations */ public function testFindWithAmbiguousAbbreviations($abbreviation, $expectedExceptionMessage) { - $this->setExpectedException('Symfony\Component\Console\Exception\CommandNotFoundException', $expectedExceptionMessage); + if (method_exists($this, 'expectException')) { + $this->expectException('Symfony\Component\Console\Exception\CommandNotFoundException'); + $this->expectExceptionMessage($expectedExceptionMessage); + } else { + $this->setExpectedException('Symfony\Component\Console\Exception\CommandNotFoundException', $expectedExceptionMessage); + } $application = new Application(); $application->add(new \FooCommand()); @@ -279,8 +392,20 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase { return array( array('f', 'Command "f" is not defined.'), - array('a', 'Command "a" is ambiguous (afoobar, afoobar1 and 1 more).'), - array('foo:b', 'Command "foo:b" is ambiguous (foo:bar, foo:bar1 and 1 more).'), + array( + 'a', + "Command \"a\" is ambiguous.\nDid you mean one of these?\n". + " afoobar The foo:bar command\n". + " afoobar1 The foo:bar1 command\n". + ' afoobar2 The foo1:bar command', + ), + array( + 'foo:b', + "Command \"foo:b\" is ambiguous.\nDid you mean one of these?\n". + " foo:bar The foo:bar command\n". + " foo:bar1 The foo:bar1 command\n". + ' foo1:bar The foo1:bar command', + ), ); } @@ -313,7 +438,7 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase /** * @dataProvider provideInvalidCommandNamesSingle - * @expectedException Symfony\Component\Console\Exception\CommandNotFoundException + * @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException * @expectedExceptionMessage Did you mean this */ public function testFindAlternativeExceptionMessageSingle($name) @@ -326,8 +451,8 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase public function provideInvalidCommandNamesSingle() { return array( - array('foo3:baR'), - array('foO3:bar'), + array('foo3:barr'), + array('fooo3:bar'), ); } @@ -425,7 +550,7 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase $application->add(new \FooCommand()); $application->add(new \Foo1Command()); $application->add(new \Foo2Command()); - $application->add(new \foo3Command()); + $application->add(new \Foo3Command()); try { $application->find('Unknown-namespace:Unknown-command'); @@ -452,9 +577,39 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase } } + public function testFindAlternativesOutput() + { + $application = new Application(); + + $application->add(new \FooCommand()); + $application->add(new \Foo1Command()); + $application->add(new \Foo2Command()); + $application->add(new \Foo3Command()); + + $expectedAlternatives = array( + 'afoobar', + 'afoobar1', + 'afoobar2', + 'foo1:bar', + 'foo3:bar', + 'foo:bar', + 'foo:bar1', + ); + + try { + $application->find('foo'); + $this->fail('->find() throws a CommandNotFoundException if command is not defined'); + } catch (\Exception $e) { + $this->assertInstanceOf('Symfony\Component\Console\Exception\CommandNotFoundException', $e, '->find() throws a CommandNotFoundException if command is not defined'); + $this->assertSame($expectedAlternatives, $e->getAlternatives()); + + $this->assertRegExp('/Command "foo" is not defined\..*Did you mean one of these\?.*/Ums', $e->getMessage()); + } + } + public function testFindNamespaceDoesNotFailOnDeepSimilarNamespaces() { - $application = $this->getMock('Symfony\Component\Console\Application', array('getNamespaces')); + $application = $this->getMockBuilder('Symfony\Component\Console\Application')->setMethods(array('getNamespaces'))->getMock(); $application->expects($this->once()) ->method('getNamespaces') ->will($this->returnValue(array('foo:sublong', 'bar:sub'))); @@ -463,7 +618,7 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase } /** - * @expectedException Symfony\Component\Console\Exception\CommandNotFoundException + * @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException * @expectedExceptionMessage Command "foo::bar" is not defined. */ public function testFindWithDoubleColonInNameThrowsException() @@ -476,17 +631,21 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase public function testSetCatchExceptions() { - $application = $this->getMock('Symfony\Component\Console\Application', array('getTerminalWidth')); + $application = new Application(); $application->setAutoExit(false); - $application->expects($this->any()) - ->method('getTerminalWidth') - ->will($this->returnValue(120)); + putenv('COLUMNS=120'); $tester = new ApplicationTester($application); $application->setCatchExceptions(true); + $this->assertTrue($application->areExceptionsCaught()); + $tester->run(array('command' => 'foo'), array('decorated' => false)); $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception1.txt', $tester->getDisplay(true), '->setCatchExceptions() sets the catch exception flag'); + $tester->run(array('command' => 'foo'), array('decorated' => false, 'capture_stderr_separately' => true)); + $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception1.txt', $tester->getErrorOutput(true), '->setCatchExceptions() sets the catch exception flag'); + $this->assertSame('', $tester->getDisplay(true)); + $application->setCatchExceptions(false); try { $tester->run(array('command' => 'foo'), array('decorated' => false)); @@ -497,96 +656,114 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase } } - /** - * @group legacy - */ - public function testLegacyAsText() + public function testAutoExitSetting() { $application = new Application(); - $application->add(new \FooCommand()); - $this->ensureStaticCommandHelp($application); - $this->assertStringEqualsFile(self::$fixturesPath.'/application_astext1.txt', $this->normalizeLineBreaks($application->asText()), '->asText() returns a text representation of the application'); - $this->assertStringEqualsFile(self::$fixturesPath.'/application_astext2.txt', $this->normalizeLineBreaks($application->asText('foo')), '->asText() returns a text representation of the application'); - } + $this->assertTrue($application->isAutoExitEnabled()); - /** - * @group legacy - */ - public function testLegacyAsXml() - { - $application = new Application(); - $application->add(new \FooCommand()); - $this->ensureStaticCommandHelp($application); - $this->assertXmlStringEqualsXmlFile(self::$fixturesPath.'/application_asxml1.txt', $application->asXml(), '->asXml() returns an XML representation of the application'); - $this->assertXmlStringEqualsXmlFile(self::$fixturesPath.'/application_asxml2.txt', $application->asXml('foo'), '->asXml() returns an XML representation of the application'); + $application->setAutoExit(false); + $this->assertFalse($application->isAutoExitEnabled()); } public function testRenderException() { - $application = $this->getMock('Symfony\Component\Console\Application', array('getTerminalWidth')); + $application = new Application(); $application->setAutoExit(false); - $application->expects($this->any()) - ->method('getTerminalWidth') - ->will($this->returnValue(120)); + putenv('COLUMNS=120'); $tester = new ApplicationTester($application); - $tester->run(array('command' => 'foo'), array('decorated' => false)); - $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception1.txt', $tester->getDisplay(true), '->renderException() renders a pretty exception'); + $tester->run(array('command' => 'foo'), array('decorated' => false, 'capture_stderr_separately' => true)); + $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception1.txt', $tester->getErrorOutput(true), '->renderException() renders a pretty exception'); - $tester->run(array('command' => 'foo'), array('decorated' => false, 'verbosity' => Output::VERBOSITY_VERBOSE)); - $this->assertContains('Exception trace', $tester->getDisplay(), '->renderException() renders a pretty exception with a stack trace when verbosity is verbose'); + $tester->run(array('command' => 'foo'), array('decorated' => false, 'verbosity' => Output::VERBOSITY_VERBOSE, 'capture_stderr_separately' => true)); + $this->assertContains('Exception trace', $tester->getErrorOutput(), '->renderException() renders a pretty exception with a stack trace when verbosity is verbose'); - $tester->run(array('command' => 'list', '--foo' => true), array('decorated' => false)); - $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception2.txt', $tester->getDisplay(true), '->renderException() renders the command synopsis when an exception occurs in the context of a command'); + $tester->run(array('command' => 'list', '--foo' => true), array('decorated' => false, 'capture_stderr_separately' => true)); + $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception2.txt', $tester->getErrorOutput(true), '->renderException() renders the command synopsis when an exception occurs in the context of a command'); $application->add(new \Foo3Command()); $tester = new ApplicationTester($application); - $tester->run(array('command' => 'foo3:bar'), array('decorated' => false)); - $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception3.txt', $tester->getDisplay(true), '->renderException() renders a pretty exceptions with previous exceptions'); + $tester->run(array('command' => 'foo3:bar'), array('decorated' => false, 'capture_stderr_separately' => true)); + $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception3.txt', $tester->getErrorOutput(true), '->renderException() renders a pretty exceptions with previous exceptions'); + + $tester->run(array('command' => 'foo3:bar'), array('decorated' => false, 'verbosity' => Output::VERBOSITY_VERBOSE)); + $this->assertRegExp('/\[Exception\]\s*First exception/', $tester->getDisplay(), '->renderException() renders a pretty exception without code exception when code exception is default and verbosity is verbose'); + $this->assertRegExp('/\[Exception\]\s*Second exception/', $tester->getDisplay(), '->renderException() renders a pretty exception without code exception when code exception is 0 and verbosity is verbose'); + $this->assertRegExp('/\[Exception \(404\)\]\s*Third exception/', $tester->getDisplay(), '->renderException() renders a pretty exception with code exception when code exception is 404 and verbosity is verbose'); $tester->run(array('command' => 'foo3:bar'), array('decorated' => true)); $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception3decorated.txt', $tester->getDisplay(true), '->renderException() renders a pretty exceptions with previous exceptions'); - $application = $this->getMock('Symfony\Component\Console\Application', array('getTerminalWidth')); + $tester->run(array('command' => 'foo3:bar'), array('decorated' => true, 'capture_stderr_separately' => true)); + $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception3decorated.txt', $tester->getErrorOutput(true), '->renderException() renders a pretty exceptions with previous exceptions'); + + $application = new Application(); $application->setAutoExit(false); - $application->expects($this->any()) - ->method('getTerminalWidth') - ->will($this->returnValue(32)); + putenv('COLUMNS=32'); $tester = new ApplicationTester($application); - $tester->run(array('command' => 'foo'), array('decorated' => false)); - $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception4.txt', $tester->getDisplay(true), '->renderException() wraps messages when they are bigger than the terminal'); + $tester->run(array('command' => 'foo'), array('decorated' => false, 'capture_stderr_separately' => true)); + $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception4.txt', $tester->getErrorOutput(true), '->renderException() wraps messages when they are bigger than the terminal'); + putenv('COLUMNS=120'); } public function testRenderExceptionWithDoubleWidthCharacters() { - $application = $this->getMock('Symfony\Component\Console\Application', array('getTerminalWidth')); + $application = new Application(); $application->setAutoExit(false); - $application->expects($this->any()) - ->method('getTerminalWidth') - ->will($this->returnValue(120)); + putenv('COLUMNS=120'); $application->register('foo')->setCode(function () { throw new \Exception('エラーメッセージ'); }); $tester = new ApplicationTester($application); - $tester->run(array('command' => 'foo'), array('decorated' => false)); - $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception_doublewidth1.txt', $tester->getDisplay(true), '->renderException() renders a pretty exceptions with previous exceptions'); + $tester->run(array('command' => 'foo'), array('decorated' => false, 'capture_stderr_separately' => true)); + $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception_doublewidth1.txt', $tester->getErrorOutput(true), '->renderException() renders a pretty exceptions with previous exceptions'); + + $tester->run(array('command' => 'foo'), array('decorated' => true, 'capture_stderr_separately' => true)); + $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception_doublewidth1decorated.txt', $tester->getErrorOutput(true), '->renderException() renders a pretty exceptions with previous exceptions'); + + $application = new Application(); + $application->setAutoExit(false); + putenv('COLUMNS=32'); + $application->register('foo')->setCode(function () { + throw new \Exception('コマンドの実行中にエラーが発生しました。'); + }); + $tester = new ApplicationTester($application); + $tester->run(array('command' => 'foo'), array('decorated' => false, 'capture_stderr_separately' => true)); + $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception_doublewidth2.txt', $tester->getErrorOutput(true), '->renderException() wraps messages when they are bigger than the terminal'); + putenv('COLUMNS=120'); + } + + public function testRenderExceptionEscapesLines() + { + $application = new Application(); + $application->setAutoExit(false); + putenv('COLUMNS=22'); + $application->register('foo')->setCode(function () { + throw new \Exception('dont break here <info>!</info>'); + }); + $tester = new ApplicationTester($application); - $tester->run(array('command' => 'foo'), array('decorated' => true)); - $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception_doublewidth1decorated.txt', $tester->getDisplay(true), '->renderException() renders a pretty exceptions with previous exceptions'); + $tester->run(array('command' => 'foo'), array('decorated' => false)); + $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception_escapeslines.txt', $tester->getDisplay(true), '->renderException() escapes lines containing formatting'); + putenv('COLUMNS=120'); + } - $application = $this->getMock('Symfony\Component\Console\Application', array('getTerminalWidth')); + public function testRenderExceptionLineBreaks() + { + $application = $this->getMockBuilder('Symfony\Component\Console\Application')->setMethods(array('getTerminalWidth'))->getMock(); $application->setAutoExit(false); $application->expects($this->any()) ->method('getTerminalWidth') - ->will($this->returnValue(32)); + ->will($this->returnValue(120)); $application->register('foo')->setCode(function () { - throw new \Exception('コマンドの実行中にエラーが発生しました。'); + throw new \InvalidArgumentException("\n\nline 1 with extra spaces \nline 2\n\nline 4\n"); }); $tester = new ApplicationTester($application); + $tester->run(array('command' => 'foo'), array('decorated' => false)); - $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception_doublewidth2.txt', $tester->getDisplay(true), '->renderException() wraps messages when they are bigger than the terminal'); + $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception_linebreaks.txt', $tester->getDisplay(true), '->renderException() keep multiple line breaks'); } public function testRun() @@ -640,9 +817,11 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase $tester->run(array('command' => 'list', '--quiet' => true)); $this->assertSame('', $tester->getDisplay(), '->run() removes all output if --quiet is passed'); + $this->assertFalse($tester->getInput()->isInteractive(), '->run() sets off the interactive mode if --quiet is passed'); $tester->run(array('command' => 'list', '-q' => true)); $this->assertSame('', $tester->getDisplay(), '->run() removes all output if -q is passed'); + $this->assertFalse($tester->getInput()->isInteractive(), '->run() sets off the interactive mode if -q is passed'); $tester->run(array('command' => 'list', '--verbose' => true)); $this->assertSame(Output::VERBOSITY_VERBOSE, $tester->getOutput()->getVerbosity(), '->run() sets the output to verbose if --verbose is passed'); @@ -700,19 +879,23 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase $input = new ArgvInput(array('cli.php', '-v', 'foo:bar')); $application->run($input, $output); + $this->addToAssertionCount(1); + $input = new ArgvInput(array('cli.php', '--verbose', 'foo:bar')); $application->run($input, $output); + + $this->addToAssertionCount(1); } public function testRunReturnsIntegerExitCode() { $exception = new \Exception('', 4); - $application = $this->getMock('Symfony\Component\Console\Application', array('doRun')); + $application = $this->getMockBuilder('Symfony\Component\Console\Application')->setMethods(array('doRun'))->getMock(); $application->setAutoExit(false); $application->expects($this->once()) - ->method('doRun') - ->will($this->throwException($exception)); + ->method('doRun') + ->will($this->throwException($exception)); $exitCode = $application->run(new ArrayInput(array()), new NullOutput()); @@ -723,11 +906,11 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase { $exception = new \Exception('', 0); - $application = $this->getMock('Symfony\Component\Console\Application', array('doRun')); + $application = $this->getMockBuilder('Symfony\Component\Console\Application')->setMethods(array('doRun'))->getMock(); $application->setAutoExit(false); $application->expects($this->once()) - ->method('doRun') - ->will($this->throwException($exception)); + ->method('doRun') + ->will($this->throwException($exception)); $exitCode = $application->run(new ArrayInput(array()), new NullOutput()); @@ -799,8 +982,6 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase $helperSet = $application->getHelperSet(); $this->assertTrue($helperSet->has('formatter')); - $this->assertTrue($helperSet->has('dialog')); - $this->assertTrue($helperSet->has('progress')); } public function testAddingSingleHelperSetOverwritesDefaultValues() @@ -919,7 +1100,7 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase /** * @expectedException \LogicException - * @expectedExceptionMessage caught + * @expectedExceptionMessage error */ public function testRunWithExceptionAndDispatcher() { @@ -950,7 +1131,212 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase $tester = new ApplicationTester($application); $tester->run(array('command' => 'foo')); - $this->assertContains('before.foo.caught.after.', $tester->getDisplay()); + $this->assertContains('before.foo.error.after.', $tester->getDisplay()); + } + + public function testRunDispatchesAllEventsWithExceptionInListener() + { + $dispatcher = $this->getDispatcher(); + $dispatcher->addListener('console.command', function () { + throw new \RuntimeException('foo'); + }); + + $application = new Application(); + $application->setDispatcher($dispatcher); + $application->setAutoExit(false); + + $application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) { + $output->write('foo.'); + }); + + $tester = new ApplicationTester($application); + $tester->run(array('command' => 'foo')); + $this->assertContains('before.error.after.', $tester->getDisplay()); + } + + /** + * @requires PHP 7 + */ + public function testRunWithError() + { + $application = new Application(); + $application->setAutoExit(false); + $application->setCatchExceptions(false); + + $application->register('dym')->setCode(function (InputInterface $input, OutputInterface $output) { + $output->write('dym.'); + + throw new \Error('dymerr'); + }); + + $tester = new ApplicationTester($application); + + try { + $tester->run(array('command' => 'dym')); + $this->fail('Error expected.'); + } catch (\Error $e) { + $this->assertSame('dymerr', $e->getMessage()); + } + } + + public function testRunAllowsErrorListenersToSilenceTheException() + { + $dispatcher = $this->getDispatcher(); + $dispatcher->addListener('console.error', function (ConsoleErrorEvent $event) { + $event->getOutput()->write('silenced.'); + + $event->setExitCode(0); + }); + + $dispatcher->addListener('console.command', function () { + throw new \RuntimeException('foo'); + }); + + $application = new Application(); + $application->setDispatcher($dispatcher); + $application->setAutoExit(false); + + $application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) { + $output->write('foo.'); + }); + + $tester = new ApplicationTester($application); + $tester->run(array('command' => 'foo')); + $this->assertContains('before.error.silenced.after.', $tester->getDisplay()); + $this->assertEquals(ConsoleCommandEvent::RETURN_CODE_DISABLED, $tester->getStatusCode()); + } + + public function testConsoleErrorEventIsTriggeredOnCommandNotFound() + { + $dispatcher = new EventDispatcher(); + $dispatcher->addListener('console.error', function (ConsoleErrorEvent $event) { + $this->assertNull($event->getCommand()); + $this->assertInstanceOf(CommandNotFoundException::class, $event->getError()); + $event->getOutput()->write('silenced command not found'); + }); + + $application = new Application(); + $application->setDispatcher($dispatcher); + $application->setAutoExit(false); + + $tester = new ApplicationTester($application); + $tester->run(array('command' => 'unknown')); + $this->assertContains('silenced command not found', $tester->getDisplay()); + $this->assertEquals(1, $tester->getStatusCode()); + } + + /** + * @group legacy + * @expectedDeprecation The "ConsoleEvents::EXCEPTION" event is deprecated since Symfony 3.3 and will be removed in 4.0. Listen to the "ConsoleEvents::ERROR" event instead. + */ + public function testLegacyExceptionListenersAreStillTriggered() + { + $dispatcher = $this->getDispatcher(); + $dispatcher->addListener('console.exception', function (ConsoleExceptionEvent $event) { + $event->getOutput()->write('caught.'); + + $event->setException(new \RuntimeException('replaced in caught.')); + }); + + $application = new Application(); + $application->setDispatcher($dispatcher); + $application->setAutoExit(false); + + $application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) { + throw new \RuntimeException('foo'); + }); + + $tester = new ApplicationTester($application); + $tester->run(array('command' => 'foo')); + $this->assertContains('before.caught.error.after.', $tester->getDisplay()); + $this->assertContains('replaced in caught.', $tester->getDisplay()); + } + + /** + * @requires PHP 7 + */ + public function testErrorIsRethrownIfNotHandledByConsoleErrorEvent() + { + $application = new Application(); + $application->setAutoExit(false); + $application->setCatchExceptions(false); + $application->setDispatcher(new EventDispatcher()); + + $application->register('dym')->setCode(function (InputInterface $input, OutputInterface $output) { + new \UnknownClass(); + }); + + $tester = new ApplicationTester($application); + + try { + $tester->run(array('command' => 'dym')); + $this->fail('->run() should rethrow PHP errors if not handled via ConsoleErrorEvent.'); + } catch (\Error $e) { + $this->assertSame($e->getMessage(), 'Class \'UnknownClass\' not found'); + } + } + + /** + * @requires PHP 7 + * @expectedException \LogicException + * @expectedExceptionMessage error + */ + public function testRunWithErrorAndDispatcher() + { + $application = new Application(); + $application->setDispatcher($this->getDispatcher()); + $application->setAutoExit(false); + $application->setCatchExceptions(false); + + $application->register('dym')->setCode(function (InputInterface $input, OutputInterface $output) { + $output->write('dym.'); + + throw new \Error('dymerr'); + }); + + $tester = new ApplicationTester($application); + $tester->run(array('command' => 'dym')); + $this->assertContains('before.dym.error.after.', $tester->getDisplay(), 'The PHP Error did not dispached events'); + } + + /** + * @requires PHP 7 + */ + public function testRunDispatchesAllEventsWithError() + { + $application = new Application(); + $application->setDispatcher($this->getDispatcher()); + $application->setAutoExit(false); + + $application->register('dym')->setCode(function (InputInterface $input, OutputInterface $output) { + $output->write('dym.'); + + throw new \Error('dymerr'); + }); + + $tester = new ApplicationTester($application); + $tester->run(array('command' => 'dym')); + $this->assertContains('before.dym.error.after.', $tester->getDisplay(), 'The PHP Error did not dispached events'); + } + + /** + * @requires PHP 7 + */ + public function testRunWithErrorFailingStatusCode() + { + $application = new Application(); + $application->setDispatcher($this->getDispatcher()); + $application->setAutoExit(false); + + $application->register('dus')->setCode(function (InputInterface $input, OutputInterface $output) { + $output->write('dus.'); + + throw new \Error('duserr'); + }); + + $tester = new ApplicationTester($application); + $tester->run(array('command' => 'dus')); + $this->assertSame(1, $tester->getStatusCode(), 'Status code should be 1'); } public function testRunWithDispatcherSkippingCommand() @@ -1026,6 +1412,9 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase $this->assertEquals('some test value', $extraValue); } + /** + * @group legacy + */ public function testTerminalDimensions() { $application = new Application(); @@ -1041,35 +1430,31 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase $this->assertSame(array($width, 80), $application->getTerminalDimensions()); } - protected function getDispatcher($skipCommand = false) + public function testSetRunCustomDefaultCommand() { - $dispatcher = new EventDispatcher(); - $dispatcher->addListener('console.command', function (ConsoleCommandEvent $event) use ($skipCommand) { - $event->getOutput()->write('before.'); + $command = new \FooCommand(); - if ($skipCommand) { - $event->disableCommand(); - } - }); - $dispatcher->addListener('console.terminate', function (ConsoleTerminateEvent $event) use ($skipCommand) { - $event->getOutput()->writeln('after.'); + $application = new Application(); + $application->setAutoExit(false); + $application->add($command); + $application->setDefaultCommand($command->getName()); - if (!$skipCommand) { - $event->setExitCode(113); - } - }); - $dispatcher->addListener('console.exception', function (ConsoleExceptionEvent $event) { - $event->getOutput()->write('caught.'); + $tester = new ApplicationTester($application); + $tester->run(array(), array('interactive' => false)); + $this->assertEquals('called'.PHP_EOL, $tester->getDisplay(), 'Application runs the default set command if different from \'list\' command'); - $event->setException(new \LogicException('caught.', $event->getExitCode(), $event->getException())); - }); + $application = new CustomDefaultCommandApplication(); + $application->setAutoExit(false); - return $dispatcher; + $tester = new ApplicationTester($application); + $tester->run(array(), array('interactive' => false)); + + $this->assertEquals('called'.PHP_EOL, $tester->getDisplay(), 'Application runs the default set command if different from \'list\' command'); } - public function testSetRunCustomDefaultCommand() + public function testSetRunCustomDefaultCommandWithOption() { - $command = new \FooCommand(); + $command = new \FooOptCommand(); $application = new Application(); $application->setAutoExit(false); @@ -1077,16 +1462,27 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase $application->setDefaultCommand($command->getName()); $tester = new ApplicationTester($application); - $tester->run(array()); - $this->assertEquals('interact called'.PHP_EOL.'called'.PHP_EOL, $tester->getDisplay(), 'Application runs the default set command if different from \'list\' command'); + $tester->run(array('--fooopt' => 'opt'), array('interactive' => false)); - $application = new CustomDefaultCommandApplication(); + $this->assertEquals('called'.PHP_EOL.'opt'.PHP_EOL, $tester->getDisplay(), 'Application runs the default set command if different from \'list\' command'); + } + + public function testSetRunCustomSingleCommand() + { + $command = new \FooCommand(); + + $application = new Application(); $application->setAutoExit(false); + $application->add($command); + $application->setDefaultCommand($command->getName(), true); $tester = new ApplicationTester($application); + $tester->run(array()); + $this->assertContains('called', $tester->getDisplay()); - $this->assertEquals('interact called'.PHP_EOL.'called'.PHP_EOL, $tester->getDisplay(), 'Application runs the default set command if different from \'list\' command'); + $tester->run(array('--help' => true)); + $this->assertContains('The foo:bar command', $tester->getDisplay()); } /** @@ -1102,9 +1498,119 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase $this->assertFalse($tester->getInput()->hasParameterOption(array('--no-interaction', '-n'))); - $inputStream = $application->getHelperSet()->get('question')->getInputStream(); + $inputStream = $tester->getInput()->getStream(); $this->assertEquals($tester->getInput()->isInteractive(), @posix_isatty($inputStream)); } + + public function testRunLazyCommandService() + { + $container = new ContainerBuilder(); + $container->addCompilerPass(new AddConsoleCommandPass()); + $container + ->register('lazy-command', LazyCommand::class) + ->addTag('console.command', array('command' => 'lazy:command')) + ->addTag('console.command', array('command' => 'lazy:alias')) + ->addTag('console.command', array('command' => 'lazy:alias2')); + $container->compile(); + + $application = new Application(); + $application->setCommandLoader($container->get('console.command_loader')); + $application->setAutoExit(false); + + $tester = new ApplicationTester($application); + + $tester->run(array('command' => 'lazy:command')); + $this->assertSame("lazy-command called\n", $tester->getDisplay(true)); + + $tester->run(array('command' => 'lazy:alias')); + $this->assertSame("lazy-command called\n", $tester->getDisplay(true)); + + $tester->run(array('command' => 'lazy:alias2')); + $this->assertSame("lazy-command called\n", $tester->getDisplay(true)); + + $command = $application->get('lazy:command'); + $this->assertSame(array('lazy:alias', 'lazy:alias2'), $command->getAliases()); + } + + /** + * @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException + */ + public function testGetDisabledLazyCommand() + { + $application = new Application(); + $application->setCommandLoader(new FactoryCommandLoader(array('disabled' => function () { return new DisabledCommand(); }))); + $application->get('disabled'); + } + + public function testHasReturnsFalseForDisabledLazyCommand() + { + $application = new Application(); + $application->setCommandLoader(new FactoryCommandLoader(array('disabled' => function () { return new DisabledCommand(); }))); + $this->assertFalse($application->has('disabled')); + } + + public function testAllExcludesDisabledLazyCommand() + { + $application = new Application(); + $application->setCommandLoader(new FactoryCommandLoader(array('disabled' => function () { return new DisabledCommand(); }))); + $this->assertArrayNotHasKey('disabled', $application->all()); + } + + protected function getDispatcher($skipCommand = false) + { + $dispatcher = new EventDispatcher(); + $dispatcher->addListener('console.command', function (ConsoleCommandEvent $event) use ($skipCommand) { + $event->getOutput()->write('before.'); + + if ($skipCommand) { + $event->disableCommand(); + } + }); + $dispatcher->addListener('console.terminate', function (ConsoleTerminateEvent $event) use ($skipCommand) { + $event->getOutput()->writeln('after.'); + + if (!$skipCommand) { + $event->setExitCode(ConsoleCommandEvent::RETURN_CODE_DISABLED); + } + }); + $dispatcher->addListener('console.error', function (ConsoleErrorEvent $event) { + $event->getOutput()->write('error.'); + + $event->setError(new \LogicException('error.', $event->getExitCode(), $event->getError())); + }); + + return $dispatcher; + } + + /** + * @requires PHP 7 + */ + public function testErrorIsRethrownIfNotHandledByConsoleErrorEventWithCatchingEnabled() + { + $application = new Application(); + $application->setAutoExit(false); + $application->setDispatcher(new EventDispatcher()); + + $application->register('dym')->setCode(function (InputInterface $input, OutputInterface $output) { + new \UnknownClass(); + }); + + $tester = new ApplicationTester($application); + + try { + $tester->run(array('command' => 'dym')); + $this->fail('->run() should rethrow PHP errors if not handled via ConsoleErrorEvent.'); + } catch (\Error $e) { + $this->assertSame($e->getMessage(), 'Class \'UnknownClass\' not found'); + } + } + + protected function tearDown() + { + putenv('SHELL_VERBOSITY'); + unset($_ENV['SHELL_VERBOSITY']); + unset($_SERVER['SHELL_VERBOSITY']); + } } class CustomApplication extends Application @@ -1144,3 +1650,19 @@ class CustomDefaultCommandApplication extends Application $this->setDefaultCommand($command->getName()); } } + +class LazyCommand extends Command +{ + public function execute(InputInterface $input, OutputInterface $output) + { + $output->writeln('lazy-command called'); + } +} + +class DisabledCommand extends Command +{ + public function isEnabled() + { + return false; + } +} diff --git a/vendor/symfony/console/Tests/Command/CommandTest.php b/vendor/symfony/console/Tests/Command/CommandTest.php index e8836d8c..4fcbf957 100644 --- a/vendor/symfony/console/Tests/Command/CommandTest.php +++ b/vendor/symfony/console/Tests/Command/CommandTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Console\Tests\Command; +use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Helper\FormatterHelper; use Symfony\Component\Console\Application; @@ -23,7 +24,7 @@ use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\NullOutput; use Symfony\Component\Console\Tester\CommandTester; -class CommandTest extends \PHPUnit_Framework_TestCase +class CommandTest extends TestCase { protected static $fixturesPath; @@ -45,7 +46,7 @@ class CommandTest extends \PHPUnit_Framework_TestCase */ public function testCommandNameCannotBeEmpty() { - new Command(); + (new Application())->add(new Command()); } public function testSetApplication() @@ -54,6 +55,14 @@ class CommandTest extends \PHPUnit_Framework_TestCase $command = new \TestCommand(); $command->setApplication($application); $this->assertEquals($application, $command->getApplication(), '->setApplication() sets the current application'); + $this->assertEquals($application->getHelperSet(), $command->getHelperSet()); + } + + public function testSetApplicationNull() + { + $command = new \TestCommand(); + $command->setApplication(null); + $this->assertNull($command->getHelperSet()); } public function testSetGetDefinition() @@ -84,6 +93,13 @@ class CommandTest extends \PHPUnit_Framework_TestCase $this->assertTrue($command->getDefinition()->hasOption('foo'), '->addOption() adds an option to the command'); } + public function testSetHidden() + { + $command = new \TestCommand(); + $command->setHidden(true); + $this->assertTrue($command->isHidden()); + } + public function testGetNamespaceGetNameSetName() { $command = new \TestCommand(); @@ -101,7 +117,12 @@ class CommandTest extends \PHPUnit_Framework_TestCase */ public function testInvalidCommandNames($name) { - $this->setExpectedException('InvalidArgumentException', sprintf('Command name "%s" is invalid.', $name)); + if (method_exists($this, 'expectException')) { + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessage(sprintf('Command name "%s" is invalid.', $name)); + } else { + $this->setExpectedException('InvalidArgumentException', sprintf('Command name "%s" is invalid.', $name)); + } $command = new \TestCommand(); $command->setName($name); @@ -156,6 +177,13 @@ class CommandTest extends \PHPUnit_Framework_TestCase $this->assertEquals(array('name1'), $command->getAliases(), '->setAliases() sets the aliases'); } + public function testSetAliasesNull() + { + $command = new \TestCommand(); + $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('InvalidArgumentException'); + $command->setAliases(null); + } + public function testGetSynopsis() { $command = new \TestCommand(); @@ -164,6 +192,15 @@ class CommandTest extends \PHPUnit_Framework_TestCase $this->assertEquals('namespace:name [--foo] [--] [<bar>]', $command->getSynopsis(), '->getSynopsis() returns the synopsis'); } + public function testAddGetUsages() + { + $command = new \TestCommand(); + $command->addUsage('foo1'); + $command->addUsage('foo2'); + $this->assertContains('namespace:name foo1', $command->getUsages()); + $this->assertContains('namespace:name foo2', $command->getUsages()); + } + public function testGetHelper() { $application = new Application(); @@ -257,7 +294,7 @@ class CommandTest extends \PHPUnit_Framework_TestCase } /** - * @expectedException Symfony\Component\Console\Exception\InvalidOptionException + * @expectedException \Symfony\Component\Console\Exception\InvalidOptionException * @expectedExceptionMessage The "--bar" option does not exist. */ public function testRunWithInvalidOption() @@ -273,10 +310,10 @@ class CommandTest extends \PHPUnit_Framework_TestCase $exitCode = $command->run(new StringInput(''), new NullOutput()); $this->assertSame(0, $exitCode, '->run() returns integer exit code (treats null as 0)'); - $command = $this->getMock('TestCommand', array('execute')); + $command = $this->getMockBuilder('TestCommand')->setMethods(array('execute'))->getMock(); $command->expects($this->once()) - ->method('execute') - ->will($this->returnValue('2.3')); + ->method('execute') + ->will($this->returnValue('2.3')); $exitCode = $command->run(new StringInput(''), new NullOutput()); $this->assertSame(2, $exitCode, '->run() returns integer exit code (casts numeric to int)'); } @@ -297,6 +334,20 @@ class CommandTest extends \PHPUnit_Framework_TestCase $this->assertSame(0, $command->run(new StringInput(''), new NullOutput())); } + public function testRunWithProcessTitle() + { + $command = new \TestCommand(); + $command->setApplication(new Application()); + $command->setProcessTitle('foo'); + $this->assertSame(0, $command->run(new StringInput(''), new NullOutput())); + if (function_exists('cli_set_process_title')) { + if (null === @cli_get_process_title() && 'Darwin' === PHP_OS) { + $this->markTestSkipped('Running "cli_get_process_title" as an unprivileged user is not supported on MacOS.'); + } + $this->assertEquals('foo', cli_get_process_title()); + } + } + public function testSetCode() { $command = new \TestCommand(); @@ -319,7 +370,6 @@ class CommandTest extends \PHPUnit_Framework_TestCase /** * @dataProvider getSetCodeBindToClosureTests - * @requires PHP 5.4 */ public function testSetCodeBindToClosure($previouslyBound, $expected) { @@ -335,53 +385,42 @@ class CommandTest extends \PHPUnit_Framework_TestCase $this->assertEquals('interact called'.PHP_EOL.$expected.PHP_EOL, $tester->getDisplay()); } - public function testSetCodeWithNonClosureCallable() + public function testSetCodeWithStaticClosure() { $command = new \TestCommand(); - $ret = $command->setCode(array($this, 'callableMethodCommand')); - $this->assertEquals($command, $ret, '->setCode() implements a fluent interface'); + $command->setCode(self::createClosure()); $tester = new CommandTester($command); $tester->execute(array()); - $this->assertEquals('interact called'.PHP_EOL.'from the code...'.PHP_EOL, $tester->getDisplay()); - } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Invalid callable provided to Command::setCode. - */ - public function testSetCodeWithNonCallable() - { - $command = new \TestCommand(); - $command->setCode(array($this, 'nonExistentMethod')); + if (\PHP_VERSION_ID < 70000) { + // Cannot bind static closures in PHP 5 + $this->assertEquals('interact called'.PHP_EOL.'not bound'.PHP_EOL, $tester->getDisplay()); + } else { + // Can bind static closures in PHP 7 + $this->assertEquals('interact called'.PHP_EOL.'bound'.PHP_EOL, $tester->getDisplay()); + } } - public function callableMethodCommand(InputInterface $input, OutputInterface $output) + private static function createClosure() { - $output->writeln('from the code...'); + return function (InputInterface $input, OutputInterface $output) { + $output->writeln(isset($this) ? 'bound' : 'not bound'); + }; } - /** - * @group legacy - */ - public function testLegacyAsText() + public function testSetCodeWithNonClosureCallable() { $command = new \TestCommand(); - $command->setApplication(new Application()); + $ret = $command->setCode(array($this, 'callableMethodCommand')); + $this->assertEquals($command, $ret, '->setCode() implements a fluent interface'); $tester = new CommandTester($command); - $tester->execute(array('command' => $command->getName())); - $this->assertStringEqualsFile(self::$fixturesPath.'/command_astext.txt', $command->asText(), '->asText() returns a text representation of the command'); + $tester->execute(array()); + $this->assertEquals('interact called'.PHP_EOL.'from the code...'.PHP_EOL, $tester->getDisplay()); } - /** - * @group legacy - */ - public function testLegacyAsXml() + public function callableMethodCommand(InputInterface $input, OutputInterface $output) { - $command = new \TestCommand(); - $command->setApplication(new Application()); - $tester = new CommandTester($command); - $tester->execute(array('command' => $command->getName())); - $this->assertXmlStringEqualsXmlFile(self::$fixturesPath.'/command_asxml.txt', $command->asXml(), '->asXml() returns an XML representation of the command'); + $output->writeln('from the code...'); } } diff --git a/vendor/symfony/console/Tests/Command/HelpCommandTest.php b/vendor/symfony/console/Tests/Command/HelpCommandTest.php index 9e068587..4d618ac1 100644 --- a/vendor/symfony/console/Tests/Command/HelpCommandTest.php +++ b/vendor/symfony/console/Tests/Command/HelpCommandTest.php @@ -11,12 +11,13 @@ namespace Symfony\Component\Console\Tests\Command; +use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Tester\CommandTester; use Symfony\Component\Console\Command\HelpCommand; use Symfony\Component\Console\Command\ListCommand; use Symfony\Component\Console\Application; -class HelpCommandTest extends \PHPUnit_Framework_TestCase +class HelpCommandTest extends TestCase { public function testExecuteForCommandAlias() { @@ -64,7 +65,7 @@ class HelpCommandTest extends \PHPUnit_Framework_TestCase $application = new Application(); $commandTester = new CommandTester($application->get('help')); $commandTester->execute(array('command_name' => 'list', '--format' => 'xml')); - $this->assertContains('list [--xml] [--raw] [--format FORMAT] [--] [<namespace>]', $commandTester->getDisplay(), '->execute() returns a text help for the given command'); + $this->assertContains('list [--raw] [--format FORMAT] [--] [<namespace>]', $commandTester->getDisplay(), '->execute() returns a text help for the given command'); $this->assertContains('<command', $commandTester->getDisplay(), '->execute() returns an XML help text if --format=xml is passed'); } } diff --git a/vendor/symfony/console/Tests/Command/ListCommandTest.php b/vendor/symfony/console/Tests/Command/ListCommandTest.php index a166a040..64478ecc 100644 --- a/vendor/symfony/console/Tests/Command/ListCommandTest.php +++ b/vendor/symfony/console/Tests/Command/ListCommandTest.php @@ -11,10 +11,11 @@ namespace Symfony\Component\Console\Tests\Command; +use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Tester\CommandTester; use Symfony\Component\Console\Application; -class ListCommandTest extends \PHPUnit_Framework_TestCase +class ListCommandTest extends TestCase { public function testExecuteListsCommands() { @@ -30,7 +31,7 @@ class ListCommandTest extends \PHPUnit_Framework_TestCase $application = new Application(); $commandTester = new CommandTester($command = $application->get('list')); $commandTester->execute(array('command' => $command->getName(), '--format' => 'xml')); - $this->assertRegExp('/<command id="list" name="list">/', $commandTester->getDisplay(), '->execute() returns a list of available commands in XML if --xml is passed'); + $this->assertRegExp('/<command id="list" name="list" hidden="0">/', $commandTester->getDisplay(), '->execute() returns a list of available commands in XML if --xml is passed'); } public function testExecuteListsCommandsWithRawOption() diff --git a/vendor/symfony/console/Tests/Command/LockableTraitTest.php b/vendor/symfony/console/Tests/Command/LockableTraitTest.php new file mode 100644 index 00000000..a622d1b4 --- /dev/null +++ b/vendor/symfony/console/Tests/Command/LockableTraitTest.php @@ -0,0 +1,67 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Tests\Command; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Console\Tester\CommandTester; +use Symfony\Component\Lock\Factory; +use Symfony\Component\Lock\Store\FlockStore; +use Symfony\Component\Lock\Store\SemaphoreStore; + +class LockableTraitTest extends TestCase +{ + protected static $fixturesPath; + + public static function setUpBeforeClass() + { + self::$fixturesPath = __DIR__.'/../Fixtures/'; + require_once self::$fixturesPath.'/FooLockCommand.php'; + require_once self::$fixturesPath.'/FooLock2Command.php'; + } + + public function testLockIsReleased() + { + $command = new \FooLockCommand(); + + $tester = new CommandTester($command); + $this->assertSame(2, $tester->execute(array())); + $this->assertSame(2, $tester->execute(array())); + } + + public function testLockReturnsFalseIfAlreadyLockedByAnotherCommand() + { + $command = new \FooLockCommand(); + + if (SemaphoreStore::isSupported(false)) { + $store = new SemaphoreStore(); + } else { + $store = new FlockStore(); + } + + $lock = (new Factory($store))->createLock($command->getName()); + $lock->acquire(); + + $tester = new CommandTester($command); + $this->assertSame(1, $tester->execute(array())); + + $lock->release(); + $this->assertSame(2, $tester->execute(array())); + } + + public function testMultipleLockCallsThrowLogicException() + { + $command = new \FooLock2Command(); + + $tester = new CommandTester($command); + $this->assertSame(1, $tester->execute(array())); + } +} diff --git a/vendor/symfony/console/Tests/CommandLoader/ContainerCommandLoaderTest.php b/vendor/symfony/console/Tests/CommandLoader/ContainerCommandLoaderTest.php new file mode 100644 index 00000000..78eefd24 --- /dev/null +++ b/vendor/symfony/console/Tests/CommandLoader/ContainerCommandLoaderTest.php @@ -0,0 +1,61 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Tests\CommandLoader; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\CommandLoader\ContainerCommandLoader; +use Symfony\Component\DependencyInjection\ServiceLocator; + +class ContainerCommandLoaderTest extends TestCase +{ + public function testHas() + { + $loader = new ContainerCommandLoader(new ServiceLocator(array( + 'foo-service' => function () { return new Command('foo'); }, + 'bar-service' => function () { return new Command('bar'); }, + )), array('foo' => 'foo-service', 'bar' => 'bar-service')); + + $this->assertTrue($loader->has('foo')); + $this->assertTrue($loader->has('bar')); + $this->assertFalse($loader->has('baz')); + } + + public function testGet() + { + $loader = new ContainerCommandLoader(new ServiceLocator(array( + 'foo-service' => function () { return new Command('foo'); }, + 'bar-service' => function () { return new Command('bar'); }, + )), array('foo' => 'foo-service', 'bar' => 'bar-service')); + + $this->assertInstanceOf(Command::class, $loader->get('foo')); + $this->assertInstanceOf(Command::class, $loader->get('bar')); + } + + /** + * @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException + */ + public function testGetUnknownCommandThrows() + { + (new ContainerCommandLoader(new ServiceLocator(array()), array()))->get('unknown'); + } + + public function testGetCommandNames() + { + $loader = new ContainerCommandLoader(new ServiceLocator(array( + 'foo-service' => function () { return new Command('foo'); }, + 'bar-service' => function () { return new Command('bar'); }, + )), array('foo' => 'foo-service', 'bar' => 'bar-service')); + + $this->assertSame(array('foo', 'bar'), $loader->getNames()); + } +} diff --git a/vendor/symfony/console/Tests/CommandLoader/FactoryCommandLoaderTest.php b/vendor/symfony/console/Tests/CommandLoader/FactoryCommandLoaderTest.php new file mode 100644 index 00000000..5ee6cd1e --- /dev/null +++ b/vendor/symfony/console/Tests/CommandLoader/FactoryCommandLoaderTest.php @@ -0,0 +1,60 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Tests\CommandLoader; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\CommandLoader\FactoryCommandLoader; + +class FactoryCommandLoaderTest extends TestCase +{ + public function testHas() + { + $loader = new FactoryCommandLoader(array( + 'foo' => function () { return new Command('foo'); }, + 'bar' => function () { return new Command('bar'); }, + )); + + $this->assertTrue($loader->has('foo')); + $this->assertTrue($loader->has('bar')); + $this->assertFalse($loader->has('baz')); + } + + public function testGet() + { + $loader = new FactoryCommandLoader(array( + 'foo' => function () { return new Command('foo'); }, + 'bar' => function () { return new Command('bar'); }, + )); + + $this->assertInstanceOf(Command::class, $loader->get('foo')); + $this->assertInstanceOf(Command::class, $loader->get('bar')); + } + + /** + * @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException + */ + public function testGetUnknownCommandThrows() + { + (new FactoryCommandLoader(array()))->get('unknown'); + } + + public function testGetCommandNames() + { + $loader = new FactoryCommandLoader(array( + 'foo' => function () { return new Command('foo'); }, + 'bar' => function () { return new Command('bar'); }, + )); + + $this->assertSame(array('foo', 'bar'), $loader->getNames()); + } +} diff --git a/vendor/symfony/console/Tests/DependencyInjection/AddConsoleCommandPassTest.php b/vendor/symfony/console/Tests/DependencyInjection/AddConsoleCommandPassTest.php new file mode 100644 index 00000000..34f64861 --- /dev/null +++ b/vendor/symfony/console/Tests/DependencyInjection/AddConsoleCommandPassTest.php @@ -0,0 +1,187 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Tests\DependencyInjection; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Console\CommandLoader\ContainerCommandLoader; +use Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\TypedReference; + +class AddConsoleCommandPassTest extends TestCase +{ + /** + * @dataProvider visibilityProvider + */ + public function testProcess($public) + { + $container = new ContainerBuilder(); + $container->addCompilerPass(new AddConsoleCommandPass()); + $container->setParameter('my-command.class', 'Symfony\Component\Console\Tests\DependencyInjection\MyCommand'); + + $definition = new Definition('%my-command.class%'); + $definition->setPublic($public); + $definition->addTag('console.command'); + $container->setDefinition('my-command', $definition); + + $container->compile(); + + $alias = 'console.command.symfony_component_console_tests_dependencyinjection_mycommand'; + + if ($public) { + $this->assertFalse($container->hasAlias($alias)); + $id = 'my-command'; + } else { + $id = $alias; + // The alias is replaced by a Definition by the ReplaceAliasByActualDefinitionPass + // in case the original service is private + $this->assertFalse($container->hasDefinition('my-command')); + $this->assertTrue($container->hasDefinition($alias)); + } + + $this->assertTrue($container->hasParameter('console.command.ids')); + $this->assertSame(array($alias => $id), $container->getParameter('console.command.ids')); + } + + public function testProcessRegistersLazyCommands() + { + $container = new ContainerBuilder(); + $command = $container + ->register('my-command', MyCommand::class) + ->setPublic(false) + ->addTag('console.command', array('command' => 'my:command')) + ->addTag('console.command', array('command' => 'my:alias')) + ; + + (new AddConsoleCommandPass())->process($container); + + $commandLoader = $container->getDefinition('console.command_loader'); + $commandLocator = $container->getDefinition((string) $commandLoader->getArgument(0)); + + $this->assertSame(ContainerCommandLoader::class, $commandLoader->getClass()); + $this->assertSame(array('my:command' => 'my-command', 'my:alias' => 'my-command'), $commandLoader->getArgument(1)); + $this->assertEquals(array(array('my-command' => new ServiceClosureArgument(new TypedReference('my-command', MyCommand::class)))), $commandLocator->getArguments()); + $this->assertSame(array('console.command.symfony_component_console_tests_dependencyinjection_mycommand' => 'my-command'), $container->getParameter('console.command.ids')); + $this->assertSame(array('my-command' => true), $container->getParameter('console.lazy_command.ids')); + $this->assertSame(array(array('setName', array('my:command')), array('setAliases', array(array('my:alias')))), $command->getMethodCalls()); + } + + public function testProcessFallsBackToDefaultName() + { + $container = new ContainerBuilder(); + $container + ->register('with-default-name', NamedCommand::class) + ->setPublic(false) + ->addTag('console.command') + ; + + $pass = new AddConsoleCommandPass(); + $pass->process($container); + + $commandLoader = $container->getDefinition('console.command_loader'); + $commandLocator = $container->getDefinition((string) $commandLoader->getArgument(0)); + + $this->assertSame(ContainerCommandLoader::class, $commandLoader->getClass()); + $this->assertSame(array('default' => 'with-default-name'), $commandLoader->getArgument(1)); + $this->assertEquals(array(array('with-default-name' => new ServiceClosureArgument(new TypedReference('with-default-name', NamedCommand::class)))), $commandLocator->getArguments()); + $this->assertSame(array('console.command.symfony_component_console_tests_dependencyinjection_namedcommand' => 'with-default-name'), $container->getParameter('console.command.ids')); + $this->assertSame(array('with-default-name' => true), $container->getParameter('console.lazy_command.ids')); + + $container = new ContainerBuilder(); + $container + ->register('with-default-name', NamedCommand::class) + ->setPublic(false) + ->addTag('console.command', array('command' => 'new-name')) + ; + + $pass->process($container); + + $this->assertSame(array('new-name' => 'with-default-name'), $container->getDefinition('console.command_loader')->getArgument(1)); + } + + public function visibilityProvider() + { + return array( + array(true), + array(false), + ); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage The service "my-command" tagged "console.command" must not be abstract. + */ + public function testProcessThrowAnExceptionIfTheServiceIsAbstract() + { + $container = new ContainerBuilder(); + $container->setResourceTracking(false); + $container->addCompilerPass(new AddConsoleCommandPass()); + + $definition = new Definition('Symfony\Component\Console\Tests\DependencyInjection\MyCommand'); + $definition->addTag('console.command'); + $definition->setAbstract(true); + $container->setDefinition('my-command', $definition); + + $container->compile(); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage The service "my-command" tagged "console.command" must be a subclass of "Symfony\Component\Console\Command\Command". + */ + public function testProcessThrowAnExceptionIfTheServiceIsNotASubclassOfCommand() + { + $container = new ContainerBuilder(); + $container->setResourceTracking(false); + $container->addCompilerPass(new AddConsoleCommandPass()); + + $definition = new Definition('SplObjectStorage'); + $definition->addTag('console.command'); + $container->setDefinition('my-command', $definition); + + $container->compile(); + } + + public function testProcessPrivateServicesWithSameCommand() + { + $container = new ContainerBuilder(); + $className = 'Symfony\Component\Console\Tests\DependencyInjection\MyCommand'; + + $definition1 = new Definition($className); + $definition1->addTag('console.command')->setPublic(false); + + $definition2 = new Definition($className); + $definition2->addTag('console.command')->setPublic(false); + + $container->setDefinition('my-command1', $definition1); + $container->setDefinition('my-command2', $definition2); + + (new AddConsoleCommandPass())->process($container); + + $alias1 = 'console.command.symfony_component_console_tests_dependencyinjection_mycommand'; + $alias2 = $alias1.'_my-command2'; + $this->assertTrue($container->hasAlias($alias1)); + $this->assertTrue($container->hasAlias($alias2)); + } +} + +class MyCommand extends Command +{ +} + +class NamedCommand extends Command +{ + protected static $defaultName = 'default'; +} diff --git a/vendor/symfony/console/Tests/Descriptor/AbstractDescriptorTest.php b/vendor/symfony/console/Tests/Descriptor/AbstractDescriptorTest.php index c36c4a8e..3686e754 100644 --- a/vendor/symfony/console/Tests/Descriptor/AbstractDescriptorTest.php +++ b/vendor/symfony/console/Tests/Descriptor/AbstractDescriptorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Console\Tests\Descriptor; +use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Application; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; @@ -18,7 +19,7 @@ use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\BufferedOutput; -abstract class AbstractDescriptorTest extends \PHPUnit_Framework_TestCase +abstract class AbstractDescriptorTest extends TestCase { /** @dataProvider getDescribeInputArgumentTestData */ public function testDescribeInputArgument(InputArgument $argument, $expectedDescription) @@ -86,7 +87,7 @@ abstract class AbstractDescriptorTest extends \PHPUnit_Framework_TestCase abstract protected function getFormat(); - private function getDescriptionTestData(array $objects) + protected function getDescriptionTestData(array $objects) { $data = array(); foreach ($objects as $name => $object) { @@ -97,10 +98,10 @@ abstract class AbstractDescriptorTest extends \PHPUnit_Framework_TestCase return $data; } - protected function assertDescription($expectedDescription, $describedObject) + protected function assertDescription($expectedDescription, $describedObject, array $options = array()) { $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true); - $this->getDescriptor()->describe($output, $describedObject, array('raw_output' => true)); + $this->getDescriptor()->describe($output, $describedObject, $options + array('raw_output' => true)); $this->assertEquals(trim($expectedDescription), trim(str_replace(PHP_EOL, "\n", $output->fetch()))); } } diff --git a/vendor/symfony/console/Tests/Descriptor/JsonDescriptorTest.php b/vendor/symfony/console/Tests/Descriptor/JsonDescriptorTest.php index f9a15612..dffcaf66 100644 --- a/vendor/symfony/console/Tests/Descriptor/JsonDescriptorTest.php +++ b/vendor/symfony/console/Tests/Descriptor/JsonDescriptorTest.php @@ -26,10 +26,10 @@ class JsonDescriptorTest extends AbstractDescriptorTest return 'json'; } - protected function assertDescription($expectedDescription, $describedObject) + protected function assertDescription($expectedDescription, $describedObject, array $options = array()) { $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true); - $this->getDescriptor()->describe($output, $describedObject, array('raw_output' => true)); + $this->getDescriptor()->describe($output, $describedObject, $options + array('raw_output' => true)); $this->assertEquals(json_decode(trim($expectedDescription), true), json_decode(trim(str_replace(PHP_EOL, "\n", $output->fetch())), true)); } } diff --git a/vendor/symfony/console/Tests/Descriptor/MarkdownDescriptorTest.php b/vendor/symfony/console/Tests/Descriptor/MarkdownDescriptorTest.php index c85e8a59..eb80f58b 100644 --- a/vendor/symfony/console/Tests/Descriptor/MarkdownDescriptorTest.php +++ b/vendor/symfony/console/Tests/Descriptor/MarkdownDescriptorTest.php @@ -12,9 +12,27 @@ namespace Symfony\Component\Console\Tests\Descriptor; use Symfony\Component\Console\Descriptor\MarkdownDescriptor; +use Symfony\Component\Console\Tests\Fixtures\DescriptorApplicationMbString; +use Symfony\Component\Console\Tests\Fixtures\DescriptorCommandMbString; class MarkdownDescriptorTest extends AbstractDescriptorTest { + public function getDescribeCommandTestData() + { + return $this->getDescriptionTestData(array_merge( + ObjectsProvider::getCommands(), + array('command_mbstring' => new DescriptorCommandMbString()) + )); + } + + public function getDescribeApplicationTestData() + { + return $this->getDescriptionTestData(array_merge( + ObjectsProvider::getApplications(), + array('application_mbstring' => new DescriptorApplicationMbString()) + )); + } + protected function getDescriptor() { return new MarkdownDescriptor(); diff --git a/vendor/symfony/console/Tests/Descriptor/ObjectsProvider.php b/vendor/symfony/console/Tests/Descriptor/ObjectsProvider.php index 45b3b2ff..b4f34ada 100644 --- a/vendor/symfony/console/Tests/Descriptor/ObjectsProvider.php +++ b/vendor/symfony/console/Tests/Descriptor/ObjectsProvider.php @@ -31,6 +31,8 @@ class ObjectsProvider 'input_argument_2' => new InputArgument('argument_name', InputArgument::IS_ARRAY, 'argument description'), 'input_argument_3' => new InputArgument('argument_name', InputArgument::OPTIONAL, 'argument description', 'default_value'), 'input_argument_4' => new InputArgument('argument_name', InputArgument::REQUIRED, "multiline\nargument description"), + 'input_argument_with_style' => new InputArgument('argument_name', InputArgument::OPTIONAL, 'argument description', '<comment>style</>'), + 'input_argument_with_default_inf_value' => new InputArgument('argument_name', InputArgument::OPTIONAL, 'argument description', INF), ); } @@ -43,6 +45,9 @@ class ObjectsProvider 'input_option_4' => new InputOption('option_name', 'o', InputOption::VALUE_IS_ARRAY | InputOption::VALUE_OPTIONAL, 'option description', array()), 'input_option_5' => new InputOption('option_name', 'o', InputOption::VALUE_REQUIRED, "multiline\noption description"), 'input_option_6' => new InputOption('option_name', array('o', 'O'), InputOption::VALUE_REQUIRED, 'option with multiple shortcuts'), + 'input_option_with_style' => new InputOption('option_name', 'o', InputOption::VALUE_REQUIRED, 'option description', '<comment>style</>'), + 'input_option_with_style_array' => new InputOption('option_name', 'o', InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'option description', array('<comment>Hello</comment>', '<info>world</info>')), + 'input_option_with_default_inf_value' => new InputOption('option_name', 'o', InputOption::VALUE_OPTIONAL, 'option description', INF), ); } diff --git a/vendor/symfony/console/Tests/Descriptor/TextDescriptorTest.php b/vendor/symfony/console/Tests/Descriptor/TextDescriptorTest.php index 350b6795..c024a522 100644 --- a/vendor/symfony/console/Tests/Descriptor/TextDescriptorTest.php +++ b/vendor/symfony/console/Tests/Descriptor/TextDescriptorTest.php @@ -12,9 +12,35 @@ namespace Symfony\Component\Console\Tests\Descriptor; use Symfony\Component\Console\Descriptor\TextDescriptor; +use Symfony\Component\Console\Tests\Fixtures\DescriptorApplication2; +use Symfony\Component\Console\Tests\Fixtures\DescriptorApplicationMbString; +use Symfony\Component\Console\Tests\Fixtures\DescriptorCommandMbString; class TextDescriptorTest extends AbstractDescriptorTest { + public function getDescribeCommandTestData() + { + return $this->getDescriptionTestData(array_merge( + ObjectsProvider::getCommands(), + array('command_mbstring' => new DescriptorCommandMbString()) + )); + } + + public function getDescribeApplicationTestData() + { + return $this->getDescriptionTestData(array_merge( + ObjectsProvider::getApplications(), + array('application_mbstring' => new DescriptorApplicationMbString()) + )); + } + + public function testDescribeApplicationWithFilteredNamespace() + { + $application = new DescriptorApplication2(); + + $this->assertDescription(file_get_contents(__DIR__.'/../Fixtures/application_filtered_namespace.txt'), $application, array('namespace' => 'command4')); + } + protected function getDescriptor() { return new TextDescriptor(); diff --git a/vendor/symfony/console/Tests/EventListener/ErrorListenerTest.php b/vendor/symfony/console/Tests/EventListener/ErrorListenerTest.php new file mode 100644 index 00000000..17eaae09 --- /dev/null +++ b/vendor/symfony/console/Tests/EventListener/ErrorListenerTest.php @@ -0,0 +1,156 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Tests\EventListener; + +use PHPUnit\Framework\TestCase; +use Psr\Log\LoggerInterface; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Event\ConsoleErrorEvent; +use Symfony\Component\Console\Event\ConsoleTerminateEvent; +use Symfony\Component\Console\EventListener\ErrorListener; +use Symfony\Component\Console\Input\ArgvInput; +use Symfony\Component\Console\Input\ArrayInput; +use Symfony\Component\Console\Input\Input; +use Symfony\Component\Console\Input\StringInput; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class ErrorListenerTest extends TestCase +{ + public function testOnConsoleError() + { + $error = new \TypeError('An error occurred'); + + $logger = $this->getLogger(); + $logger + ->expects($this->once()) + ->method('error') + ->with('Error thrown while running command "{command}". Message: "{message}"', array('error' => $error, 'command' => 'test:run --foo=baz buzz', 'message' => 'An error occurred')) + ; + + $listener = new ErrorListener($logger); + $listener->onConsoleError(new ConsoleErrorEvent(new ArgvInput(array('console.php', 'test:run', '--foo=baz', 'buzz')), $this->getOutput(), $error, new Command('test:run'))); + } + + public function testOnConsoleErrorWithNoCommandAndNoInputString() + { + $error = new \RuntimeException('An error occurred'); + + $logger = $this->getLogger(); + $logger + ->expects($this->once()) + ->method('error') + ->with('An error occurred while using the console. Message: "{message}"', array('error' => $error, 'message' => 'An error occurred')) + ; + + $listener = new ErrorListener($logger); + $listener->onConsoleError(new ConsoleErrorEvent(new NonStringInput(), $this->getOutput(), $error)); + } + + public function testOnConsoleTerminateForNonZeroExitCodeWritesToLog() + { + $logger = $this->getLogger(); + $logger + ->expects($this->once()) + ->method('debug') + ->with('Command "{command}" exited with code "{code}"', array('command' => 'test:run', 'code' => 255)) + ; + + $listener = new ErrorListener($logger); + $listener->onConsoleTerminate($this->getConsoleTerminateEvent(new ArgvInput(array('console.php', 'test:run')), 255)); + } + + public function testOnConsoleTerminateForZeroExitCodeDoesNotWriteToLog() + { + $logger = $this->getLogger(); + $logger + ->expects($this->never()) + ->method('debug') + ; + + $listener = new ErrorListener($logger); + $listener->onConsoleTerminate($this->getConsoleTerminateEvent(new ArgvInput(array('console.php', 'test:run')), 0)); + } + + public function testGetSubscribedEvents() + { + $this->assertEquals( + array( + 'console.error' => array('onConsoleError', -128), + 'console.terminate' => array('onConsoleTerminate', -128), + ), + ErrorListener::getSubscribedEvents() + ); + } + + public function testAllKindsOfInputCanBeLogged() + { + $logger = $this->getLogger(); + $logger + ->expects($this->exactly(3)) + ->method('debug') + ->with('Command "{command}" exited with code "{code}"', array('command' => 'test:run --foo=bar', 'code' => 255)) + ; + + $listener = new ErrorListener($logger); + $listener->onConsoleTerminate($this->getConsoleTerminateEvent(new ArgvInput(array('console.php', 'test:run', '--foo=bar')), 255)); + $listener->onConsoleTerminate($this->getConsoleTerminateEvent(new ArrayInput(array('name' => 'test:run', '--foo' => 'bar')), 255)); + $listener->onConsoleTerminate($this->getConsoleTerminateEvent(new StringInput('test:run --foo=bar'), 255)); + } + + public function testCommandNameIsDisplayedForNonStringableInput() + { + $logger = $this->getLogger(); + $logger + ->expects($this->once()) + ->method('debug') + ->with('Command "{command}" exited with code "{code}"', array('command' => 'test:run', 'code' => 255)) + ; + + $listener = new ErrorListener($logger); + $listener->onConsoleTerminate($this->getConsoleTerminateEvent($this->getMockBuilder(InputInterface::class)->getMock(), 255)); + } + + private function getLogger() + { + return $this->getMockForAbstractClass(LoggerInterface::class); + } + + private function getConsoleTerminateEvent(InputInterface $input, $exitCode) + { + return new ConsoleTerminateEvent(new Command('test:run'), $input, $this->getOutput(), $exitCode); + } + + private function getOutput() + { + return $this->getMockBuilder(OutputInterface::class)->getMock(); + } +} + +class NonStringInput extends Input +{ + public function getFirstArgument() + { + } + + public function hasParameterOption($values, $onlyParams = false) + { + } + + public function getParameterOption($values, $default = false, $onlyParams = false) + { + } + + public function parse() + { + } +} diff --git a/vendor/symfony/console/Tests/Fixtures/DescriptorApplication2.php b/vendor/symfony/console/Tests/Fixtures/DescriptorApplication2.php index ff551358..7bb02fa5 100644 --- a/vendor/symfony/console/Tests/Fixtures/DescriptorApplication2.php +++ b/vendor/symfony/console/Tests/Fixtures/DescriptorApplication2.php @@ -20,5 +20,7 @@ class DescriptorApplication2 extends Application parent::__construct('My Symfony application', 'v1.0'); $this->add(new DescriptorCommand1()); $this->add(new DescriptorCommand2()); + $this->add(new DescriptorCommand3()); + $this->add(new DescriptorCommand4()); } } diff --git a/vendor/symfony/console/Tests/Fixtures/DescriptorApplicationMbString.php b/vendor/symfony/console/Tests/Fixtures/DescriptorApplicationMbString.php new file mode 100644 index 00000000..bf170c44 --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/DescriptorApplicationMbString.php @@ -0,0 +1,24 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Tests\Fixtures; + +use Symfony\Component\Console\Application; + +class DescriptorApplicationMbString extends Application +{ + public function __construct() + { + parent::__construct('MbString åpplicätion'); + + $this->add(new DescriptorCommandMbString()); + } +} diff --git a/vendor/symfony/console/Tests/Fixtures/DescriptorCommand3.php b/vendor/symfony/console/Tests/Fixtures/DescriptorCommand3.php new file mode 100644 index 00000000..77f92e23 --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/DescriptorCommand3.php @@ -0,0 +1,27 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Tests\Fixtures; + +use Symfony\Component\Console\Command\Command; + +class DescriptorCommand3 extends Command +{ + protected function configure() + { + $this + ->setName('descriptor:command3') + ->setDescription('command 3 description') + ->setHelp('command 3 help') + ->setHidden(true) + ; + } +} diff --git a/vendor/symfony/console/Tests/Fixtures/DescriptorCommand4.php b/vendor/symfony/console/Tests/Fixtures/DescriptorCommand4.php new file mode 100644 index 00000000..13e8e5ba --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/DescriptorCommand4.php @@ -0,0 +1,25 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Tests\Fixtures; + +use Symfony\Component\Console\Command\Command; + +class DescriptorCommand4 extends Command +{ + protected function configure() + { + $this + ->setName('descriptor:command4') + ->setAliases(array('descriptor:alias_command4', 'command4:descriptor')) + ; + } +} diff --git a/vendor/symfony/console/Tests/Fixtures/DescriptorCommandMbString.php b/vendor/symfony/console/Tests/Fixtures/DescriptorCommandMbString.php new file mode 100644 index 00000000..66de917e --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/DescriptorCommandMbString.php @@ -0,0 +1,32 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Tests\Fixtures; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputOption; + +class DescriptorCommandMbString extends Command +{ + protected function configure() + { + $this + ->setName('descriptor:åèä') + ->setDescription('command åèä description') + ->setHelp('command åèä help') + ->addUsage('-o|--option_name <argument_name>') + ->addUsage('<argument_name>') + ->addArgument('argument_åèä', InputArgument::REQUIRED) + ->addOption('option_åèä', 'o', InputOption::VALUE_NONE) + ; + } +} diff --git a/vendor/symfony/console/Tests/Fixtures/DummyOutput.php b/vendor/symfony/console/Tests/Fixtures/DummyOutput.php index 0070c0a4..866e2143 100644 --- a/vendor/symfony/console/Tests/Fixtures/DummyOutput.php +++ b/vendor/symfony/console/Tests/Fixtures/DummyOutput.php @@ -26,7 +26,7 @@ class DummyOutput extends BufferedOutput public function getLogs() { $logs = array(); - foreach (explode("\n", trim($this->fetch())) as $message) { + foreach (explode(PHP_EOL, trim($this->fetch())) as $message) { preg_match('/^\[(.*)\] (.*)/', $message, $matches); $logs[] = sprintf('%s %s', $matches[1], $matches[2]); } diff --git a/vendor/symfony/console/Tests/Fixtures/Foo3Command.php b/vendor/symfony/console/Tests/Fixtures/Foo3Command.php index 6c890faf..adb3a2d8 100644 --- a/vendor/symfony/console/Tests/Fixtures/Foo3Command.php +++ b/vendor/symfony/console/Tests/Fixtures/Foo3Command.php @@ -23,7 +23,7 @@ class Foo3Command extends Command throw new \Exception('Second exception <comment>comment</comment>', 0, $e); } } catch (\Exception $e) { - throw new \Exception('Third exception <fg=blue;bg=red>comment</>', 0, $e); + throw new \Exception('Third exception <fg=blue;bg=red>comment</>', 404, $e); } } } diff --git a/vendor/symfony/console/Tests/Fixtures/FooLock2Command.php b/vendor/symfony/console/Tests/Fixtures/FooLock2Command.php new file mode 100644 index 00000000..4e4656f2 --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/FooLock2Command.php @@ -0,0 +1,28 @@ +<?php + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Command\LockableTrait; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class FooLock2Command extends Command +{ + use LockableTrait; + + protected function configure() + { + $this->setName('foo:lock2'); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + try { + $this->lock(); + $this->lock(); + } catch (LogicException $e) { + return 1; + } + + return 2; + } +} diff --git a/vendor/symfony/console/Tests/Fixtures/FooLockCommand.php b/vendor/symfony/console/Tests/Fixtures/FooLockCommand.php new file mode 100644 index 00000000..dfa28a6b --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/FooLockCommand.php @@ -0,0 +1,27 @@ +<?php + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Command\LockableTrait; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class FooLockCommand extends Command +{ + use LockableTrait; + + protected function configure() + { + $this->setName('foo:lock'); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + if (!$this->lock()) { + return 1; + } + + $this->release(); + + return 2; + } +} diff --git a/vendor/symfony/console/Tests/Fixtures/FooOptCommand.php b/vendor/symfony/console/Tests/Fixtures/FooOptCommand.php new file mode 100644 index 00000000..9043aa48 --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/FooOptCommand.php @@ -0,0 +1,36 @@ +<?php + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +class FooOptCommand extends Command +{ + public $input; + public $output; + + protected function configure() + { + $this + ->setName('foo:bar') + ->setDescription('The foo:bar command') + ->setAliases(array('afoobar')) + ->addOption('fooopt', 'fo', InputOption::VALUE_OPTIONAL, 'fooopt description') + ; + } + + protected function interact(InputInterface $input, OutputInterface $output) + { + $output->writeln('interact called'); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $this->input = $input; + $this->output = $output; + + $output->writeln('called'); + $output->writeln($this->input->getOption('fooopt')); + } +} diff --git a/vendor/symfony/console/Tests/Fixtures/FooSameCaseLowercaseCommand.php b/vendor/symfony/console/Tests/Fixtures/FooSameCaseLowercaseCommand.php new file mode 100644 index 00000000..c875be0c --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/FooSameCaseLowercaseCommand.php @@ -0,0 +1,11 @@ +<?php + +use Symfony\Component\Console\Command\Command; + +class FooSameCaseLowercaseCommand extends Command +{ + protected function configure() + { + $this->setName('foo:bar')->setDescription('foo:bar command'); + } +} diff --git a/vendor/symfony/console/Tests/Fixtures/FooSameCaseUppercaseCommand.php b/vendor/symfony/console/Tests/Fixtures/FooSameCaseUppercaseCommand.php new file mode 100644 index 00000000..75c8d002 --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/FooSameCaseUppercaseCommand.php @@ -0,0 +1,11 @@ +<?php + +use Symfony\Component\Console\Command\Command; + +class FooSameCaseUppercaseCommand extends Command +{ + protected function configure() + { + $this->setName('foo:BAR')->setDescription('foo:BAR command'); + } +} diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_0.php b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_0.php index 996fafb9..8fe7c077 100644 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_0.php +++ b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_0.php @@ -2,10 +2,10 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Tests\Style\SymfonyStyleWithForcedLineLength; +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 SymfonyStyleWithForcedLineLength($input, $output); + $output = new SymfonyStyle($input, $output); $output->caution('Lorem ipsum dolor sit amet'); }; diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_1.php b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_1.php index 6634cd56..e5c700d6 100644 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_1.php +++ b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_1.php @@ -2,11 +2,11 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Tests\Style\SymfonyStyleWithForcedLineLength; +use Symfony\Component\Console\Style\SymfonyStyle; //Ensure has single blank line between titles and blocks return function (InputInterface $input, OutputInterface $output) { - $output = new SymfonyStyleWithForcedLineLength($input, $output); + $output = new SymfonyStyle($input, $output); $output->title('Title'); $output->warning('Lorem ipsum dolor sit amet'); $output->title('Title'); diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_10.php b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_10.php index 4120df9c..3111873d 100644 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_10.php +++ b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_10.php @@ -2,11 +2,11 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Tests\Style\SymfonyStyleWithForcedLineLength; +use Symfony\Component\Console\Style\SymfonyStyle; //Ensure that all lines are aligned to the begin of the first line in a very long line block return function (InputInterface $input, OutputInterface $output) { - $output = new SymfonyStyleWithForcedLineLength($input, $output); + $output = new SymfonyStyle($input, $output); $output->block( 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum', 'CUSTOM', diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_11.php b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_11.php index a2781ddb..3ed897de 100644 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_11.php +++ b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_11.php @@ -2,12 +2,11 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Tests\Style\SymfonyStyleWithForcedLineLength; +use Symfony\Component\Console\Style\SymfonyStyle; -//Ensure that all lines are aligned to the begin of the first one and start with '//' in a very long line comment +// ensure long words are properly wrapped in blocks return function (InputInterface $input, OutputInterface $output) { - $output = new SymfonyStyleWithForcedLineLength($input, $output); - $output->comment( - 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum' - ); + $word = 'Lopadotemachoselachogaleokranioleipsanodrimhypotrimmatosilphioparaomelitokatakechymenokichlepikossyphophattoperisteralektryonoptekephalliokigklopeleiolagoiosiraiobaphetraganopterygon'; + $sfStyle = new SymfonyStyle($input, $output); + $sfStyle->block($word, 'CUSTOM', 'fg=white;bg=blue', ' § ', false); }; diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_12.php b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_12.php new file mode 100644 index 00000000..8c458ae7 --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_12.php @@ -0,0 +1,13 @@ +<?php + +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; + +// ensure that all lines are aligned to the begin of the first one and start with '//' in a very long line comment +return function (InputInterface $input, OutputInterface $output) { + $output = new SymfonyStyle($input, $output); + $output->comment( + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum' + ); +}; diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_13.php b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_13.php new file mode 100644 index 00000000..827cbad1 --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_13.php @@ -0,0 +1,14 @@ +<?php + +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; + +// ensure that nested tags have no effect on the color of the '//' prefix +return function (InputInterface $input, OutputInterface $output) { + $output->setDecorated(true); + $output = new SymfonyStyle($input, $output); + $output->comment( + 'Lorem ipsum dolor sit <comment>amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</comment> Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum' + ); +}; diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_14.php b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_14.php new file mode 100644 index 00000000..a893a48b --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_14.php @@ -0,0 +1,17 @@ +<?php + +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; + +// ensure that block() behaves properly with a prefix and without type +return function (InputInterface $input, OutputInterface $output) { + $output = new SymfonyStyle($input, $output); + $output->block( + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum', + null, + null, + '$ ', + true + ); +}; diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_15.php b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_15.php new file mode 100644 index 00000000..68402cd4 --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_15.php @@ -0,0 +1,14 @@ +<?php + +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; + +// ensure that block() behaves properly with a type and without prefix +return function (InputInterface $input, OutputInterface $output) { + $output = new SymfonyStyle($input, $output); + $output->block( + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum', + 'TEST' + ); +}; diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_16.php b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_16.php new file mode 100644 index 00000000..66e81796 --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_16.php @@ -0,0 +1,15 @@ +<?php + +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; + +// ensure that block() output is properly formatted (even padding lines) +return function (InputInterface $input, OutputInterface $output) { + $output->setDecorated(true); + $output = new SymfonyStyle($input, $output); + $output->success( + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum', + 'TEST' + ); +}; diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_17.php b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_17.php new file mode 100644 index 00000000..311e6b39 --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_17.php @@ -0,0 +1,13 @@ +<?php + +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; + +//Ensure symfony style helper methods handle trailing backslashes properly when decorating user texts +return function (InputInterface $input, OutputInterface $output) { + $output = new SymfonyStyle($input, $output); + + $output->title('Title ending with \\'); + $output->section('Section ending with \\'); +}; diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_2.php b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_2.php index 6004e3d6..791b626f 100644 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_2.php +++ b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_2.php @@ -2,11 +2,11 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Tests\Style\SymfonyStyleWithForcedLineLength; +use Symfony\Component\Console\Style\SymfonyStyle; //Ensure has single blank line between blocks return function (InputInterface $input, OutputInterface $output) { - $output = new SymfonyStyleWithForcedLineLength($input, $output); + $output = new SymfonyStyle($input, $output); $output->warning('Warning'); $output->caution('Caution'); $output->error('Error'); diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_3.php b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_3.php index c7a08f13..99253a6c 100644 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_3.php +++ b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_3.php @@ -2,11 +2,11 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Tests\Style\SymfonyStyleWithForcedLineLength; +use Symfony\Component\Console\Style\SymfonyStyle; //Ensure has single blank line between two titles return function (InputInterface $input, OutputInterface $output) { - $output = new SymfonyStyleWithForcedLineLength($input, $output); + $output = new SymfonyStyle($input, $output); $output->title('First title'); $output->title('Second title'); }; diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_4.php b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_4.php index afea70c7..0c5d3fb2 100644 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_4.php +++ b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_4.php @@ -2,11 +2,11 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Tests\Style\SymfonyStyleWithForcedLineLength; +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 SymfonyStyleWithForcedLineLength($input, $output); + $output = new SymfonyStyle($input, $output); $output->write('Lorem ipsum dolor sit amet'); $output->title('First title'); diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_5.php b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_5.php index d2c68a9e..96433ed5 100644 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_5.php +++ b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_5.php @@ -2,11 +2,11 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Tests\Style\SymfonyStyleWithForcedLineLength; +use Symfony\Component\Console\Style\SymfonyStyle; -//Ensure has proper line ending before outputing a text block like with SymfonyStyle::listing() or SymfonyStyle::text() +//Ensure has proper line ending before outputting a text block like with SymfonyStyle::listing() or SymfonyStyle::text() return function (InputInterface $input, OutputInterface $output) { - $output = new SymfonyStyleWithForcedLineLength($input, $output); + $output = new SymfonyStyle($input, $output); $output->writeln('Lorem ipsum dolor sit amet'); $output->listing(array( diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_6.php b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_6.php index f1d79905..8031ec9c 100644 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_6.php +++ b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_6.php @@ -2,11 +2,11 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Tests\Style\SymfonyStyleWithForcedLineLength; +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 SymfonyStyleWithForcedLineLength($input, $output); + $output = new SymfonyStyle($input, $output); $output->listing(array( 'Lorem ipsum dolor sit amet', diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_7.php b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_7.php index cbfea734..203eb5b1 100644 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_7.php +++ b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_7.php @@ -2,11 +2,11 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Tests\Style\SymfonyStyleWithForcedLineLength; +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 SymfonyStyleWithForcedLineLength($input, $output); + $output = new SymfonyStyle($input, $output); $output->title('Title'); $output->askHidden('Hidden question'); $output->choice('Choice question with default', array('choice1', 'choice2'), 'choice1'); diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_8.php b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_8.php index 0244fd27..922ef1f9 100644 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_8.php +++ b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_8.php @@ -2,7 +2,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Tests\Style\SymfonyStyleWithForcedLineLength; +use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Console\Helper\TableCell; //Ensure formatting tables when using multiple headers with TableCell @@ -21,6 +21,6 @@ return function (InputInterface $input, OutputInterface $output) { array('978-0804169127', 'Divine Comedy'), ); - $output = new SymfonyStyleWithForcedLineLength($input, $output); + $output = new SymfonyStyle($input, $output); $output->table($headers, $rows); }; diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_9.php b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_9.php index 6420730f..57afdf06 100644 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_9.php +++ b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_9.php @@ -2,10 +2,10 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Tests\Style\SymfonyStyleWithForcedLineLength; +use Symfony\Component\Console\Style\SymfonyStyle; //Ensure that all lines are aligned to the begin of the first line in a multi-line block return function (InputInterface $input, OutputInterface $output) { - $output = new SymfonyStyleWithForcedLineLength($input, $output); + $output = new SymfonyStyle($input, $output); $output->block(array('Custom block', 'Second custom block line'), 'CUSTOM', 'fg=white;bg=green', 'X ', true); }; diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/interactive_command_1.php b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/interactive_command_1.php new file mode 100644 index 00000000..3c9c7440 --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/interactive_command_1.php @@ -0,0 +1,19 @@ +<?php + +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; + +//Ensure that questions have the expected outputs +return function (InputInterface $input, OutputInterface $output) { + $output = new SymfonyStyle($input, $output); + $stream = fopen('php://memory', 'r+', false); + + fwrite($stream, "Foo\nBar\nBaz"); + rewind($stream); + $input->setStream($stream); + + $output->ask('What\'s your name?'); + $output->ask('How are you?'); + $output->ask('Where do you come from?'); +}; diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/interactive_output_1.txt b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/interactive_output_1.txt new file mode 100644 index 00000000..6fc7d7eb --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/interactive_output_1.txt @@ -0,0 +1,7 @@ + + What's your name?: + > + How are you?: + > + Where do you come from?: + > diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_11.txt b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_11.txt index 9983af83..190d7840 100644 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_11.txt +++ b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_11.txt @@ -1,6 +1,4 @@ - // Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna - // aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. - // Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur - // sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum + § [CUSTOM] Lopadotemachoselachogaleokranioleipsanodrimhypotrimmatosilphioparaomelitokatakechymenokichlepikossyphophatto + § peristeralektryonoptekephalliokigklopeleiolagoiosiraiobaphetraganopterygon diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_12.txt b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_12.txt new file mode 100644 index 00000000..9983af83 --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_12.txt @@ -0,0 +1,6 @@ + + // Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna + // aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. + // Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur + // sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum + diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_13.txt b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_13.txt new file mode 100644 index 00000000..0f3704b7 --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_13.txt @@ -0,0 +1,7 @@ + +[39;49m // [39;49mLorem ipsum dolor sit [33mamet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et [39m +[39;49m // [39;49m[33mdolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea [39m +[39;49m // [39;49m[33mcommodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla [39m +[39;49m // [39;49m[33mpariatur.[39m Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim +[39;49m // [39;49mid est laborum + diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_14.txt b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_14.txt new file mode 100644 index 00000000..1d0d37e7 --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_14.txt @@ -0,0 +1,6 @@ + +$ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna +$ aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. +$ Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint +$ occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum + diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_15.txt b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_15.txt new file mode 100644 index 00000000..66404b81 --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_15.txt @@ -0,0 +1,7 @@ + + [TEST] Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore + magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla + pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est + laborum + diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_16.txt b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_16.txt new file mode 100644 index 00000000..a0d18016 --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_16.txt @@ -0,0 +1,8 @@ + +[30;42m [39;49m +[30;42m [OK] Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore [39;49m +[30;42m magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo [39;49m +[30;42m consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. [39;49m +[30;42m Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum [39;49m +[30;42m [39;49m + diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_17.txt b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_17.txt new file mode 100644 index 00000000..59d00e04 --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_17.txt @@ -0,0 +1,7 @@ + +Title ending with \ +=================== + +Section ending with \ +--------------------- + diff --git a/vendor/symfony/console/Tests/Fixtures/application_1.json b/vendor/symfony/console/Tests/Fixtures/application_1.json index b17b38d8..29faa826 100644 --- a/vendor/symfony/console/Tests/Fixtures/application_1.json +++ b/vendor/symfony/console/Tests/Fixtures/application_1.json @@ -1 +1,156 @@ -{"commands":[{"name":"help","usage":["help [--xml] [--format FORMAT] [--raw] [--] [<command_name>]"],"description":"Displays help for a command","help":"The <info>help<\/info> command displays help for a given command:\n\n <info>php app\/console help list<\/info>\n\nYou can also output the help in other formats by using the <comment>--format<\/comment> option:\n\n <info>php app\/console help --format=xml list<\/info>\n\nTo display the list of available commands, please use the <info>list<\/info> command.","definition":{"arguments":{"command_name":{"name":"command_name","is_required":false,"is_array":false,"description":"The command name","default":"help"}},"options":{"xml":{"name":"--xml","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output help as XML","default":false},"format":{"name":"--format","shortcut":"","accept_value":true,"is_value_required":true,"is_multiple":false,"description":"The output format (txt, xml, json, or md)","default":"txt"},"raw":{"name":"--raw","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output raw command help","default":false},"help":{"name":"--help","shortcut":"-h","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Display this help message","default":false},"quiet":{"name":"--quiet","shortcut":"-q","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Do not output any message","default":false},"verbose":{"name":"--verbose","shortcut":"-v|-vv|-vvv","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug","default":false},"version":{"name":"--version","shortcut":"-V","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Display this application version","default":false},"ansi":{"name":"--ansi","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Force ANSI output","default":false},"no-ansi":{"name":"--no-ansi","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Disable ANSI output","default":false},"no-interaction":{"name":"--no-interaction","shortcut":"-n","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Do not ask any interactive question","default":false}}}},{"name":"list","usage":["list [--xml] [--raw] [--format FORMAT] [--] [<namespace>]"],"description":"Lists commands","help":"The <info>list<\/info> command lists all commands:\n\n <info>php app\/console list<\/info>\n\nYou can also display the commands for a specific namespace:\n\n <info>php app\/console list test<\/info>\n\nYou can also output the information in other formats by using the <comment>--format<\/comment> option:\n\n <info>php app\/console list --format=xml<\/info>\n\nIt's also possible to get raw list of commands (useful for embedding command runner):\n\n <info>php app\/console list --raw<\/info>","definition":{"arguments":{"namespace":{"name":"namespace","is_required":false,"is_array":false,"description":"The namespace name","default":null}},"options":{"xml":{"name":"--xml","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output list as XML","default":false},"raw":{"name":"--raw","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output raw command list","default":false},"format":{"name":"--format","shortcut":"","accept_value":true,"is_value_required":true,"is_multiple":false,"description":"The output format (txt, xml, json, or md)","default":"txt"}}}}],"namespaces":[{"id":"_global","commands":["help","list"]}]} +{ + "commands": [ + { + "name": "help", + "hidden": false, + "usage": [ + "help [--format FORMAT] [--raw] [--] [<command_name>]" + ], + "description": "Displays help for a command", + "help": "The <info>help<\/info> command displays help for a given command:\n\n <info>php app\/console help list<\/info>\n\nYou can also output the help in other formats by using the <comment>--format<\/comment> option:\n\n <info>php app\/console help --format=xml list<\/info>\n\nTo display the list of available commands, please use the <info>list<\/info> command.", + "definition": { + "arguments": { + "command_name": { + "name": "command_name", + "is_required": false, + "is_array": false, + "description": "The command name", + "default": "help" + } + }, + "options": { + "format": { + "name": "--format", + "shortcut": "", + "accept_value": true, + "is_value_required": true, + "is_multiple": false, + "description": "The output format (txt, xml, json, or md)", + "default": "txt" + }, + "raw": { + "name": "--raw", + "shortcut": "", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "To output raw command help", + "default": false + }, + "help": { + "name": "--help", + "shortcut": "-h", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Display this help message", + "default": false + }, + "quiet": { + "name": "--quiet", + "shortcut": "-q", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Do not output any message", + "default": false + }, + "verbose": { + "name": "--verbose", + "shortcut": "-v|-vv|-vvv", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug", + "default": false + }, + "version": { + "name": "--version", + "shortcut": "-V", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Display this application version", + "default": false + }, + "ansi": { + "name": "--ansi", + "shortcut": "", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Force ANSI output", + "default": false + }, + "no-ansi": { + "name": "--no-ansi", + "shortcut": "", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Disable ANSI output", + "default": false + }, + "no-interaction": { + "name": "--no-interaction", + "shortcut": "-n", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Do not ask any interactive question", + "default": false + } + } + } + }, + { + "name": "list", + "hidden": false, + "usage": [ + "list [--raw] [--format FORMAT] [--] [<namespace>]" + ], + "description": "Lists commands", + "help": "The <info>list<\/info> command lists all commands:\n\n <info>php app\/console list<\/info>\n\nYou can also display the commands for a specific namespace:\n\n <info>php app\/console list test<\/info>\n\nYou can also output the information in other formats by using the <comment>--format<\/comment> option:\n\n <info>php app\/console list --format=xml<\/info>\n\nIt's also possible to get raw list of commands (useful for embedding command runner):\n\n <info>php app\/console list --raw<\/info>", + "definition": { + "arguments": { + "namespace": { + "name": "namespace", + "is_required": false, + "is_array": false, + "description": "The namespace name", + "default": null + } + }, + "options": { + "raw": { + "name": "--raw", + "shortcut": "", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "To output raw command list", + "default": false + }, + "format": { + "name": "--format", + "shortcut": "", + "accept_value": true, + "is_value_required": true, + "is_multiple": false, + "description": "The output format (txt, xml, json, or md)", + "default": "txt" + } + } + } + } + ], + "namespaces": [ + { + "id": "_global", + "commands": [ + "help", + "list" + ] + } + ] +} diff --git a/vendor/symfony/console/Tests/Fixtures/application_1.md b/vendor/symfony/console/Tests/Fixtures/application_1.md index 82a605da..b46c975a 100644 --- a/vendor/symfony/console/Tests/Fixtures/application_1.md +++ b/vendor/symfony/console/Tests/Fixtures/application_1.md @@ -1,201 +1,172 @@ -UNKNOWN -======= +Console Tool +============ -* help -* list +* [`help`](#help) +* [`list`](#list) -help ----- +`help` +------ -* Description: Displays help for a command -* Usage: +Displays help for a command - * `help [--xml] [--format FORMAT] [--raw] [--] [<command_name>]` +### Usage -The <info>help</info> command displays help for a given command: +* `help [--format FORMAT] [--raw] [--] [<command_name>]` - <info>php app/console help list</info> +The help command displays help for a given command: -You can also output the help in other formats by using the <comment>--format</comment> option: + php app/console help list - <info>php app/console help --format=xml list</info> +You can also output the help in other formats by using the --format option: -To display the list of available commands, please use the <info>list</info> command. + php app/console help --format=xml list -### Arguments: +To display the list of available commands, please use the list command. -**command_name:** +### Arguments + +#### `command_name` + +The command name -* Name: command_name * Is required: no * Is array: no -* Description: The command name * Default: `'help'` -### Options: - -**xml:** +### Options -* Name: `--xml` -* Shortcut: <none> -* Accept value: no -* Is value required: no -* Is multiple: no -* Description: To output help as XML -* Default: `false` +#### `--format` -**format:** +The output format (txt, xml, json, or md) -* Name: `--format` -* Shortcut: <none> * Accept value: yes * Is value required: yes * Is multiple: no -* Description: The output format (txt, xml, json, or md) * Default: `'txt'` -**raw:** +#### `--raw` + +To output raw command help -* Name: `--raw` -* Shortcut: <none> * Accept value: no * Is value required: no * Is multiple: no -* Description: To output raw command help * Default: `false` -**help:** +#### `--help|-h` + +Display this help message -* Name: `--help` -* Shortcut: `-h` * Accept value: no * Is value required: no * Is multiple: no -* Description: Display this help message * Default: `false` -**quiet:** +#### `--quiet|-q` + +Do not output any message -* Name: `--quiet` -* Shortcut: `-q` * Accept value: no * Is value required: no * Is multiple: no -* Description: Do not output any message * Default: `false` -**verbose:** +#### `--verbose|-v|-vv|-vvv` + +Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug -* Name: `--verbose` -* Shortcut: `-v|-vv|-vvv` * Accept value: no * Is value required: no * Is multiple: no -* Description: Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug * Default: `false` -**version:** +#### `--version|-V` + +Display this application version -* Name: `--version` -* Shortcut: `-V` * Accept value: no * Is value required: no * Is multiple: no -* Description: Display this application version * Default: `false` -**ansi:** +#### `--ansi` + +Force ANSI output -* Name: `--ansi` -* Shortcut: <none> * Accept value: no * Is value required: no * Is multiple: no -* Description: Force ANSI output * Default: `false` -**no-ansi:** +#### `--no-ansi` + +Disable ANSI output -* Name: `--no-ansi` -* Shortcut: <none> * Accept value: no * Is value required: no * Is multiple: no -* Description: Disable ANSI output * Default: `false` -**no-interaction:** +#### `--no-interaction|-n` + +Do not ask any interactive question -* Name: `--no-interaction` -* Shortcut: `-n` * Accept value: no * Is value required: no * Is multiple: no -* Description: Do not ask any interactive question * Default: `false` -list ----- +`list` +------ -* Description: Lists commands -* Usage: +Lists commands - * `list [--xml] [--raw] [--format FORMAT] [--] [<namespace>]` +### Usage -The <info>list</info> command lists all commands: +* `list [--raw] [--format FORMAT] [--] [<namespace>]` - <info>php app/console list</info> +The list command lists all commands: + + php app/console list You can also display the commands for a specific namespace: - <info>php app/console list test</info> + php app/console list test -You can also output the information in other formats by using the <comment>--format</comment> option: +You can also output the information in other formats by using the --format option: - <info>php app/console list --format=xml</info> + php app/console list --format=xml It's also possible to get raw list of commands (useful for embedding command runner): - <info>php app/console list --raw</info> + php app/console list --raw + +### Arguments -### Arguments: +#### `namespace` -**namespace:** +The namespace name -* Name: namespace * Is required: no * Is array: no -* Description: The namespace name * Default: `NULL` -### Options: +### Options -**xml:** +#### `--raw` -* Name: `--xml` -* Shortcut: <none> -* Accept value: no -* Is value required: no -* Is multiple: no -* Description: To output list as XML -* Default: `false` +To output raw command list -**raw:** - -* Name: `--raw` -* Shortcut: <none> * Accept value: no * Is value required: no * Is multiple: no -* Description: To output raw command list * Default: `false` -**format:** +#### `--format` + +The output format (txt, xml, json, or md) -* Name: `--format` -* Shortcut: <none> * Accept value: yes * Is value required: yes * Is multiple: no -* Description: The output format (txt, xml, json, or md) * Default: `'txt'` diff --git a/vendor/symfony/console/Tests/Fixtures/application_1.txt b/vendor/symfony/console/Tests/Fixtures/application_1.txt index c4cf8f21..8a7b47e0 100644 --- a/vendor/symfony/console/Tests/Fixtures/application_1.txt +++ b/vendor/symfony/console/Tests/Fixtures/application_1.txt @@ -1,4 +1,4 @@ -<info>Console Tool</info> +Console Tool <comment>Usage:</comment> command [options] [arguments] diff --git a/vendor/symfony/console/Tests/Fixtures/application_1.xml b/vendor/symfony/console/Tests/Fixtures/application_1.xml index 35d1db4d..a0bd076c 100644 --- a/vendor/symfony/console/Tests/Fixtures/application_1.xml +++ b/vendor/symfony/console/Tests/Fixtures/application_1.xml @@ -1,9 +1,9 @@ <?xml version="1.0" encoding="UTF-8"?> <symfony> <commands> - <command id="help" name="help"> + <command id="help" name="help" hidden="0"> <usages> - <usage>help [--xml] [--format FORMAT] [--raw] [--] [<command_name>]</usage> + <usage>help [--format FORMAT] [--raw] [--] [<command_name>]</usage> </usages> <description>Displays help for a command</description> <help>The <info>help</info> command displays help for a given command: @@ -24,9 +24,6 @@ </argument> </arguments> <options> - <option name="--xml" shortcut="" accept_value="0" is_value_required="0" is_multiple="0"> - <description>To output help as XML</description> - </option> <option name="--format" shortcut="" accept_value="1" is_value_required="1" is_multiple="0"> <description>The output format (txt, xml, json, or md)</description> <defaults> @@ -59,9 +56,9 @@ </option> </options> </command> - <command id="list" name="list"> + <command id="list" name="list" hidden="0"> <usages> - <usage>list [--xml] [--raw] [--format FORMAT] [--] [<namespace>]</usage> + <usage>list [--raw] [--format FORMAT] [--] [<namespace>]</usage> </usages> <description>Lists commands</description> <help>The <info>list</info> command lists all commands: @@ -86,9 +83,6 @@ </argument> </arguments> <options> - <option name="--xml" shortcut="" accept_value="0" is_value_required="0" is_multiple="0"> - <description>To output list as XML</description> - </option> <option name="--raw" shortcut="" accept_value="0" is_value_required="0" is_multiple="0"> <description>To output raw command list</description> </option> diff --git a/vendor/symfony/console/Tests/Fixtures/application_2.json b/vendor/symfony/console/Tests/Fixtures/application_2.json index e47a7a96..4777a60b 100644 --- a/vendor/symfony/console/Tests/Fixtures/application_2.json +++ b/vendor/symfony/console/Tests/Fixtures/application_2.json @@ -1 +1,509 @@ -{"commands":[{"name":"help","usage":["help [--xml] [--format FORMAT] [--raw] [--] [<command_name>]"],"description":"Displays help for a command","help":"The <info>help<\/info> command displays help for a given command:\n\n <info>php app\/console help list<\/info>\n\nYou can also output the help in other formats by using the <comment>--format<\/comment> option:\n\n <info>php app\/console help --format=xml list<\/info>\n\nTo display the list of available commands, please use the <info>list<\/info> command.","definition":{"arguments":{"command_name":{"name":"command_name","is_required":false,"is_array":false,"description":"The command name","default":"help"}},"options":{"xml":{"name":"--xml","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output help as XML","default":false},"format":{"name":"--format","shortcut":"","accept_value":true,"is_value_required":true,"is_multiple":false,"description":"The output format (txt, xml, json, or md)","default":"txt"},"raw":{"name":"--raw","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output raw command help","default":false},"help":{"name":"--help","shortcut":"-h","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Display this help message","default":false},"quiet":{"name":"--quiet","shortcut":"-q","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Do not output any message","default":false},"verbose":{"name":"--verbose","shortcut":"-v|-vv|-vvv","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug","default":false},"version":{"name":"--version","shortcut":"-V","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Display this application version","default":false},"ansi":{"name":"--ansi","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Force ANSI output","default":false},"no-ansi":{"name":"--no-ansi","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Disable ANSI output","default":false},"no-interaction":{"name":"--no-interaction","shortcut":"-n","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Do not ask any interactive question","default":false}}}},{"name":"list","usage":["list [--xml] [--raw] [--format FORMAT] [--] [<namespace>]"],"description":"Lists commands","help":"The <info>list<\/info> command lists all commands:\n\n <info>php app\/console list<\/info>\n\nYou can also display the commands for a specific namespace:\n\n <info>php app\/console list test<\/info>\n\nYou can also output the information in other formats by using the <comment>--format<\/comment> option:\n\n <info>php app\/console list --format=xml<\/info>\n\nIt's also possible to get raw list of commands (useful for embedding command runner):\n\n <info>php app\/console list --raw<\/info>","definition":{"arguments":{"namespace":{"name":"namespace","is_required":false,"is_array":false,"description":"The namespace name","default":null}},"options":{"xml":{"name":"--xml","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output list as XML","default":false},"raw":{"name":"--raw","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output raw command list","default":false},"format":{"name":"--format","shortcut":"","accept_value":true,"is_value_required":true,"is_multiple":false,"description":"The output format (txt, xml, json, or md)","default":"txt"}}}},{"name":"descriptor:command1","usage":["descriptor:command1", "alias1", "alias2"],"description":"command 1 description","help":"command 1 help","definition":{"arguments":[],"options":{"help":{"name":"--help","shortcut":"-h","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Display this help message","default":false},"quiet":{"name":"--quiet","shortcut":"-q","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Do not output any message","default":false},"verbose":{"name":"--verbose","shortcut":"-v|-vv|-vvv","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug","default":false},"version":{"name":"--version","shortcut":"-V","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Display this application version","default":false},"ansi":{"name":"--ansi","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Force ANSI output","default":false},"no-ansi":{"name":"--no-ansi","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Disable ANSI output","default":false},"no-interaction":{"name":"--no-interaction","shortcut":"-n","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Do not ask any interactive question","default":false}}}},{"name":"descriptor:command2","usage":["descriptor:command2 [-o|--option_name] [--] <argument_name>", "descriptor:command2 -o|--option_name <argument_name>", "descriptor:command2 <argument_name>"],"description":"command 2 description","help":"command 2 help","definition":{"arguments":{"argument_name":{"name":"argument_name","is_required":true,"is_array":false,"description":"","default":null}},"options":{"option_name":{"name":"--option_name","shortcut":"-o","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"","default":false},"help":{"name":"--help","shortcut":"-h","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Display this help message","default":false},"quiet":{"name":"--quiet","shortcut":"-q","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Do not output any message","default":false},"verbose":{"name":"--verbose","shortcut":"-v|-vv|-vvv","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug","default":false},"version":{"name":"--version","shortcut":"-V","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Display this application version","default":false},"ansi":{"name":"--ansi","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Force ANSI output","default":false},"no-ansi":{"name":"--no-ansi","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Disable ANSI output","default":false},"no-interaction":{"name":"--no-interaction","shortcut":"-n","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Do not ask any interactive question","default":false}}}}],"namespaces":[{"id":"_global","commands":["alias1","alias2","help","list"]},{"id":"descriptor","commands":["descriptor:command1","descriptor:command2"]}]}
\ No newline at end of file +{ + "application": { + "name": "My Symfony application", + "version": "v1.0" + }, + "commands": [ + { + "name": "help", + "hidden": false, + "usage": [ + "help [--format FORMAT] [--raw] [--] [<command_name>]" + ], + "description": "Displays help for a command", + "help": "The <info>help<\/info> command displays help for a given command:\n\n <info>php app\/console help list<\/info>\n\nYou can also output the help in other formats by using the <comment>--format<\/comment> option:\n\n <info>php app\/console help --format=xml list<\/info>\n\nTo display the list of available commands, please use the <info>list<\/info> command.", + "definition": { + "arguments": { + "command_name": { + "name": "command_name", + "is_required": false, + "is_array": false, + "description": "The command name", + "default": "help" + } + }, + "options": { + "format": { + "name": "--format", + "shortcut": "", + "accept_value": true, + "is_value_required": true, + "is_multiple": false, + "description": "The output format (txt, xml, json, or md)", + "default": "txt" + }, + "raw": { + "name": "--raw", + "shortcut": "", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "To output raw command help", + "default": false + }, + "help": { + "name": "--help", + "shortcut": "-h", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Display this help message", + "default": false + }, + "quiet": { + "name": "--quiet", + "shortcut": "-q", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Do not output any message", + "default": false + }, + "verbose": { + "name": "--verbose", + "shortcut": "-v|-vv|-vvv", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug", + "default": false + }, + "version": { + "name": "--version", + "shortcut": "-V", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Display this application version", + "default": false + }, + "ansi": { + "name": "--ansi", + "shortcut": "", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Force ANSI output", + "default": false + }, + "no-ansi": { + "name": "--no-ansi", + "shortcut": "", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Disable ANSI output", + "default": false + }, + "no-interaction": { + "name": "--no-interaction", + "shortcut": "-n", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Do not ask any interactive question", + "default": false + } + } + } + }, + { + "name": "list", + "hidden": false, + "usage": [ + "list [--raw] [--format FORMAT] [--] [<namespace>]" + ], + "description": "Lists commands", + "help": "The <info>list<\/info> command lists all commands:\n\n <info>php app\/console list<\/info>\n\nYou can also display the commands for a specific namespace:\n\n <info>php app\/console list test<\/info>\n\nYou can also output the information in other formats by using the <comment>--format<\/comment> option:\n\n <info>php app\/console list --format=xml<\/info>\n\nIt's also possible to get raw list of commands (useful for embedding command runner):\n\n <info>php app\/console list --raw<\/info>", + "definition": { + "arguments": { + "namespace": { + "name": "namespace", + "is_required": false, + "is_array": false, + "description": "The namespace name", + "default": null + } + }, + "options": { + "raw": { + "name": "--raw", + "shortcut": "", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "To output raw command list", + "default": false + }, + "format": { + "name": "--format", + "shortcut": "", + "accept_value": true, + "is_value_required": true, + "is_multiple": false, + "description": "The output format (txt, xml, json, or md)", + "default": "txt" + } + } + } + }, + { + "name": "descriptor:command1", + "hidden": false, + "usage": [ + "descriptor:command1", + "alias1", + "alias2" + ], + "description": "command 1 description", + "help": "command 1 help", + "definition": { + "arguments": [], + "options": { + "help": { + "name": "--help", + "shortcut": "-h", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Display this help message", + "default": false + }, + "quiet": { + "name": "--quiet", + "shortcut": "-q", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Do not output any message", + "default": false + }, + "verbose": { + "name": "--verbose", + "shortcut": "-v|-vv|-vvv", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug", + "default": false + }, + "version": { + "name": "--version", + "shortcut": "-V", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Display this application version", + "default": false + }, + "ansi": { + "name": "--ansi", + "shortcut": "", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Force ANSI output", + "default": false + }, + "no-ansi": { + "name": "--no-ansi", + "shortcut": "", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Disable ANSI output", + "default": false + }, + "no-interaction": { + "name": "--no-interaction", + "shortcut": "-n", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Do not ask any interactive question", + "default": false + } + } + } + }, + { + "name": "descriptor:command2", + "hidden": false, + "usage": [ + "descriptor:command2 [-o|--option_name] [--] <argument_name>", + "descriptor:command2 -o|--option_name <argument_name>", + "descriptor:command2 <argument_name>" + ], + "description": "command 2 description", + "help": "command 2 help", + "definition": { + "arguments": { + "argument_name": { + "name": "argument_name", + "is_required": true, + "is_array": false, + "description": "", + "default": null + } + }, + "options": { + "option_name": { + "name": "--option_name", + "shortcut": "-o", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "", + "default": false + }, + "help": { + "name": "--help", + "shortcut": "-h", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Display this help message", + "default": false + }, + "quiet": { + "name": "--quiet", + "shortcut": "-q", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Do not output any message", + "default": false + }, + "verbose": { + "name": "--verbose", + "shortcut": "-v|-vv|-vvv", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug", + "default": false + }, + "version": { + "name": "--version", + "shortcut": "-V", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Display this application version", + "default": false + }, + "ansi": { + "name": "--ansi", + "shortcut": "", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Force ANSI output", + "default": false + }, + "no-ansi": { + "name": "--no-ansi", + "shortcut": "", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Disable ANSI output", + "default": false + }, + "no-interaction": { + "name": "--no-interaction", + "shortcut": "-n", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Do not ask any interactive question", + "default": false + } + } + } + }, + { + "name": "descriptor:command3", + "hidden": true, + "usage": [ + "descriptor:command3" + ], + "description": "command 3 description", + "help": "command 3 help", + "definition": { + "arguments": {}, + "options": { + "help": { + "name": "--help", + "shortcut": "-h", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Display this help message", + "default": false + }, + "quiet": { + "name": "--quiet", + "shortcut": "-q", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Do not output any message", + "default": false + }, + "verbose": { + "name": "--verbose", + "shortcut": "-v|-vv|-vvv", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug", + "default": false + }, + "version": { + "name": "--version", + "shortcut": "-V", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Display this application version", + "default": false + }, + "ansi": { + "name": "--ansi", + "shortcut": "", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Force ANSI output", + "default": false + }, + "no-ansi": { + "name": "--no-ansi", + "shortcut": "", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Disable ANSI output", + "default": false + }, + "no-interaction": { + "name": "--no-interaction", + "shortcut": "-n", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Do not ask any interactive question", + "default": false + } + } + } + }, + { + "name": "descriptor:command4", + "hidden": false, + "usage": [ + "descriptor:command4", + "descriptor:alias_command4", + "command4:descriptor" + ], + "description": null, + "help": "", + "definition": { + "arguments": {}, + "options": { + "help": { + "name": "--help", + "shortcut": "-h", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Display this help message", + "default": false + }, + "quiet": { + "name": "--quiet", + "shortcut": "-q", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Do not output any message", + "default": false + }, + "verbose": { + "name": "--verbose", + "shortcut": "-v|-vv|-vvv", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug", + "default": false + }, + "version": { + "name": "--version", + "shortcut": "-V", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Display this application version", + "default": false + }, + "ansi": { + "name": "--ansi", + "shortcut": "", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Force ANSI output", + "default": false + }, + "no-ansi": { + "name": "--no-ansi", + "shortcut": "", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Disable ANSI output", + "default": false + }, + "no-interaction": { + "name": "--no-interaction", + "shortcut": "-n", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "Do not ask any interactive question", + "default": false + } + } + } + } + ], + "namespaces": [ + { + "id": "_global", + "commands": [ + "alias1", + "alias2", + "help", + "list" + ] + }, + { + "id": "command4", + "commands": [ + "command4:descriptor" + ] + }, + { + "id": "descriptor", + "commands": [ + "descriptor:alias_command4", + "descriptor:command1", + "descriptor:command2", + "descriptor:command3", + "descriptor:command4" + ] + } + ] +} diff --git a/vendor/symfony/console/Tests/Fixtures/application_2.md b/vendor/symfony/console/Tests/Fixtures/application_2.md index f031c9e5..5b4896c0 100644 --- a/vendor/symfony/console/Tests/Fixtures/application_2.md +++ b/vendor/symfony/console/Tests/Fixtures/application_2.md @@ -1,396 +1,431 @@ -My Symfony application -====================== +My Symfony application v1.0 +=========================== -* alias1 -* alias2 -* help -* list +* [`alias1`](#descriptorcommand1) +* [`alias2`](#descriptorcommand1) +* [`help`](#help) +* [`list`](#list) + +**command4:** + +* [`command4:descriptor`](#descriptorcommand4) **descriptor:** -* descriptor:command1 -* descriptor:command2 +* [`descriptor:alias_command4`](#descriptorcommand4) +* [`descriptor:command1`](#descriptorcommand1) +* [`descriptor:command2`](#descriptorcommand2) +* [`descriptor:command4`](#descriptorcommand4) + +`help` +------ -help ----- +Displays help for a command -* Description: Displays help for a command -* Usage: +### Usage - * `help [--xml] [--format FORMAT] [--raw] [--] [<command_name>]` +* `help [--format FORMAT] [--raw] [--] [<command_name>]` -The <info>help</info> command displays help for a given command: +The help command displays help for a given command: - <info>php app/console help list</info> + php app/console help list -You can also output the help in other formats by using the <comment>--format</comment> option: +You can also output the help in other formats by using the --format option: - <info>php app/console help --format=xml list</info> + php app/console help --format=xml list -To display the list of available commands, please use the <info>list</info> command. +To display the list of available commands, please use the list command. -### Arguments: +### Arguments -**command_name:** +#### `command_name` + +The command name -* Name: command_name * Is required: no * Is array: no -* Description: The command name * Default: `'help'` -### Options: - -**xml:** +### Options -* Name: `--xml` -* Shortcut: <none> -* Accept value: no -* Is value required: no -* Is multiple: no -* Description: To output help as XML -* Default: `false` +#### `--format` -**format:** +The output format (txt, xml, json, or md) -* Name: `--format` -* Shortcut: <none> * Accept value: yes * Is value required: yes * Is multiple: no -* Description: The output format (txt, xml, json, or md) * Default: `'txt'` -**raw:** +#### `--raw` + +To output raw command help -* Name: `--raw` -* Shortcut: <none> * Accept value: no * Is value required: no * Is multiple: no -* Description: To output raw command help * Default: `false` -**help:** +#### `--help|-h` + +Display this help message -* Name: `--help` -* Shortcut: `-h` * Accept value: no * Is value required: no * Is multiple: no -* Description: Display this help message * Default: `false` -**quiet:** +#### `--quiet|-q` + +Do not output any message -* Name: `--quiet` -* Shortcut: `-q` * Accept value: no * Is value required: no * Is multiple: no -* Description: Do not output any message * Default: `false` -**verbose:** +#### `--verbose|-v|-vv|-vvv` + +Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug -* Name: `--verbose` -* Shortcut: `-v|-vv|-vvv` * Accept value: no * Is value required: no * Is multiple: no -* Description: Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug * Default: `false` -**version:** +#### `--version|-V` + +Display this application version -* Name: `--version` -* Shortcut: `-V` * Accept value: no * Is value required: no * Is multiple: no -* Description: Display this application version * Default: `false` -**ansi:** +#### `--ansi` + +Force ANSI output -* Name: `--ansi` -* Shortcut: <none> * Accept value: no * Is value required: no * Is multiple: no -* Description: Force ANSI output * Default: `false` -**no-ansi:** +#### `--no-ansi` + +Disable ANSI output -* Name: `--no-ansi` -* Shortcut: <none> * Accept value: no * Is value required: no * Is multiple: no -* Description: Disable ANSI output * Default: `false` -**no-interaction:** +#### `--no-interaction|-n` + +Do not ask any interactive question -* Name: `--no-interaction` -* Shortcut: `-n` * Accept value: no * Is value required: no * Is multiple: no -* Description: Do not ask any interactive question * Default: `false` -list ----- +`list` +------ + +Lists commands -* Description: Lists commands -* Usage: +### Usage - * `list [--xml] [--raw] [--format FORMAT] [--] [<namespace>]` +* `list [--raw] [--format FORMAT] [--] [<namespace>]` -The <info>list</info> command lists all commands: +The list command lists all commands: - <info>php app/console list</info> + php app/console list You can also display the commands for a specific namespace: - <info>php app/console list test</info> + php app/console list test -You can also output the information in other formats by using the <comment>--format</comment> option: +You can also output the information in other formats by using the --format option: - <info>php app/console list --format=xml</info> + php app/console list --format=xml It's also possible to get raw list of commands (useful for embedding command runner): - <info>php app/console list --raw</info> + php app/console list --raw -### Arguments: +### Arguments -**namespace:** +#### `namespace` + +The namespace name -* Name: namespace * Is required: no * Is array: no -* Description: The namespace name * Default: `NULL` -### Options: - -**xml:** +### Options -* Name: `--xml` -* Shortcut: <none> -* Accept value: no -* Is value required: no -* Is multiple: no -* Description: To output list as XML -* Default: `false` +#### `--raw` -**raw:** +To output raw command list -* Name: `--raw` -* Shortcut: <none> * Accept value: no * Is value required: no * Is multiple: no -* Description: To output raw command list * Default: `false` -**format:** +#### `--format` + +The output format (txt, xml, json, or md) -* Name: `--format` -* Shortcut: <none> * Accept value: yes * Is value required: yes * Is multiple: no -* Description: The output format (txt, xml, json, or md) * Default: `'txt'` -descriptor:command1 -------------------- +`descriptor:command1` +--------------------- + +command 1 description -* Description: command 1 description -* Usage: +### Usage - * `descriptor:command1` - * `alias1` - * `alias2` +* `descriptor:command1` +* `alias1` +* `alias2` command 1 help -### Options: +### Options + +#### `--help|-h` -**help:** +Display this help message -* Name: `--help` -* Shortcut: `-h` * Accept value: no * Is value required: no * Is multiple: no -* Description: Display this help message * Default: `false` -**quiet:** +#### `--quiet|-q` + +Do not output any message -* Name: `--quiet` -* Shortcut: `-q` * Accept value: no * Is value required: no * Is multiple: no -* Description: Do not output any message * Default: `false` -**verbose:** +#### `--verbose|-v|-vv|-vvv` + +Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug -* Name: `--verbose` -* Shortcut: `-v|-vv|-vvv` * Accept value: no * Is value required: no * Is multiple: no -* Description: Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug * Default: `false` -**version:** +#### `--version|-V` + +Display this application version -* Name: `--version` -* Shortcut: `-V` * Accept value: no * Is value required: no * Is multiple: no -* Description: Display this application version * Default: `false` -**ansi:** +#### `--ansi` + +Force ANSI output -* Name: `--ansi` -* Shortcut: <none> * Accept value: no * Is value required: no * Is multiple: no -* Description: Force ANSI output * Default: `false` -**no-ansi:** +#### `--no-ansi` + +Disable ANSI output -* Name: `--no-ansi` -* Shortcut: <none> * Accept value: no * Is value required: no * Is multiple: no -* Description: Disable ANSI output * Default: `false` -**no-interaction:** +#### `--no-interaction|-n` + +Do not ask any interactive question -* Name: `--no-interaction` -* Shortcut: `-n` * Accept value: no * Is value required: no * Is multiple: no -* Description: Do not ask any interactive question * Default: `false` -descriptor:command2 -------------------- +`descriptor:command2` +--------------------- -* Description: command 2 description -* Usage: +command 2 description - * `descriptor:command2 [-o|--option_name] [--] <argument_name>` - * `descriptor:command2 -o|--option_name <argument_name>` - * `descriptor:command2 <argument_name>` +### Usage + +* `descriptor:command2 [-o|--option_name] [--] <argument_name>` +* `descriptor:command2 -o|--option_name <argument_name>` +* `descriptor:command2 <argument_name>` command 2 help -### Arguments: +### Arguments -**argument_name:** +#### `argument_name` -* Name: argument_name * Is required: yes * Is array: no -* Description: <none> * Default: `NULL` -### Options: +### Options + +#### `--option_name|-o` + +* Accept value: no +* Is value required: no +* Is multiple: no +* Default: `false` + +#### `--help|-h` -**option_name:** +Display this help message -* Name: `--option_name` -* Shortcut: `-o` * Accept value: no * Is value required: no * Is multiple: no -* Description: <none> * Default: `false` -**help:** +#### `--quiet|-q` + +Do not output any message -* Name: `--help` -* Shortcut: `-h` * Accept value: no * Is value required: no * Is multiple: no -* Description: Display this help message * Default: `false` -**quiet:** +#### `--verbose|-v|-vv|-vvv` + +Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug -* Name: `--quiet` -* Shortcut: `-q` * Accept value: no * Is value required: no * Is multiple: no -* Description: Do not output any message * Default: `false` -**verbose:** +#### `--version|-V` + +Display this application version -* Name: `--verbose` -* Shortcut: `-v|-vv|-vvv` * Accept value: no * Is value required: no * Is multiple: no -* Description: Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug * Default: `false` -**version:** +#### `--ansi` + +Force ANSI output -* Name: `--version` -* Shortcut: `-V` * Accept value: no * Is value required: no * Is multiple: no -* Description: Display this application version * Default: `false` -**ansi:** +#### `--no-ansi` + +Disable ANSI output -* Name: `--ansi` -* Shortcut: <none> * Accept value: no * Is value required: no * Is multiple: no -* Description: Force ANSI output * Default: `false` -**no-ansi:** +#### `--no-interaction|-n` + +Do not ask any interactive question -* Name: `--no-ansi` -* Shortcut: <none> * Accept value: no * Is value required: no * Is multiple: no -* Description: Disable ANSI output * Default: `false` -**no-interaction:** +`descriptor:command4` +--------------------- + +### Usage + +* `descriptor:command4` +* `descriptor:alias_command4` +* `command4:descriptor` + + +### Options + +#### `--help|-h` + +Display this help message + +* Accept value: no +* Is value required: no +* Is multiple: no +* Default: `false` + +#### `--quiet|-q` + +Do not output any message + +* Accept value: no +* Is value required: no +* Is multiple: no +* Default: `false` + +#### `--verbose|-v|-vv|-vvv` + +Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug + +* Accept value: no +* Is value required: no +* Is multiple: no +* Default: `false` + +#### `--version|-V` + +Display this application version + +* Accept value: no +* Is value required: no +* Is multiple: no +* Default: `false` + +#### `--ansi` + +Force ANSI output + +* Accept value: no +* Is value required: no +* Is multiple: no +* Default: `false` + +#### `--no-ansi` + +Disable ANSI output + +* Accept value: no +* Is value required: no +* Is multiple: no +* Default: `false` + +#### `--no-interaction|-n` + +Do not ask any interactive question -* Name: `--no-interaction` -* Shortcut: `-n` * Accept value: no * Is value required: no * Is multiple: no -* Description: Do not ask any interactive question * Default: `false` diff --git a/vendor/symfony/console/Tests/Fixtures/application_2.txt b/vendor/symfony/console/Tests/Fixtures/application_2.txt index 292aa829..d624f194 100644 --- a/vendor/symfony/console/Tests/Fixtures/application_2.txt +++ b/vendor/symfony/console/Tests/Fixtures/application_2.txt @@ -1,4 +1,4 @@ -<info>My Symfony application</info> version <comment>v1.0</comment> +My Symfony application <info>v1.0</info> <comment>Usage:</comment> command [options] [arguments] @@ -13,10 +13,9 @@ <info>-v|vv|vvv, --verbose</info> Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug <comment>Available commands:</comment> - <info>alias1</info> command 1 description - <info>alias2</info> command 1 description <info>help</info> Displays help for a command <info>list</info> Lists commands <comment>descriptor</comment> - <info>descriptor:command1</info> command 1 description + <info>descriptor:command1</info> [alias1|alias2] command 1 description <info>descriptor:command2</info> command 2 description + <info>descriptor:command4</info> [descriptor:alias_command4|command4:descriptor] diff --git a/vendor/symfony/console/Tests/Fixtures/application_2.xml b/vendor/symfony/console/Tests/Fixtures/application_2.xml index bc8ab219..5f0f98bd 100644 --- a/vendor/symfony/console/Tests/Fixtures/application_2.xml +++ b/vendor/symfony/console/Tests/Fixtures/application_2.xml @@ -1,9 +1,9 @@ <?xml version="1.0" encoding="UTF-8"?> <symfony name="My Symfony application" version="v1.0"> <commands> - <command id="help" name="help"> + <command id="help" name="help" hidden="0"> <usages> - <usage>help [--xml] [--format FORMAT] [--raw] [--] [<command_name>]</usage> + <usage>help [--format FORMAT] [--raw] [--] [<command_name>]</usage> </usages> <description>Displays help for a command</description> <help>The <info>help</info> command displays help for a given command: @@ -24,9 +24,6 @@ </argument> </arguments> <options> - <option name="--xml" shortcut="" accept_value="0" is_value_required="0" is_multiple="0"> - <description>To output help as XML</description> - </option> <option name="--format" shortcut="" accept_value="1" is_value_required="1" is_multiple="0"> <description>The output format (txt, xml, json, or md)</description> <defaults> @@ -59,9 +56,9 @@ </option> </options> </command> - <command id="list" name="list"> + <command id="list" name="list" hidden="0"> <usages> - <usage>list [--xml] [--raw] [--format FORMAT] [--] [<namespace>]</usage> + <usage>list [--raw] [--format FORMAT] [--] [<namespace>]</usage> </usages> <description>Lists commands</description> <help>The <info>list</info> command lists all commands: @@ -86,9 +83,6 @@ </argument> </arguments> <options> - <option name="--xml" shortcut="" accept_value="0" is_value_required="0" is_multiple="0"> - <description>To output list as XML</description> - </option> <option name="--raw" shortcut="" accept_value="0" is_value_required="0" is_multiple="0"> <description>To output raw command list</description> </option> @@ -100,7 +94,7 @@ </option> </options> </command> - <command id="descriptor:command1" name="descriptor:command1"> + <command id="descriptor:command1" name="descriptor:command1" hidden="0"> <usages> <usage>descriptor:command1</usage> <usage>alias1</usage> @@ -133,7 +127,7 @@ </option> </options> </command> - <command id="descriptor:command2" name="descriptor:command2"> + <command id="descriptor:command2" name="descriptor:command2" hidden="0"> <usages> <usage>descriptor:command2 [-o|--option_name] [--] <argument_name></usage> <usage>descriptor:command2 -o|--option_name <argument_name></usage> @@ -174,6 +168,70 @@ </option> </options> </command> + <command id="descriptor:command3" name="descriptor:command3" hidden="1"> + <usages> + <usage>descriptor:command3</usage> + </usages> + <description>command 3 description</description> + <help>command 3 help</help> + <arguments/> + <options> + <option name="--help" shortcut="-h" accept_value="0" is_value_required="0" is_multiple="0"> + <description>Display this help message</description> + </option> + <option name="--quiet" shortcut="-q" accept_value="0" is_value_required="0" is_multiple="0"> + <description>Do not output any message</description> + </option> + <option name="--verbose" shortcut="-v" shortcuts="-v|-vv|-vvv" accept_value="0" is_value_required="0" is_multiple="0"> + <description>Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug</description> + </option> + <option name="--version" shortcut="-V" accept_value="0" is_value_required="0" is_multiple="0"> + <description>Display this application version</description> + </option> + <option name="--ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0"> + <description>Force ANSI output</description> + </option> + <option name="--no-ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0"> + <description>Disable ANSI output</description> + </option> + <option name="--no-interaction" shortcut="-n" accept_value="0" is_value_required="0" is_multiple="0"> + <description>Do not ask any interactive question</description> + </option> + </options> + </command> + <command id="descriptor:command4" name="descriptor:command4" hidden="0"> + <usages> + <usage>descriptor:command4</usage> + <usage>descriptor:alias_command4</usage> + <usage>command4:descriptor</usage> + </usages> + <description></description> + <help></help> + <arguments/> + <options> + <option name="--help" shortcut="-h" accept_value="0" is_value_required="0" is_multiple="0"> + <description>Display this help message</description> + </option> + <option name="--quiet" shortcut="-q" accept_value="0" is_value_required="0" is_multiple="0"> + <description>Do not output any message</description> + </option> + <option name="--verbose" shortcut="-v" shortcuts="-v|-vv|-vvv" accept_value="0" is_value_required="0" is_multiple="0"> + <description>Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug</description> + </option> + <option name="--version" shortcut="-V" accept_value="0" is_value_required="0" is_multiple="0"> + <description>Display this application version</description> + </option> + <option name="--ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0"> + <description>Force ANSI output</description> + </option> + <option name="--no-ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0"> + <description>Disable ANSI output</description> + </option> + <option name="--no-interaction" shortcut="-n" accept_value="0" is_value_required="0" is_multiple="0"> + <description>Do not ask any interactive question</description> + </option> + </options> + </command> </commands> <namespaces> <namespace id="_global"> @@ -182,9 +240,15 @@ <command>help</command> <command>list</command> </namespace> + <namespace id="command4"> + <command>command4:descriptor</command> + </namespace> <namespace id="descriptor"> + <command>descriptor:alias_command4</command> <command>descriptor:command1</command> <command>descriptor:command2</command> + <command>descriptor:command3</command> + <command>descriptor:command4</command> </namespace> </namespaces> </symfony> diff --git a/vendor/symfony/console/Tests/Fixtures/application_asxml1.txt b/vendor/symfony/console/Tests/Fixtures/application_asxml1.txt deleted file mode 100644 index 8277d9e6..00000000 --- a/vendor/symfony/console/Tests/Fixtures/application_asxml1.txt +++ /dev/null @@ -1,146 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<symfony> - <commands> - <command id="help" name="help"> - <usages> - <usage>help [--xml] [--format FORMAT] [--raw] [--] [<command_name>]</usage> - </usages> - <description>Displays help for a command</description> - <help>The <info>help</info> command displays help for a given command: - - <info>php app/console help list</info> - - You can also output the help in other formats by using the <comment>--format</comment> option: - - <info>php app/console help --format=xml list</info> - - To display the list of available commands, please use the <info>list</info> command.</help> - <arguments> - <argument name="command_name" is_required="0" is_array="0"> - <description>The command name</description> - <defaults> - <default>help</default> - </defaults> - </argument> - </arguments> - <options> - <option name="--xml" shortcut="" accept_value="0" is_value_required="0" is_multiple="0"> - <description>To output help as XML</description> - </option> - <option name="--format" shortcut="" accept_value="1" is_value_required="1" is_multiple="0"> - <description>The output format (txt, xml, json, or md)</description> - <defaults> - <default>txt</default> - </defaults> - </option> - <option name="--raw" shortcut="" accept_value="0" is_value_required="0" is_multiple="0"> - <description>To output raw command help</description> - </option> - <option name="--help" shortcut="-h" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Display this help message</description> - </option> - <option name="--quiet" shortcut="-q" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Do not output any message</description> - </option> - <option name="--verbose" shortcut="-v" shortcuts="-v|-vv|-vvv" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug</description> - </option> - <option name="--version" shortcut="-V" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Display this application version</description> - </option> - <option name="--ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Force ANSI output</description> - </option> - <option name="--no-ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Disable ANSI output</description> - </option> - <option name="--no-interaction" shortcut="-n" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Do not ask any interactive question</description> - </option> - </options> - </command> - <command id="list" name="list"> - <usages> - <usage>list [--xml] [--raw] [--format FORMAT] [--] [<namespace>]</usage> - </usages> - <description>Lists commands</description> - <help>The <info>list</info> command lists all commands: - - <info>php app/console list</info> - - You can also display the commands for a specific namespace: - - <info>php app/console list test</info> - - You can also output the information in other formats by using the <comment>--format</comment> option: - - <info>php app/console list --format=xml</info> - - It's also possible to get raw list of commands (useful for embedding command runner): - - <info>php app/console list --raw</info></help> - <arguments> - <argument name="namespace" is_required="0" is_array="0"> - <description>The namespace name</description> - <defaults/> - </argument> - </arguments> - <options> - <option name="--xml" shortcut="" accept_value="0" is_value_required="0" is_multiple="0"> - <description>To output list as XML</description> - </option> - <option name="--raw" shortcut="" accept_value="0" is_value_required="0" is_multiple="0"> - <description>To output raw command list</description> - </option> - <option name="--format" shortcut="" accept_value="1" is_value_required="1" is_multiple="0"> - <description>The output format (txt, xml, json, or md)</description> - <defaults> - <default>txt</default> - </defaults> - </option> - </options> - </command> - <command id="foo:bar" name="foo:bar"> - <usages> - <usage>foo:bar</usage> - <usage>afoobar</usage> - </usages> - <description>The foo:bar command</description> - <help>The foo:bar command</help> - <arguments/> - <options> - <option name="--help" shortcut="-h" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Display this help message</description> - </option> - <option name="--quiet" shortcut="-q" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Do not output any message</description> - </option> - <option name="--verbose" shortcut="-v" shortcuts="-v|-vv|-vvv" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug</description> - </option> - <option name="--version" shortcut="-V" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Display this application version</description> - </option> - <option name="--ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Force ANSI output</description> - </option> - <option name="--no-ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Disable ANSI output</description> - </option> - <option name="--no-interaction" shortcut="-n" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Do not ask any interactive question</description> - </option> - </options> - </command> - </commands> - <namespaces> - <namespace id="_global"> - <command>afoobar</command> - <command>help</command> - <command>list</command> - </namespace> - <namespace id="foo"> - <command>foo:bar</command> - </namespace> - </namespaces> -</symfony> diff --git a/vendor/symfony/console/Tests/Fixtures/application_asxml2.txt b/vendor/symfony/console/Tests/Fixtures/application_asxml2.txt deleted file mode 100644 index 93d6d4e9..00000000 --- a/vendor/symfony/console/Tests/Fixtures/application_asxml2.txt +++ /dev/null @@ -1,37 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<symfony> - <commands namespace="foo"> - <command id="foo:bar" name="foo:bar"> - <usages> - <usage>foo:bar</usage> - <usage>afoobar</usage> - </usages> - <description>The foo:bar command</description> - <help>The foo:bar command</help> - <arguments/> - <options> - <option name="--help" shortcut="-h" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Display this help message</description> - </option> - <option name="--quiet" shortcut="-q" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Do not output any message</description> - </option> - <option name="--verbose" shortcut="-v" shortcuts="-v|-vv|-vvv" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug</description> - </option> - <option name="--version" shortcut="-V" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Display this application version</description> - </option> - <option name="--ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Force ANSI output</description> - </option> - <option name="--no-ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Disable ANSI output</description> - </option> - <option name="--no-interaction" shortcut="-n" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Do not ask any interactive question</description> - </option> - </options> - </command> - </commands> -</symfony> diff --git a/vendor/symfony/console/Tests/Fixtures/application_astext2.txt b/vendor/symfony/console/Tests/Fixtures/application_filtered_namespace.txt index c99ccdda..3bca2700 100644 --- a/vendor/symfony/console/Tests/Fixtures/application_astext2.txt +++ b/vendor/symfony/console/Tests/Fixtures/application_filtered_namespace.txt @@ -1,4 +1,4 @@ -<info>Console Tool</info> +My Symfony application <info>v1.0</info> <comment>Usage:</comment> command [options] [arguments] @@ -12,5 +12,5 @@ <info>-n, --no-interaction</info> Do not ask any interactive question <info>-v|vv|vvv, --verbose</info> Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug -<comment>Available commands for the "foo" namespace:</comment> - <info>foo:bar</info> The foo:bar command +<comment>Available commands for the "command4" namespace:</comment> + <info>command4:descriptor</info> diff --git a/vendor/symfony/console/Tests/Fixtures/application_gethelp.txt b/vendor/symfony/console/Tests/Fixtures/application_gethelp.txt index 0c16e3c8..5a5920d0 100644 --- a/vendor/symfony/console/Tests/Fixtures/application_gethelp.txt +++ b/vendor/symfony/console/Tests/Fixtures/application_gethelp.txt @@ -1 +1 @@ -<info>Console Tool</info>
\ No newline at end of file +Console Tool
\ No newline at end of file diff --git a/vendor/symfony/console/Tests/Fixtures/application_mbstring.md b/vendor/symfony/console/Tests/Fixtures/application_mbstring.md new file mode 100644 index 00000000..f34e5585 --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/application_mbstring.md @@ -0,0 +1,269 @@ +MbString åpplicätion +==================== + +* [`help`](#help) +* [`list`](#list) + +**descriptor:** + +* [`descriptor:åèä`](#descriptoråèä) + +`help` +------ + +Displays help for a command + +### Usage + +* `help [--format FORMAT] [--raw] [--] [<command_name>]` + +The help command displays help for a given command: + + php app/console help list + +You can also output the help in other formats by using the --format option: + + php app/console help --format=xml list + +To display the list of available commands, please use the list command. + +### Arguments + +#### `command_name` + +The command name + +* Is required: no +* Is array: no +* Default: `'help'` + +### Options + +#### `--format` + +The output format (txt, xml, json, or md) + +* Accept value: yes +* Is value required: yes +* Is multiple: no +* Default: `'txt'` + +#### `--raw` + +To output raw command help + +* Accept value: no +* Is value required: no +* Is multiple: no +* Default: `false` + +#### `--help|-h` + +Display this help message + +* Accept value: no +* Is value required: no +* Is multiple: no +* Default: `false` + +#### `--quiet|-q` + +Do not output any message + +* Accept value: no +* Is value required: no +* Is multiple: no +* Default: `false` + +#### `--verbose|-v|-vv|-vvv` + +Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug + +* Accept value: no +* Is value required: no +* Is multiple: no +* Default: `false` + +#### `--version|-V` + +Display this application version + +* Accept value: no +* Is value required: no +* Is multiple: no +* Default: `false` + +#### `--ansi` + +Force ANSI output + +* Accept value: no +* Is value required: no +* Is multiple: no +* Default: `false` + +#### `--no-ansi` + +Disable ANSI output + +* Accept value: no +* Is value required: no +* Is multiple: no +* Default: `false` + +#### `--no-interaction|-n` + +Do not ask any interactive question + +* Accept value: no +* Is value required: no +* Is multiple: no +* Default: `false` + +`list` +------ + +Lists commands + +### Usage + +* `list [--raw] [--format FORMAT] [--] [<namespace>]` + +The list command lists all commands: + + php app/console list + +You can also display the commands for a specific namespace: + + php app/console list test + +You can also output the information in other formats by using the --format option: + + php app/console list --format=xml + +It's also possible to get raw list of commands (useful for embedding command runner): + + php app/console list --raw + +### Arguments + +#### `namespace` + +The namespace name + +* Is required: no +* Is array: no +* Default: `NULL` + +### Options + +#### `--raw` + +To output raw command list + +* Accept value: no +* Is value required: no +* Is multiple: no +* Default: `false` + +#### `--format` + +The output format (txt, xml, json, or md) + +* Accept value: yes +* Is value required: yes +* Is multiple: no +* Default: `'txt'` + +`descriptor:åèä` +---------------- + +command åèä description + +### Usage + +* `descriptor:åèä [-o|--option_åèä] [--] <argument_åèä>` +* `descriptor:åèä -o|--option_name <argument_name>` +* `descriptor:åèä <argument_name>` + +command åèä help + +### Arguments + +#### `argument_åèä` + +* Is required: yes +* Is array: no +* Default: `NULL` + +### Options + +#### `--option_åèä|-o` + +* Accept value: no +* Is value required: no +* Is multiple: no +* Default: `false` + +#### `--help|-h` + +Display this help message + +* Accept value: no +* Is value required: no +* Is multiple: no +* Default: `false` + +#### `--quiet|-q` + +Do not output any message + +* Accept value: no +* Is value required: no +* Is multiple: no +* Default: `false` + +#### `--verbose|-v|-vv|-vvv` + +Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug + +* Accept value: no +* Is value required: no +* Is multiple: no +* Default: `false` + +#### `--version|-V` + +Display this application version + +* Accept value: no +* Is value required: no +* Is multiple: no +* Default: `false` + +#### `--ansi` + +Force ANSI output + +* Accept value: no +* Is value required: no +* Is multiple: no +* Default: `false` + +#### `--no-ansi` + +Disable ANSI output + +* Accept value: no +* Is value required: no +* Is multiple: no +* Default: `false` + +#### `--no-interaction|-n` + +Do not ask any interactive question + +* Accept value: no +* Is value required: no +* Is multiple: no +* Default: `false` diff --git a/vendor/symfony/console/Tests/Fixtures/application_astext1.txt b/vendor/symfony/console/Tests/Fixtures/application_mbstring.txt index 19dacb23..b409d188 100644 --- a/vendor/symfony/console/Tests/Fixtures/application_astext1.txt +++ b/vendor/symfony/console/Tests/Fixtures/application_mbstring.txt @@ -1,4 +1,4 @@ -<info>Console Tool</info> +MbString åpplicätion <comment>Usage:</comment> command [options] [arguments] @@ -13,8 +13,7 @@ <info>-v|vv|vvv, --verbose</info> Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug <comment>Available commands:</comment> - <info>afoobar</info> The foo:bar command - <info>help</info> Displays help for a command - <info>list</info> Lists commands - <comment>foo</comment> - <info>foo:bar</info> The foo:bar command + <info>help</info> Displays help for a command + <info>list</info> Lists commands + <comment>descriptor</comment> + <info>descriptor:åèä</info> command åèä description diff --git a/vendor/symfony/console/Tests/Fixtures/application_renderexception1.txt b/vendor/symfony/console/Tests/Fixtures/application_renderexception1.txt index 919cec42..1df5bd64 100644 --- a/vendor/symfony/console/Tests/Fixtures/application_renderexception1.txt +++ b/vendor/symfony/console/Tests/Fixtures/application_renderexception1.txt @@ -1,6 +1,5 @@ - - [Symfony\Component\Console\Exception\CommandNotFoundException] - Command "foo" is not defined. - + + Command "foo" is not defined. + diff --git a/vendor/symfony/console/Tests/Fixtures/application_renderexception2.txt b/vendor/symfony/console/Tests/Fixtures/application_renderexception2.txt index d9e93da4..932063d7 100644 --- a/vendor/symfony/console/Tests/Fixtures/application_renderexception2.txt +++ b/vendor/symfony/console/Tests/Fixtures/application_renderexception2.txt @@ -1,8 +1,7 @@ - - [Symfony\Component\Console\Exception\InvalidOptionException] - The "--foo" option does not exist. - + + The "--foo" option does not exist. + -list [--xml] [--raw] [--format FORMAT] [--] [<namespace>] +list [--raw] [--format FORMAT] [--] [<namespace>] diff --git a/vendor/symfony/console/Tests/Fixtures/application_renderexception3.txt b/vendor/symfony/console/Tests/Fixtures/application_renderexception3.txt index 8276137b..5366b84f 100644 --- a/vendor/symfony/console/Tests/Fixtures/application_renderexception3.txt +++ b/vendor/symfony/console/Tests/Fixtures/application_renderexception3.txt @@ -1,16 +1,16 @@ - - [Exception] - Third exception comment - +In Foo3Command.php line 26: + + Third exception <fg=blue;bg=red>comment</> + - - [Exception] - Second exception comment - +In Foo3Command.php line 23: + + Second exception <comment>comment</comment> + +In Foo3Command.php line 21: - [Exception] First exception <p>this is html</p> diff --git a/vendor/symfony/console/Tests/Fixtures/application_renderexception3decorated.txt b/vendor/symfony/console/Tests/Fixtures/application_renderexception3decorated.txt index b4a7b018..59937092 100644 --- a/vendor/symfony/console/Tests/Fixtures/application_renderexception3decorated.txt +++ b/vendor/symfony/console/Tests/Fixtures/application_renderexception3decorated.txt @@ -1,17 +1,17 @@ -[37;41m [39;49m -[37;41m [Exception] [39;49m -[37;41m Third exception [39;49m[34;41mcomment[39;49m[37;41m [39;49m -[37;41m [39;49m +[33mIn Foo3Command.php line 26:[39m +[37;41m [39;49m +[37;41m Third exception <fg=blue;bg=red>comment</> [39;49m +[37;41m [39;49m -[37;41m [39;49m -[37;41m [Exception] [39;49m -[37;41m Second exception [39;49m[33mcomment[39m[37;41m [39;49m -[37;41m [39;49m +[33mIn Foo3Command.php line 23:[39m +[37;41m [39;49m +[37;41m Second exception <comment>comment</comment> [39;49m +[37;41m [39;49m +[33mIn Foo3Command.php line 21:[39m [37;41m [39;49m -[37;41m [Exception] [39;49m -[37;41m First exception [39;49m[37;41m<p>[39;49m[37;41mthis is html[39;49m[37;41m</p>[39;49m[37;41m [39;49m +[37;41m First exception <p>this is html</p> [39;49m [37;41m [39;49m [32mfoo3:bar[39m diff --git a/vendor/symfony/console/Tests/Fixtures/application_renderexception4.txt b/vendor/symfony/console/Tests/Fixtures/application_renderexception4.txt index cb080e9c..548a13e5 100644 --- a/vendor/symfony/console/Tests/Fixtures/application_renderexception4.txt +++ b/vendor/symfony/console/Tests/Fixtures/application_renderexception4.txt @@ -1,7 +1,6 @@ - - [Symfony\Component\Console\Exception\CommandNotFoundException] - Command "foo" is not define - d. - + + Command "foo" is not define + d. + diff --git a/vendor/symfony/console/Tests/Fixtures/application_renderexception_doublewidth1.txt b/vendor/symfony/console/Tests/Fixtures/application_renderexception_doublewidth1.txt index 1ba5f8fd..01986c91 100644 --- a/vendor/symfony/console/Tests/Fixtures/application_renderexception_doublewidth1.txt +++ b/vendor/symfony/console/Tests/Fixtures/application_renderexception_doublewidth1.txt @@ -1,6 +1,6 @@ +In ApplicationTest.php line 716: - [Exception] エラーメッセージ diff --git a/vendor/symfony/console/Tests/Fixtures/application_renderexception_doublewidth1decorated.txt b/vendor/symfony/console/Tests/Fixtures/application_renderexception_doublewidth1decorated.txt index 20644251..ba057d8c 100644 --- a/vendor/symfony/console/Tests/Fixtures/application_renderexception_doublewidth1decorated.txt +++ b/vendor/symfony/console/Tests/Fixtures/application_renderexception_doublewidth1decorated.txt @@ -1,6 +1,6 @@ +[33mIn ApplicationTest.php line 716:[39m [37;41m [39;49m -[37;41m [Exception] [39;49m [37;41m エラーメッセージ [39;49m [37;41m [39;49m diff --git a/vendor/symfony/console/Tests/Fixtures/application_renderexception_doublewidth2.txt b/vendor/symfony/console/Tests/Fixtures/application_renderexception_doublewidth2.txt index e41fcfcf..66b52c87 100644 --- a/vendor/symfony/console/Tests/Fixtures/application_renderexception_doublewidth2.txt +++ b/vendor/symfony/console/Tests/Fixtures/application_renderexception_doublewidth2.txt @@ -1,6 +1,6 @@ +In ApplicationTest.php line 730: - [Exception] コマンドの実行中にエラーが 発生しました。 diff --git a/vendor/symfony/console/Tests/Fixtures/application_renderexception_escapeslines.txt b/vendor/symfony/console/Tests/Fixtures/application_renderexception_escapeslines.txt new file mode 100644 index 00000000..326ee42f --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/application_renderexception_escapeslines.txt @@ -0,0 +1,9 @@ + +In ApplicationTest.php line 744: + + dont break here < + info>!</info> + + +foo + diff --git a/vendor/symfony/console/Tests/Fixtures/application_renderexception_linebreaks.txt b/vendor/symfony/console/Tests/Fixtures/application_renderexception_linebreaks.txt new file mode 100644 index 00000000..88ee0f29 --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/application_renderexception_linebreaks.txt @@ -0,0 +1,11 @@ + +In ApplicationTest.php line 761: + + line 1 with extra spaces + line 2 + + line 4 + + +foo + diff --git a/vendor/symfony/console/Tests/Fixtures/application_run2.txt b/vendor/symfony/console/Tests/Fixtures/application_run2.txt index d28b928e..65a685d0 100644 --- a/vendor/symfony/console/Tests/Fixtures/application_run2.txt +++ b/vendor/symfony/console/Tests/Fixtures/application_run2.txt @@ -1,29 +1,26 @@ Usage: - help [options] [--] [<command_name>] + list [options] [--] [<namespace>] Arguments: - command The command to execute - command_name The command name [default: "help"] + namespace The namespace name Options: - --xml To output help as XML - --format=FORMAT The output format (txt, xml, json, or md) [default: "txt"] - --raw To output raw command help - -h, --help Display this help message - -q, --quiet Do not output any message - -V, --version Display this application version - --ansi Force ANSI output - --no-ansi Disable ANSI output - -n, --no-interaction Do not ask any interactive question - -v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug + --raw To output raw command list + --format=FORMAT The output format (txt, xml, json, or md) [default: "txt"] Help: - The help command displays help for a given command: - - php app/console help list - - You can also output the help in other formats by using the --format option: - - php app/console help --format=xml list - - To display the list of available commands, please use the list command. + The list command lists all commands: + + php app/console list + + You can also display the commands for a specific namespace: + + php app/console list test + + You can also output the information in other formats by using the --format option: + + php app/console list --format=xml + + It's also possible to get raw list of commands (useful for embedding command runner): + + php app/console list --raw diff --git a/vendor/symfony/console/Tests/Fixtures/application_run3.txt b/vendor/symfony/console/Tests/Fixtures/application_run3.txt index bc51995f..65a685d0 100644 --- a/vendor/symfony/console/Tests/Fixtures/application_run3.txt +++ b/vendor/symfony/console/Tests/Fixtures/application_run3.txt @@ -5,23 +5,22 @@ Arguments: namespace The namespace name Options: - --xml To output list as XML --raw To output raw command list --format=FORMAT The output format (txt, xml, json, or md) [default: "txt"] Help: - The list command lists all commands: - - php app/console list - - You can also display the commands for a specific namespace: - - php app/console list test - - You can also output the information in other formats by using the --format option: - - php app/console list --format=xml - - It's also possible to get raw list of commands (useful for embedding command runner): - - php app/console list --raw + The list command lists all commands: + + php app/console list + + You can also display the commands for a specific namespace: + + php app/console list test + + You can also output the information in other formats by using the --format option: + + php app/console list --format=xml + + It's also possible to get raw list of commands (useful for embedding command runner): + + php app/console list --raw diff --git a/vendor/symfony/console/Tests/Fixtures/command_1.json b/vendor/symfony/console/Tests/Fixtures/command_1.json index 20f310b4..09087900 100644 --- a/vendor/symfony/console/Tests/Fixtures/command_1.json +++ b/vendor/symfony/console/Tests/Fixtures/command_1.json @@ -1 +1,15 @@ -{"name":"descriptor:command1","usage":["descriptor:command1", "alias1", "alias2"],"description":"command 1 description","help":"command 1 help","definition":{"arguments":[],"options":[]}} +{ + "name": "descriptor:command1", + "hidden": false, + "usage": [ + "descriptor:command1", + "alias1", + "alias2" + ], + "description": "command 1 description", + "help": "command 1 help", + "definition": { + "arguments": [], + "options": [] + } +} diff --git a/vendor/symfony/console/Tests/Fixtures/command_1.md b/vendor/symfony/console/Tests/Fixtures/command_1.md index 34ed3ea7..e9a0180b 100644 --- a/vendor/symfony/console/Tests/Fixtures/command_1.md +++ b/vendor/symfony/console/Tests/Fixtures/command_1.md @@ -1,11 +1,12 @@ -descriptor:command1 -------------------- +`descriptor:command1` +--------------------- -* Description: command 1 description -* Usage: +command 1 description - * `descriptor:command1` - * `alias1` - * `alias2` +### Usage + +* `descriptor:command1` +* `alias1` +* `alias2` command 1 help diff --git a/vendor/symfony/console/Tests/Fixtures/command_1.txt b/vendor/symfony/console/Tests/Fixtures/command_1.txt index 28e14a05..e5e93ee0 100644 --- a/vendor/symfony/console/Tests/Fixtures/command_1.txt +++ b/vendor/symfony/console/Tests/Fixtures/command_1.txt @@ -4,4 +4,4 @@ alias2 <comment>Help:</comment> - command 1 help + command 1 help diff --git a/vendor/symfony/console/Tests/Fixtures/command_1.xml b/vendor/symfony/console/Tests/Fixtures/command_1.xml index 838b9bd9..fa0cca08 100644 --- a/vendor/symfony/console/Tests/Fixtures/command_1.xml +++ b/vendor/symfony/console/Tests/Fixtures/command_1.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<command id="descriptor:command1" name="descriptor:command1"> +<command id="descriptor:command1" name="descriptor:command1" hidden="0"> <usages> <usage>descriptor:command1</usage> <usage>alias1</usage> diff --git a/vendor/symfony/console/Tests/Fixtures/command_2.json b/vendor/symfony/console/Tests/Fixtures/command_2.json index 38edd1e2..8a1ec023 100644 --- a/vendor/symfony/console/Tests/Fixtures/command_2.json +++ b/vendor/symfony/console/Tests/Fixtures/command_2.json @@ -1 +1,33 @@ -{"name":"descriptor:command2","usage":["descriptor:command2 [-o|--option_name] [--] <argument_name>", "descriptor:command2 -o|--option_name <argument_name>", "descriptor:command2 <argument_name>"],"description":"command 2 description","help":"command 2 help","definition":{"arguments":{"argument_name":{"name":"argument_name","is_required":true,"is_array":false,"description":"","default":null}},"options":{"option_name":{"name":"--option_name","shortcut":"-o","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"","default":false}}}} +{ + "name": "descriptor:command2", + "hidden": false, + "usage": [ + "descriptor:command2 [-o|--option_name] [--] <argument_name>", + "descriptor:command2 -o|--option_name <argument_name>", + "descriptor:command2 <argument_name>" + ], + "description": "command 2 description", + "help": "command 2 help", + "definition": { + "arguments": { + "argument_name": { + "name": "argument_name", + "is_required": true, + "is_array": false, + "description": "", + "default": null + } + }, + "options": { + "option_name": { + "name": "--option_name", + "shortcut": "-o", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "", + "default": false + } + } + } +} diff --git a/vendor/symfony/console/Tests/Fixtures/command_2.md b/vendor/symfony/console/Tests/Fixtures/command_2.md index 6f538b64..41f51f01 100644 --- a/vendor/symfony/console/Tests/Fixtures/command_2.md +++ b/vendor/symfony/console/Tests/Fixtures/command_2.md @@ -1,33 +1,29 @@ -descriptor:command2 -------------------- +`descriptor:command2` +--------------------- -* Description: command 2 description -* Usage: +command 2 description - * `descriptor:command2 [-o|--option_name] [--] <argument_name>` - * `descriptor:command2 -o|--option_name <argument_name>` - * `descriptor:command2 <argument_name>` +### Usage + +* `descriptor:command2 [-o|--option_name] [--] <argument_name>` +* `descriptor:command2 -o|--option_name <argument_name>` +* `descriptor:command2 <argument_name>` command 2 help -### Arguments: +### Arguments -**argument_name:** +#### `argument_name` -* Name: argument_name * Is required: yes * Is array: no -* Description: <none> * Default: `NULL` -### Options: +### Options -**option_name:** +#### `--option_name|-o` -* Name: `--option_name` -* Shortcut: `-o` * Accept value: no * Is value required: no * Is multiple: no -* Description: <none> * Default: `false` diff --git a/vendor/symfony/console/Tests/Fixtures/command_2.txt b/vendor/symfony/console/Tests/Fixtures/command_2.txt index 72f7ce05..2864c7bd 100644 --- a/vendor/symfony/console/Tests/Fixtures/command_2.txt +++ b/vendor/symfony/console/Tests/Fixtures/command_2.txt @@ -1,7 +1,7 @@ <comment>Usage:</comment> - descriptor:command2 [options] [--] <argument_name> - descriptor:command2 -o|--option_name <argument_name> - descriptor:command2 <argument_name> + descriptor:command2 [options] [--] \<argument_name> + descriptor:command2 -o|--option_name \<argument_name> + descriptor:command2 \<argument_name> <comment>Arguments:</comment> <info>argument_name</info> @@ -10,4 +10,4 @@ <info>-o, --option_name</info> <comment>Help:</comment> - command 2 help + command 2 help diff --git a/vendor/symfony/console/Tests/Fixtures/command_2.xml b/vendor/symfony/console/Tests/Fixtures/command_2.xml index 67364caa..ae69e2f4 100644 --- a/vendor/symfony/console/Tests/Fixtures/command_2.xml +++ b/vendor/symfony/console/Tests/Fixtures/command_2.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<command id="descriptor:command2" name="descriptor:command2"> +<command id="descriptor:command2" name="descriptor:command2" hidden="0"> <usages> <usage>descriptor:command2 [-o|--option_name] [--] <argument_name></usage> <usage>descriptor:command2 -o|--option_name <argument_name></usage> diff --git a/vendor/symfony/console/Tests/Fixtures/command_astext.txt b/vendor/symfony/console/Tests/Fixtures/command_astext.txt deleted file mode 100644 index 7e206388..00000000 --- a/vendor/symfony/console/Tests/Fixtures/command_astext.txt +++ /dev/null @@ -1,18 +0,0 @@ -<comment>Usage:</comment> - namespace:name - name - -<comment>Arguments:</comment> - <info>command</info> The command to execute - -<comment>Options:</comment> - <info>-h, --help</info> Display this help message - <info>-q, --quiet</info> Do not output any message - <info>-V, --version</info> Display this application version - <info> --ansi</info> Force ANSI output - <info> --no-ansi</info> Disable ANSI output - <info>-n, --no-interaction</info> Do not ask any interactive question - <info>-v|vv|vvv, --verbose</info> Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug - -<comment>Help:</comment> - help diff --git a/vendor/symfony/console/Tests/Fixtures/command_asxml.txt b/vendor/symfony/console/Tests/Fixtures/command_asxml.txt deleted file mode 100644 index 5e776238..00000000 --- a/vendor/symfony/console/Tests/Fixtures/command_asxml.txt +++ /dev/null @@ -1,38 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<command id="namespace:name" name="namespace:name"> - <usages> - <usage>namespace:name</usage> - <usage>name</usage> - </usages> - <description>description</description> - <help>help</help> - <arguments> - <argument name="command" is_required="1" is_array="0"> - <description>The command to execute</description> - <defaults/> - </argument> - </arguments> - <options> - <option name="--help" shortcut="-h" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Display this help message</description> - </option> - <option name="--quiet" shortcut="-q" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Do not output any message</description> - </option> - <option name="--verbose" shortcut="-v" shortcuts="-v|-vv|-vvv" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug</description> - </option> - <option name="--version" shortcut="-V" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Display this application version</description> - </option> - <option name="--ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Force ANSI output</description> - </option> - <option name="--no-ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Disable ANSI output</description> - </option> - <option name="--no-interaction" shortcut="-n" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Do not ask any interactive question</description> - </option> - </options> -</command> diff --git a/vendor/symfony/console/Tests/Fixtures/command_mbstring.md b/vendor/symfony/console/Tests/Fixtures/command_mbstring.md new file mode 100644 index 00000000..7ef40d7b --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/command_mbstring.md @@ -0,0 +1,29 @@ +`descriptor:åèä` +---------------- + +command åèä description + +### Usage + +* `descriptor:åèä [-o|--option_åèä] [--] <argument_åèä>` +* `descriptor:åèä -o|--option_name <argument_name>` +* `descriptor:åèä <argument_name>` + +command åèä help + +### Arguments + +#### `argument_åèä` + +* Is required: yes +* Is array: no +* Default: `NULL` + +### Options + +#### `--option_åèä|-o` + +* Accept value: no +* Is value required: no +* Is multiple: no +* Default: `false` diff --git a/vendor/symfony/console/Tests/Fixtures/command_mbstring.txt b/vendor/symfony/console/Tests/Fixtures/command_mbstring.txt new file mode 100644 index 00000000..cde457dc --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/command_mbstring.txt @@ -0,0 +1,13 @@ +<comment>Usage:</comment> + descriptor:åèä [options] [--] \<argument_åèä> + descriptor:åèä -o|--option_name \<argument_name> + descriptor:åèä \<argument_name> + +<comment>Arguments:</comment> + <info>argument_åèä</info> + +<comment>Options:</comment> + <info>-o, --option_åèä</info> + +<comment>Help:</comment> + command åèä help diff --git a/vendor/symfony/console/Tests/Fixtures/definition_astext.txt b/vendor/symfony/console/Tests/Fixtures/definition_astext.txt deleted file mode 100644 index 0431c072..00000000 --- a/vendor/symfony/console/Tests/Fixtures/definition_astext.txt +++ /dev/null @@ -1,11 +0,0 @@ -<comment>Arguments:</comment> - <info>foo</info> The foo argument - <info>baz</info> The baz argument<comment> [default: true]</comment> - <info>bar</info> The bar argument<comment> [default: ["http://foo.com/"]]</comment> - -<comment>Options:</comment> - <info>-f, --foo=FOO</info> The foo option - <info> --baz[=BAZ]</info> The baz option<comment> [default: false]</comment> - <info>-b, --bar[=BAR]</info> The bar option<comment> [default: "bar"]</comment> - <info> --qux[=QUX]</info> The qux option<comment> [default: ["http://foo.com/","bar"]]</comment><comment> (multiple values allowed)</comment> - <info> --qux2[=QUX2]</info> The qux2 option<comment> [default: {"foo":"bar"}]</comment><comment> (multiple values allowed)</comment>
\ No newline at end of file diff --git a/vendor/symfony/console/Tests/Fixtures/definition_asxml.txt b/vendor/symfony/console/Tests/Fixtures/definition_asxml.txt deleted file mode 100644 index eec8c079..00000000 --- a/vendor/symfony/console/Tests/Fixtures/definition_asxml.txt +++ /dev/null @@ -1,39 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<definition> - <arguments> - <argument name="foo" is_required="0" is_array="0"> - <description>The foo argument</description> - <defaults/> - </argument> - <argument name="baz" is_required="0" is_array="0"> - <description>The baz argument</description> - <defaults> - <default>true</default> - </defaults> - </argument> - <argument name="bar" is_required="0" is_array="1"> - <description>The bar argument</description> - <defaults> - <default>bar</default> - </defaults> - </argument> - </arguments> - <options> - <option name="--foo" shortcut="-f" accept_value="1" is_value_required="1" is_multiple="0"> - <description>The foo option</description> - <defaults/> - </option> - <option name="--baz" shortcut="" accept_value="1" is_value_required="0" is_multiple="0"> - <description>The baz option</description> - <defaults> - <default>false</default> - </defaults> - </option> - <option name="--bar" shortcut="-b" accept_value="1" is_value_required="0" is_multiple="0"> - <description>The bar option</description> - <defaults> - <default>bar</default> - </defaults> - </option> - </options> -</definition> diff --git a/vendor/symfony/console/Tests/Fixtures/input_argument_1.json b/vendor/symfony/console/Tests/Fixtures/input_argument_1.json index b8173b6b..0ab93296 100644 --- a/vendor/symfony/console/Tests/Fixtures/input_argument_1.json +++ b/vendor/symfony/console/Tests/Fixtures/input_argument_1.json @@ -1 +1,7 @@ -{"name":"argument_name","is_required":true,"is_array":false,"description":"","default":null} +{ + "name": "argument_name", + "is_required": true, + "is_array": false, + "description": "", + "default": null +} diff --git a/vendor/symfony/console/Tests/Fixtures/input_argument_1.md b/vendor/symfony/console/Tests/Fixtures/input_argument_1.md index 88f311ab..7516cbd4 100644 --- a/vendor/symfony/console/Tests/Fixtures/input_argument_1.md +++ b/vendor/symfony/console/Tests/Fixtures/input_argument_1.md @@ -1,7 +1,5 @@ -**argument_name:** +#### `argument_name` -* Name: argument_name * Is required: yes * Is array: no -* Description: <none> * Default: `NULL` diff --git a/vendor/symfony/console/Tests/Fixtures/input_argument_2.json b/vendor/symfony/console/Tests/Fixtures/input_argument_2.json index ef06b09a..7450016f 100644 --- a/vendor/symfony/console/Tests/Fixtures/input_argument_2.json +++ b/vendor/symfony/console/Tests/Fixtures/input_argument_2.json @@ -1 +1,7 @@ -{"name":"argument_name","is_required":false,"is_array":true,"description":"argument description","default":[]} +{ + "name": "argument_name", + "is_required": false, + "is_array": true, + "description": "argument description", + "default": [] +} diff --git a/vendor/symfony/console/Tests/Fixtures/input_argument_2.md b/vendor/symfony/console/Tests/Fixtures/input_argument_2.md index 3cdb00cc..2e7e7580 100644 --- a/vendor/symfony/console/Tests/Fixtures/input_argument_2.md +++ b/vendor/symfony/console/Tests/Fixtures/input_argument_2.md @@ -1,7 +1,7 @@ -**argument_name:** +#### `argument_name` + +argument description -* Name: argument_name * Is required: no * Is array: yes -* Description: argument description * Default: `array ()` diff --git a/vendor/symfony/console/Tests/Fixtures/input_argument_3.json b/vendor/symfony/console/Tests/Fixtures/input_argument_3.json index de8484e6..9a83c5a5 100644 --- a/vendor/symfony/console/Tests/Fixtures/input_argument_3.json +++ b/vendor/symfony/console/Tests/Fixtures/input_argument_3.json @@ -1 +1,7 @@ -{"name":"argument_name","is_required":false,"is_array":false,"description":"argument description","default":"default_value"} +{ + "name": "argument_name", + "is_required": false, + "is_array": false, + "description": "argument description", + "default": "default_value" +} diff --git a/vendor/symfony/console/Tests/Fixtures/input_argument_3.md b/vendor/symfony/console/Tests/Fixtures/input_argument_3.md index be1c443a..b0dd8785 100644 --- a/vendor/symfony/console/Tests/Fixtures/input_argument_3.md +++ b/vendor/symfony/console/Tests/Fixtures/input_argument_3.md @@ -1,7 +1,7 @@ -**argument_name:** +#### `argument_name` + +argument description -* Name: argument_name * Is required: no * Is array: no -* Description: argument description * Default: `'default_value'` diff --git a/vendor/symfony/console/Tests/Fixtures/input_argument_4.json b/vendor/symfony/console/Tests/Fixtures/input_argument_4.json index 8067a4d1..cbcb19b3 100644 --- a/vendor/symfony/console/Tests/Fixtures/input_argument_4.json +++ b/vendor/symfony/console/Tests/Fixtures/input_argument_4.json @@ -1 +1,7 @@ -{"name":"argument_name","is_required":true,"is_array":false,"description":"multiline argument description","default":null} +{ + "name": "argument_name", + "is_required": true, + "is_array": false, + "description": "multiline argument description", + "default": null +} diff --git a/vendor/symfony/console/Tests/Fixtures/input_argument_4.md b/vendor/symfony/console/Tests/Fixtures/input_argument_4.md index f026ab37..b9bb7edc 100644 --- a/vendor/symfony/console/Tests/Fixtures/input_argument_4.md +++ b/vendor/symfony/console/Tests/Fixtures/input_argument_4.md @@ -1,8 +1,8 @@ -**argument_name:** +#### `argument_name` + +multiline +argument description -* Name: argument_name * Is required: yes * Is array: no -* Description: multiline - argument description * Default: `NULL` diff --git a/vendor/symfony/console/Tests/Fixtures/input_argument_4.txt b/vendor/symfony/console/Tests/Fixtures/input_argument_4.txt index aa74e8ce..fc7d669a 100644 --- a/vendor/symfony/console/Tests/Fixtures/input_argument_4.txt +++ b/vendor/symfony/console/Tests/Fixtures/input_argument_4.txt @@ -1,2 +1,2 @@ <info>argument_name</info> multiline - argument description + argument description diff --git a/vendor/symfony/console/Tests/Fixtures/input_argument_with_default_inf_value.json b/vendor/symfony/console/Tests/Fixtures/input_argument_with_default_inf_value.json new file mode 100644 index 00000000..b61ecf7b --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/input_argument_with_default_inf_value.json @@ -0,0 +1,7 @@ +{ + "name": "argument_name", + "is_required": false, + "is_array": false, + "description": "argument description", + "default": "INF" +} diff --git a/vendor/symfony/console/Tests/Fixtures/input_argument_with_default_inf_value.md b/vendor/symfony/console/Tests/Fixtures/input_argument_with_default_inf_value.md new file mode 100644 index 00000000..4f4d9b16 --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/input_argument_with_default_inf_value.md @@ -0,0 +1,7 @@ +#### `argument_name` + +argument description + +* Is required: no +* Is array: no +* Default: `INF` diff --git a/vendor/symfony/console/Tests/Fixtures/input_argument_with_default_inf_value.txt b/vendor/symfony/console/Tests/Fixtures/input_argument_with_default_inf_value.txt new file mode 100644 index 00000000..c32d768c --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/input_argument_with_default_inf_value.txt @@ -0,0 +1 @@ + <info>argument_name</info> argument description<comment> [default: INF]</comment> diff --git a/vendor/symfony/console/Tests/Fixtures/input_argument_with_default_inf_value.xml b/vendor/symfony/console/Tests/Fixtures/input_argument_with_default_inf_value.xml new file mode 100644 index 00000000..d4572600 --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/input_argument_with_default_inf_value.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<argument name="argument_name" is_required="0" is_array="0"> + <description>argument description</description> + <defaults> + <default>INF</default> + </defaults> +</argument> diff --git a/vendor/symfony/console/Tests/Fixtures/input_argument_with_style.json b/vendor/symfony/console/Tests/Fixtures/input_argument_with_style.json new file mode 100644 index 00000000..93342351 --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/input_argument_with_style.json @@ -0,0 +1,7 @@ +{ + "name": "argument_name", + "is_required": false, + "is_array": false, + "description": "argument description", + "default": "<comment>style</>" +} diff --git a/vendor/symfony/console/Tests/Fixtures/input_argument_with_style.md b/vendor/symfony/console/Tests/Fixtures/input_argument_with_style.md new file mode 100644 index 00000000..a2be9672 --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/input_argument_with_style.md @@ -0,0 +1,7 @@ +#### `argument_name` + +argument description + +* Is required: no +* Is array: no +* Default: `'style'` diff --git a/vendor/symfony/console/Tests/Fixtures/input_argument_with_style.txt b/vendor/symfony/console/Tests/Fixtures/input_argument_with_style.txt new file mode 100644 index 00000000..35384a6b --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/input_argument_with_style.txt @@ -0,0 +1 @@ + <info>argument_name</info> argument description<comment> [default: "\<comment>style\</>"]</comment> diff --git a/vendor/symfony/console/Tests/Fixtures/input_argument_with_style.xml b/vendor/symfony/console/Tests/Fixtures/input_argument_with_style.xml new file mode 100644 index 00000000..73332c79 --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/input_argument_with_style.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<argument name="argument_name" is_required="0" is_array="0"> + <description>argument description</description> + <defaults> + <default><comment>style</></default> + </defaults> +</argument> diff --git a/vendor/symfony/console/Tests/Fixtures/input_definition_1.json b/vendor/symfony/console/Tests/Fixtures/input_definition_1.json index c7a7d838..44aa2c2e 100644 --- a/vendor/symfony/console/Tests/Fixtures/input_definition_1.json +++ b/vendor/symfony/console/Tests/Fixtures/input_definition_1.json @@ -1 +1,4 @@ -{"arguments":[],"options":[]} +{ + "arguments": [], + "options": [] +} diff --git a/vendor/symfony/console/Tests/Fixtures/input_definition_2.json b/vendor/symfony/console/Tests/Fixtures/input_definition_2.json index 9964a55a..7cfd57e5 100644 --- a/vendor/symfony/console/Tests/Fixtures/input_definition_2.json +++ b/vendor/symfony/console/Tests/Fixtures/input_definition_2.json @@ -1 +1,12 @@ -{"arguments":{"argument_name":{"name":"argument_name","is_required":true,"is_array":false,"description":"","default":null}},"options":[]} +{ + "arguments": { + "argument_name": { + "name": "argument_name", + "is_required": true, + "is_array": false, + "description": "", + "default": null + } + }, + "options": [] +} diff --git a/vendor/symfony/console/Tests/Fixtures/input_definition_2.md b/vendor/symfony/console/Tests/Fixtures/input_definition_2.md index 923191cd..ffc2bbbe 100644 --- a/vendor/symfony/console/Tests/Fixtures/input_definition_2.md +++ b/vendor/symfony/console/Tests/Fixtures/input_definition_2.md @@ -1,9 +1,7 @@ -### Arguments: +### Arguments -**argument_name:** +#### `argument_name` -* Name: argument_name * Is required: yes * Is array: no -* Description: <none> * Default: `NULL` diff --git a/vendor/symfony/console/Tests/Fixtures/input_definition_3.json b/vendor/symfony/console/Tests/Fixtures/input_definition_3.json index 6a860560..3b3cf73c 100644 --- a/vendor/symfony/console/Tests/Fixtures/input_definition_3.json +++ b/vendor/symfony/console/Tests/Fixtures/input_definition_3.json @@ -1 +1,14 @@ -{"arguments":[],"options":{"option_name":{"name":"--option_name","shortcut":"-o","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"","default":false}}} +{ + "arguments": [], + "options": { + "option_name": { + "name": "--option_name", + "shortcut": "-o", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "", + "default": false + } + } +} diff --git a/vendor/symfony/console/Tests/Fixtures/input_definition_3.md b/vendor/symfony/console/Tests/Fixtures/input_definition_3.md index 40fd7b0a..11f7cd6b 100644 --- a/vendor/symfony/console/Tests/Fixtures/input_definition_3.md +++ b/vendor/symfony/console/Tests/Fixtures/input_definition_3.md @@ -1,11 +1,8 @@ -### Options: +### Options -**option_name:** +#### `--option_name|-o` -* Name: `--option_name` -* Shortcut: `-o` * Accept value: no * Is value required: no * Is multiple: no -* Description: <none> * Default: `false` diff --git a/vendor/symfony/console/Tests/Fixtures/input_definition_4.json b/vendor/symfony/console/Tests/Fixtures/input_definition_4.json index c5a0019f..d4a51e82 100644 --- a/vendor/symfony/console/Tests/Fixtures/input_definition_4.json +++ b/vendor/symfony/console/Tests/Fixtures/input_definition_4.json @@ -1 +1,22 @@ -{"arguments":{"argument_name":{"name":"argument_name","is_required":true,"is_array":false,"description":"","default":null}},"options":{"option_name":{"name":"--option_name","shortcut":"-o","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"","default":false}}} +{ + "arguments": { + "argument_name": { + "name": "argument_name", + "is_required": true, + "is_array": false, + "description": "", + "default": null + } + }, + "options": { + "option_name": { + "name": "--option_name", + "shortcut": "-o", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "", + "default": false + } + } +} diff --git a/vendor/symfony/console/Tests/Fixtures/input_definition_4.md b/vendor/symfony/console/Tests/Fixtures/input_definition_4.md index a31feea4..c4f947f5 100644 --- a/vendor/symfony/console/Tests/Fixtures/input_definition_4.md +++ b/vendor/symfony/console/Tests/Fixtures/input_definition_4.md @@ -1,21 +1,16 @@ -### Arguments: +### Arguments -**argument_name:** +#### `argument_name` -* Name: argument_name * Is required: yes * Is array: no -* Description: <none> * Default: `NULL` -### Options: +### Options -**option_name:** +#### `--option_name|-o` -* Name: `--option_name` -* Shortcut: `-o` * Accept value: no * Is value required: no * Is multiple: no -* Description: <none> * Default: `false` diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_1.json b/vendor/symfony/console/Tests/Fixtures/input_option_1.json index 60c5b56c..f86bf967 100644 --- a/vendor/symfony/console/Tests/Fixtures/input_option_1.json +++ b/vendor/symfony/console/Tests/Fixtures/input_option_1.json @@ -1 +1,9 @@ -{"name":"--option_name","shortcut":"-o","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"","default":false} +{ + "name": "--option_name", + "shortcut": "-o", + "accept_value": false, + "is_value_required": false, + "is_multiple": false, + "description": "", + "default": false +} diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_1.md b/vendor/symfony/console/Tests/Fixtures/input_option_1.md index 6f9e9a7e..c544a4e6 100644 --- a/vendor/symfony/console/Tests/Fixtures/input_option_1.md +++ b/vendor/symfony/console/Tests/Fixtures/input_option_1.md @@ -1,9 +1,6 @@ -**option_name:** +#### `--option_name|-o` -* Name: `--option_name` -* Shortcut: `-o` * Accept value: no * Is value required: no * Is multiple: no -* Description: <none> * Default: `false` diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_2.json b/vendor/symfony/console/Tests/Fixtures/input_option_2.json index 04e4228e..32dbab21 100644 --- a/vendor/symfony/console/Tests/Fixtures/input_option_2.json +++ b/vendor/symfony/console/Tests/Fixtures/input_option_2.json @@ -1 +1,9 @@ -{"name":"--option_name","shortcut":"-o","accept_value":true,"is_value_required":false,"is_multiple":false,"description":"option description","default":"default_value"} +{ + "name": "--option_name", + "shortcut": "-o", + "accept_value": true, + "is_value_required": false, + "is_multiple": false, + "description": "option description", + "default": "default_value" +} diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_2.md b/vendor/symfony/console/Tests/Fixtures/input_option_2.md index 634ac0b0..293e6179 100644 --- a/vendor/symfony/console/Tests/Fixtures/input_option_2.md +++ b/vendor/symfony/console/Tests/Fixtures/input_option_2.md @@ -1,9 +1,8 @@ -**option_name:** +#### `--option_name|-o` + +option description -* Name: `--option_name` -* Shortcut: `-o` * Accept value: yes * Is value required: no * Is multiple: no -* Description: option description * Default: `'default_value'` diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_3.json b/vendor/symfony/console/Tests/Fixtures/input_option_3.json index c1ea120c..6d55a6ef 100644 --- a/vendor/symfony/console/Tests/Fixtures/input_option_3.json +++ b/vendor/symfony/console/Tests/Fixtures/input_option_3.json @@ -1 +1,9 @@ -{"name":"--option_name","shortcut":"-o","accept_value":true,"is_value_required":true,"is_multiple":false,"description":"option description","default":null} +{ + "name": "--option_name", + "shortcut": "-o", + "accept_value": true, + "is_value_required": true, + "is_multiple": false, + "description": "option description", + "default": null +} diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_3.md b/vendor/symfony/console/Tests/Fixtures/input_option_3.md index 34282896..7e89d697 100644 --- a/vendor/symfony/console/Tests/Fixtures/input_option_3.md +++ b/vendor/symfony/console/Tests/Fixtures/input_option_3.md @@ -1,9 +1,8 @@ -**option_name:** +#### `--option_name|-o` + +option description -* Name: `--option_name` -* Shortcut: `-o` * Accept value: yes * Is value required: yes * Is multiple: no -* Description: option description * Default: `NULL` diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_4.json b/vendor/symfony/console/Tests/Fixtures/input_option_4.json index 1b671d80..788a8ed4 100644 --- a/vendor/symfony/console/Tests/Fixtures/input_option_4.json +++ b/vendor/symfony/console/Tests/Fixtures/input_option_4.json @@ -1 +1,9 @@ -{"name":"--option_name","shortcut":"-o","accept_value":true,"is_value_required":false,"is_multiple":true,"description":"option description","default":[]} +{ + "name": "--option_name", + "shortcut": "-o", + "accept_value": true, + "is_value_required": false, + "is_multiple": true, + "description": "option description", + "default": [] +} diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_4.md b/vendor/symfony/console/Tests/Fixtures/input_option_4.md index 8ffba56e..7eb2d2ae 100644 --- a/vendor/symfony/console/Tests/Fixtures/input_option_4.md +++ b/vendor/symfony/console/Tests/Fixtures/input_option_4.md @@ -1,9 +1,8 @@ -**option_name:** +#### `--option_name|-o` + +option description -* Name: `--option_name` -* Shortcut: `-o` * Accept value: yes * Is value required: no * Is multiple: yes -* Description: option description * Default: `array ()` diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_5.json b/vendor/symfony/console/Tests/Fixtures/input_option_5.json index 35a1405f..9f34d832 100644 --- a/vendor/symfony/console/Tests/Fixtures/input_option_5.json +++ b/vendor/symfony/console/Tests/Fixtures/input_option_5.json @@ -1 +1,9 @@ -{"name":"--option_name","shortcut":"-o","accept_value":true,"is_value_required":true,"is_multiple":false,"description":"multiline option description","default":null} +{ + "name": "--option_name", + "shortcut": "-o", + "accept_value": true, + "is_value_required": true, + "is_multiple": false, + "description": "multiline option description", + "default": null +} diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_5.md b/vendor/symfony/console/Tests/Fixtures/input_option_5.md index 82f51cad..72ca4391 100644 --- a/vendor/symfony/console/Tests/Fixtures/input_option_5.md +++ b/vendor/symfony/console/Tests/Fixtures/input_option_5.md @@ -1,10 +1,9 @@ -**option_name:** +#### `--option_name|-o` + +multiline +option description -* Name: `--option_name` -* Shortcut: `-o` * Accept value: yes * Is value required: yes * Is multiple: no -* Description: multiline - option description * Default: `NULL` diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_5.txt b/vendor/symfony/console/Tests/Fixtures/input_option_5.txt index 4368883c..9563b4ca 100644 --- a/vendor/symfony/console/Tests/Fixtures/input_option_5.txt +++ b/vendor/symfony/console/Tests/Fixtures/input_option_5.txt @@ -1,2 +1,2 @@ <info>-o, --option_name=OPTION_NAME</info> multiline - option description + option description diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_6.json b/vendor/symfony/console/Tests/Fixtures/input_option_6.json index d84e8721..0638de03 100644 --- a/vendor/symfony/console/Tests/Fixtures/input_option_6.json +++ b/vendor/symfony/console/Tests/Fixtures/input_option_6.json @@ -1 +1,9 @@ -{"name":"--option_name","shortcut":"-o|-O","accept_value":true,"is_value_required":true,"is_multiple":false,"description":"option with multiple shortcuts","default":null} +{ + "name": "--option_name", + "shortcut": "-o|-O", + "accept_value": true, + "is_value_required": true, + "is_multiple": false, + "description": "option with multiple shortcuts", + "default": null +} diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_6.md b/vendor/symfony/console/Tests/Fixtures/input_option_6.md index ed1ea1c8..87acd8b9 100644 --- a/vendor/symfony/console/Tests/Fixtures/input_option_6.md +++ b/vendor/symfony/console/Tests/Fixtures/input_option_6.md @@ -1,9 +1,8 @@ -**option_name:** +#### `--option_name|-o|-O` + +option with multiple shortcuts -* Name: `--option_name` -* Shortcut: `-o|-O` * Accept value: yes * Is value required: yes * Is multiple: no -* Description: option with multiple shortcuts * Default: `NULL` diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_with_default_inf_value.json b/vendor/symfony/console/Tests/Fixtures/input_option_with_default_inf_value.json new file mode 100644 index 00000000..7c96ad30 --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/input_option_with_default_inf_value.json @@ -0,0 +1,9 @@ +{ + "name": "--option_name", + "shortcut": "-o", + "accept_value": true, + "is_value_required": false, + "is_multiple": false, + "description": "option description", + "default": "INF" +} diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_with_default_inf_value.md b/vendor/symfony/console/Tests/Fixtures/input_option_with_default_inf_value.md new file mode 100644 index 00000000..c27e30a0 --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/input_option_with_default_inf_value.md @@ -0,0 +1,8 @@ +#### `--option_name|-o` + +option description + +* Accept value: yes +* Is value required: no +* Is multiple: no +* Default: `INF` diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_with_default_inf_value.txt b/vendor/symfony/console/Tests/Fixtures/input_option_with_default_inf_value.txt new file mode 100644 index 00000000..d467dcf4 --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/input_option_with_default_inf_value.txt @@ -0,0 +1 @@ + <info>-o, --option_name[=OPTION_NAME]</info> option description<comment> [default: INF]</comment> diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_with_default_inf_value.xml b/vendor/symfony/console/Tests/Fixtures/input_option_with_default_inf_value.xml new file mode 100644 index 00000000..5d1d2175 --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/input_option_with_default_inf_value.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<option name="--option_name" shortcut="-o" accept_value="1" is_value_required="0" is_multiple="0"> + <description>option description</description> + <defaults> + <default>INF</default> + </defaults> +</option> diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_with_style.json b/vendor/symfony/console/Tests/Fixtures/input_option_with_style.json new file mode 100644 index 00000000..df328bf8 --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/input_option_with_style.json @@ -0,0 +1,9 @@ +{ + "name": "--option_name", + "shortcut": "-o", + "accept_value": true, + "is_value_required": true, + "is_multiple": false, + "description": "option description", + "default": "<comment>style</>" +} diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_with_style.md b/vendor/symfony/console/Tests/Fixtures/input_option_with_style.md new file mode 100644 index 00000000..e07a5643 --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/input_option_with_style.md @@ -0,0 +1,8 @@ +#### `--option_name|-o` + +option description + +* Accept value: yes +* Is value required: yes +* Is multiple: no +* Default: `'style'` diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_with_style.txt b/vendor/symfony/console/Tests/Fixtures/input_option_with_style.txt new file mode 100644 index 00000000..880a5351 --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/input_option_with_style.txt @@ -0,0 +1 @@ + <info>-o, --option_name=OPTION_NAME</info> option description<comment> [default: "\<comment>style\</>"]</comment> diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_with_style.xml b/vendor/symfony/console/Tests/Fixtures/input_option_with_style.xml new file mode 100644 index 00000000..764b9e65 --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/input_option_with_style.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<option name="--option_name" shortcut="-o" accept_value="1" is_value_required="1" is_multiple="0"> + <description>option description</description> + <defaults> + <default><comment>style</></default> + </defaults> +</option> diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_with_style_array.json b/vendor/symfony/console/Tests/Fixtures/input_option_with_style_array.json new file mode 100644 index 00000000..b1754550 --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/input_option_with_style_array.json @@ -0,0 +1,12 @@ +{ + "name": "--option_name", + "shortcut": "-o", + "accept_value": true, + "is_value_required": true, + "is_multiple": true, + "description": "option description", + "default": [ + "<comment>Hello</comment>", + "<info>world</info>" + ] +} diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_with_style_array.md b/vendor/symfony/console/Tests/Fixtures/input_option_with_style_array.md new file mode 100644 index 00000000..16a045bc --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/input_option_with_style_array.md @@ -0,0 +1,8 @@ +#### `--option_name|-o` + +option description + +* Accept value: yes +* Is value required: yes +* Is multiple: yes +* Default: `array ( 0 => 'Hello', 1 => 'world',)` diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_with_style_array.txt b/vendor/symfony/console/Tests/Fixtures/input_option_with_style_array.txt new file mode 100644 index 00000000..265c18c5 --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/input_option_with_style_array.txt @@ -0,0 +1 @@ + <info>-o, --option_name=OPTION_NAME</info> option description<comment> [default: ["\<comment>Hello\</comment>","\<info>world\</info>"]]</comment><comment> (multiple values allowed)</comment> diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_with_style_array.xml b/vendor/symfony/console/Tests/Fixtures/input_option_with_style_array.xml new file mode 100644 index 00000000..09dc8658 --- /dev/null +++ b/vendor/symfony/console/Tests/Fixtures/input_option_with_style_array.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<option name="--option_name" shortcut="-o" accept_value="1" is_value_required="1" is_multiple="1"> + <description>option description</description> + <defaults> + <default><comment>Hello</comment></default> + <default><info>world</info></default> + </defaults> +</option> diff --git a/vendor/symfony/console/Tests/Formatter/OutputFormatterStyleStackTest.php b/vendor/symfony/console/Tests/Formatter/OutputFormatterStyleStackTest.php index 774df268..6cd7c82b 100644 --- a/vendor/symfony/console/Tests/Formatter/OutputFormatterStyleStackTest.php +++ b/vendor/symfony/console/Tests/Formatter/OutputFormatterStyleStackTest.php @@ -11,10 +11,11 @@ namespace Symfony\Component\Console\Tests\Formatter; +use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Formatter\OutputFormatterStyleStack; use Symfony\Component\Console\Formatter\OutputFormatterStyle; -class OutputFormatterStyleStackTest extends \PHPUnit_Framework_TestCase +class OutputFormatterStyleStackTest extends TestCase { public function testPush() { diff --git a/vendor/symfony/console/Tests/Formatter/OutputFormatterStyleTest.php b/vendor/symfony/console/Tests/Formatter/OutputFormatterStyleTest.php index 0abfb3ce..ddf77902 100644 --- a/vendor/symfony/console/Tests/Formatter/OutputFormatterStyleTest.php +++ b/vendor/symfony/console/Tests/Formatter/OutputFormatterStyleTest.php @@ -11,9 +11,10 @@ namespace Symfony\Component\Console\Tests\Formatter; +use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Formatter\OutputFormatterStyle; -class OutputFormatterStyleTest extends \PHPUnit_Framework_TestCase +class OutputFormatterStyleTest extends TestCase { public function testConstructor() { @@ -40,7 +41,7 @@ class OutputFormatterStyleTest extends \PHPUnit_Framework_TestCase $style->setForeground('default'); $this->assertEquals("\033[39mfoo\033[39m", $style->apply('foo')); - $this->setExpectedException('InvalidArgumentException'); + $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('InvalidArgumentException'); $style->setForeground('undefined-color'); } @@ -57,7 +58,7 @@ class OutputFormatterStyleTest extends \PHPUnit_Framework_TestCase $style->setBackground('default'); $this->assertEquals("\033[49mfoo\033[49m", $style->apply('foo')); - $this->setExpectedException('InvalidArgumentException'); + $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('InvalidArgumentException'); $style->setBackground('undefined-color'); } diff --git a/vendor/symfony/console/Tests/Formatter/OutputFormatterTest.php b/vendor/symfony/console/Tests/Formatter/OutputFormatterTest.php index b8d5ca6d..a1aa8013 100644 --- a/vendor/symfony/console/Tests/Formatter/OutputFormatterTest.php +++ b/vendor/symfony/console/Tests/Formatter/OutputFormatterTest.php @@ -11,10 +11,11 @@ namespace Symfony\Component\Console\Tests\Formatter; +use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Formatter\OutputFormatter; use Symfony\Component\Console\Formatter\OutputFormatterStyle; -class OutputFormatterTest extends \PHPUnit_Framework_TestCase +class OutputFormatterTest extends TestCase { public function testEmptyTag() { @@ -27,6 +28,9 @@ class OutputFormatterTest extends \PHPUnit_Framework_TestCase $formatter = new OutputFormatter(true); $this->assertEquals('foo<bar', $formatter->format('foo\\<bar')); + $this->assertEquals('foo << bar', $formatter->format('foo << bar')); + $this->assertEquals('foo << bar \\', $formatter->format('foo << bar \\')); + $this->assertEquals("foo << \033[32mbar \\ baz\033[39m \\", $formatter->format('foo << <info>bar \\ baz</info> \\')); $this->assertEquals('<info>some info</info>', $formatter->format('\\<info>some info\\</info>')); $this->assertEquals('\\<info>some info\\</info>', OutputFormatter::escape('<info>some info</info>')); @@ -152,6 +156,67 @@ class OutputFormatterTest extends \PHPUnit_Framework_TestCase $this->assertEquals("\033[34;41msome text\033[39;49m", $formatter->format('<fg=blue;bg=red>some text</fg=blue;bg=red>')); } + /** + * @param string $tag + * @param string|null $expected + * @param string|null $input + * + * @dataProvider provideInlineStyleOptionsCases + */ + public function testInlineStyleOptions($tag, $expected = null, $input = null) + { + $styleString = substr($tag, 1, -1); + $formatter = new OutputFormatter(true); + $method = new \ReflectionMethod($formatter, 'createStyleFromString'); + $method->setAccessible(true); + $result = $method->invoke($formatter, $styleString); + if (null === $expected) { + $this->assertFalse($result); + $expected = $tag.$input.'</'.$styleString.'>'; + $this->assertSame($expected, $formatter->format($expected)); + } else { + /* @var OutputFormatterStyle $result */ + $this->assertInstanceOf(OutputFormatterStyle::class, $result); + $this->assertSame($expected, $formatter->format($tag.$input.'</>')); + $this->assertSame($expected, $formatter->format($tag.$input.'</'.$styleString.'>')); + } + } + + public function provideInlineStyleOptionsCases() + { + return array( + array('<unknown=_unknown_>'), + array('<unknown=_unknown_;a=1;b>'), + array('<fg=green;>', "\033[32m[test]\033[39m", '[test]'), + array('<fg=green;bg=blue;>', "\033[32;44ma\033[39;49m", 'a'), + array('<fg=green;options=bold>', "\033[32;1mb\033[39;22m", 'b'), + array('<fg=green;options=reverse;>', "\033[32;7m<a>\033[39;27m", '<a>'), + array('<fg=green;options=bold,underscore>', "\033[32;1;4mz\033[39;22;24m", 'z'), + array('<fg=green;options=bold,underscore,reverse;>', "\033[32;1;4;7md\033[39;22;24;27m", 'd'), + ); + } + + /** + * @group legacy + * @dataProvider provideInlineStyleTagsWithUnknownOptions + * @expectedDeprecation Unknown style options are deprecated since version 3.2 and will be removed in 4.0. Exception "Invalid option specified: "%s". Expected one of (bold, underscore, blink, reverse, conceal)". + */ + public function testInlineStyleOptionsUnknownAreDeprecated($tag, $option) + { + $formatter = new OutputFormatter(true); + $formatter->format($tag); + } + + public function provideInlineStyleTagsWithUnknownOptions() + { + return array( + array('<options=abc;>', 'abc'), + array('<options=abc,def;>', 'abc'), + array('<fg=green;options=xyz;>', 'xyz'), + array('<fg=green;options=efg,abc>', 'efg'), + ); + } + public function testNonStyleTag() { $formatter = new OutputFormatter(true); @@ -195,6 +260,9 @@ class OutputFormatterTest extends \PHPUnit_Framework_TestCase $this->assertEquals( 'some question', $formatter->format('<question>some question</question>') ); + $this->assertEquals( + 'some text with inline style', $formatter->format('<fg=red>some text with inline style</>') + ); $formatter->setDecorated(true); @@ -210,6 +278,9 @@ class OutputFormatterTest extends \PHPUnit_Framework_TestCase $this->assertEquals( "\033[30;46msome question\033[39;49m", $formatter->format('<question>some question</question>') ); + $this->assertEquals( + "\033[31msome text with inline style\033[39m", $formatter->format('<fg=red>some text with inline style</>') + ); } public function testContentWithLineBreaks() diff --git a/vendor/symfony/console/Tests/Helper/AbstractQuestionHelperTest.php b/vendor/symfony/console/Tests/Helper/AbstractQuestionHelperTest.php new file mode 100644 index 00000000..56dd65f6 --- /dev/null +++ b/vendor/symfony/console/Tests/Helper/AbstractQuestionHelperTest.php @@ -0,0 +1,34 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Tests\Helper; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Console\Input\StreamableInputInterface; + +abstract class AbstractQuestionHelperTest extends TestCase +{ + protected function createStreamableInputInterfaceMock($stream = null, $interactive = true) + { + $mock = $this->getMockBuilder(StreamableInputInterface::class)->getMock(); + $mock->expects($this->any()) + ->method('isInteractive') + ->will($this->returnValue($interactive)); + + if ($stream) { + $mock->expects($this->any()) + ->method('getStream') + ->willReturn($stream); + } + + return $mock; + } +} diff --git a/vendor/symfony/console/Tests/Helper/FormatterHelperTest.php b/vendor/symfony/console/Tests/Helper/FormatterHelperTest.php index e0aa9211..f5d891a1 100644 --- a/vendor/symfony/console/Tests/Helper/FormatterHelperTest.php +++ b/vendor/symfony/console/Tests/Helper/FormatterHelperTest.php @@ -11,9 +11,10 @@ namespace Symfony\Component\Console\Tests\Helper; +use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Helper\FormatterHelper; -class FormatterHelperTest extends \PHPUnit_Framework_TestCase +class FormatterHelperTest extends TestCase { public function testFormatSection() { @@ -89,4 +90,40 @@ class FormatterHelperTest extends \PHPUnit_Framework_TestCase '::formatBlock() escapes \'<\' chars' ); } + + public function testTruncatingWithShorterLengthThanMessageWithSuffix() + { + $formatter = new FormatterHelper(); + $message = 'testing truncate'; + + $this->assertSame('test...', $formatter->truncate($message, 4)); + $this->assertSame('testing truncat...', $formatter->truncate($message, 15)); + $this->assertSame('testing truncate...', $formatter->truncate($message, 16)); + $this->assertSame('zażółć gęślą...', $formatter->truncate('zażółć gęślą jaźń', 12)); + } + + public function testTruncatingMessageWithCustomSuffix() + { + $formatter = new FormatterHelper(); + $message = 'testing truncate'; + + $this->assertSame('test!', $formatter->truncate($message, 4, '!')); + } + + public function testTruncatingWithLongerLengthThanMessageWithSuffix() + { + $formatter = new FormatterHelper(); + $message = 'test'; + + $this->assertSame($message, $formatter->truncate($message, 10)); + } + + public function testTruncatingWithNegativeLength() + { + $formatter = new FormatterHelper(); + $message = 'testing truncate'; + + $this->assertSame('testing tru...', $formatter->truncate($message, -5)); + $this->assertSame('...', $formatter->truncate($message, -100)); + } } diff --git a/vendor/symfony/console/Tests/Helper/HelperSetTest.php b/vendor/symfony/console/Tests/Helper/HelperSetTest.php index 04edd304..aceef704 100644 --- a/vendor/symfony/console/Tests/Helper/HelperSetTest.php +++ b/vendor/symfony/console/Tests/Helper/HelperSetTest.php @@ -11,10 +11,11 @@ namespace Symfony\Component\Console\Tests\Helper; +use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Helper\HelperSet; use Symfony\Component\Console\Command\Command; -class HelperSetTest extends \PHPUnit_Framework_TestCase +class HelperSetTest extends TestCase { public function testConstructor() { @@ -108,16 +109,9 @@ class HelperSetTest extends \PHPUnit_Framework_TestCase } } - /** - * Create a generic mock for the helper interface. Optionally check for a call to setHelperSet with a specific - * helperset instance. - * - * @param string $name - * @param HelperSet $helperset allows a mock to verify a particular helperset set is being added to the Helper - */ private function getGenericMockHelper($name, HelperSet $helperset = null) { - $mock_helper = $this->getMock('\Symfony\Component\Console\Helper\HelperInterface'); + $mock_helper = $this->getMockBuilder('\Symfony\Component\Console\Helper\HelperInterface')->getMock(); $mock_helper->expects($this->any()) ->method('getName') ->will($this->returnValue($name)); diff --git a/vendor/symfony/console/Tests/Helper/HelperTest.php b/vendor/symfony/console/Tests/Helper/HelperTest.php index 33fa2205..18475824 100644 --- a/vendor/symfony/console/Tests/Helper/HelperTest.php +++ b/vendor/symfony/console/Tests/Helper/HelperTest.php @@ -11,9 +11,10 @@ namespace Symfony\Component\Console\Tests\Helper; +use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Helper\Helper; -class HelperTest extends \PHPUnit_Framework_TestCase +class HelperTest extends TestCase { public function formatTimeProvider() { diff --git a/vendor/symfony/console/Tests/Helper/LegacyDialogHelperTest.php b/vendor/symfony/console/Tests/Helper/LegacyDialogHelperTest.php deleted file mode 100644 index 97bf7756..00000000 --- a/vendor/symfony/console/Tests/Helper/LegacyDialogHelperTest.php +++ /dev/null @@ -1,263 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Helper; - -use Symfony\Component\Console\Input\ArrayInput; -use Symfony\Component\Console\Helper\DialogHelper; -use Symfony\Component\Console\Helper\HelperSet; -use Symfony\Component\Console\Helper\FormatterHelper; -use Symfony\Component\Console\Output\ConsoleOutput; -use Symfony\Component\Console\Output\StreamOutput; -use Symfony\Component\Console\Exception\InvalidArgumentException; - -/** - * @group legacy - */ -class LegacyDialogHelperTest extends \PHPUnit_Framework_TestCase -{ - public function testSelect() - { - $dialog = new DialogHelper(); - - $helperSet = new HelperSet(array(new FormatterHelper())); - $dialog->setHelperSet($helperSet); - - $heroes = array('Superman', 'Batman', 'Spiderman'); - - $dialog->setInputStream($this->getInputStream("\n1\n 1 \nFabien\n1\nFabien\n1\n0,2\n 0 , 2 \n\n\n")); - $this->assertEquals('2', $dialog->select($this->getOutputStream(), 'What is your favorite superhero?', $heroes, '2')); - $this->assertEquals('1', $dialog->select($this->getOutputStream(), 'What is your favorite superhero?', $heroes)); - $this->assertEquals('1', $dialog->select($this->getOutputStream(), 'What is your favorite superhero?', $heroes)); - $this->assertEquals('1', $dialog->select($output = $this->getOutputStream(), 'What is your favorite superhero?', $heroes, null, false, 'Input "%s" is not a superhero!', false)); - - rewind($output->getStream()); - $this->assertContains('Input "Fabien" is not a superhero!', stream_get_contents($output->getStream())); - - try { - $this->assertEquals('1', $dialog->select($output = $this->getOutputStream(), 'What is your favorite superhero?', $heroes, null, 1)); - $this->fail(); - } catch (\InvalidArgumentException $e) { - $this->assertEquals('Value "Fabien" is invalid', $e->getMessage()); - } - - $this->assertEquals(array('1'), $dialog->select($this->getOutputStream(), 'What is your favorite superhero?', $heroes, null, false, 'Input "%s" is not a superhero!', true)); - $this->assertEquals(array('0', '2'), $dialog->select($this->getOutputStream(), 'What is your favorite superhero?', $heroes, null, false, 'Input "%s" is not a superhero!', true)); - $this->assertEquals(array('0', '2'), $dialog->select($this->getOutputStream(), 'What is your favorite superhero?', $heroes, null, false, 'Input "%s" is not a superhero!', true)); - $this->assertEquals(array('0', '1'), $dialog->select($this->getOutputStream(), 'What is your favorite superhero?', $heroes, '0,1', false, 'Input "%s" is not a superhero!', true)); - $this->assertEquals(array('0', '1'), $dialog->select($this->getOutputStream(), 'What is your favorite superhero?', $heroes, ' 0 , 1 ', false, 'Input "%s" is not a superhero!', true)); - } - - public function testSelectOnErrorOutput() - { - $dialog = new DialogHelper(); - - $helperSet = new HelperSet(array(new FormatterHelper())); - $dialog->setHelperSet($helperSet); - - $heroes = array('Superman', 'Batman', 'Spiderman'); - - $dialog->setInputStream($this->getInputStream("Stdout\n1\n")); - $this->assertEquals('1', $dialog->select($output = $this->getConsoleOutput($this->getOutputStream()), 'What is your favorite superhero?', $heroes, null, false, 'Input "%s" is not a superhero!', false)); - - rewind($output->getErrorOutput()->getStream()); - $this->assertContains('Input "Stdout" is not a superhero!', stream_get_contents($output->getErrorOutput()->getStream())); - } - - public function testAsk() - { - $dialog = new DialogHelper(); - - $dialog->setInputStream($this->getInputStream("\n8AM\n")); - - $this->assertEquals('2PM', $dialog->ask($this->getOutputStream(), 'What time is it?', '2PM')); - $this->assertEquals('8AM', $dialog->ask($output = $this->getOutputStream(), 'What time is it?', '2PM')); - - rewind($output->getStream()); - $this->assertEquals('What time is it?', stream_get_contents($output->getStream())); - } - - public function testAskOnErrorOutput() - { - if (!$this->hasSttyAvailable()) { - $this->markTestSkipped('`stderr` is required to test stderr output functionality'); - } - - $dialog = new DialogHelper(); - - $dialog->setInputStream($this->getInputStream("not stdout\n")); - - $this->assertEquals('not stdout', $dialog->ask($output = $this->getConsoleOutput($this->getOutputStream()), 'Where should output go?', 'stderr')); - - rewind($output->getErrorOutput()->getStream()); - $this->assertEquals('Where should output go?', stream_get_contents($output->getErrorOutput()->getStream())); - } - - public function testAskWithAutocomplete() - { - if (!$this->hasSttyAvailable()) { - $this->markTestSkipped('`stty` is required to test autocomplete functionality'); - } - - // Acm<NEWLINE> - // Ac<BACKSPACE><BACKSPACE>s<TAB>Test<NEWLINE> - // <NEWLINE> - // <UP ARROW><UP ARROW><NEWLINE> - // <UP ARROW><UP ARROW><UP ARROW><UP ARROW><UP ARROW><TAB>Test<NEWLINE> - // <DOWN ARROW><NEWLINE> - // S<BACKSPACE><BACKSPACE><DOWN ARROW><DOWN ARROW><NEWLINE> - // F00<BACKSPACE><BACKSPACE>oo<TAB><NEWLINE> - $inputStream = $this->getInputStream("Acm\nAc\177\177s\tTest\n\n\033[A\033[A\n\033[A\033[A\033[A\033[A\033[A\tTest\n\033[B\nS\177\177\033[B\033[B\nF00\177\177oo\t\n"); - - $dialog = new DialogHelper(); - $dialog->setInputStream($inputStream); - - $bundles = array('AcmeDemoBundle', 'AsseticBundle', 'SecurityBundle', 'FooBundle'); - - $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->getOutputStream(), 'Please select a bundle', 'FrameworkBundle', $bundles)); - $this->assertEquals('AsseticBundleTest', $dialog->ask($this->getOutputStream(), 'Please select a bundle', 'FrameworkBundle', $bundles)); - $this->assertEquals('FrameworkBundle', $dialog->ask($this->getOutputStream(), 'Please select a bundle', 'FrameworkBundle', $bundles)); - $this->assertEquals('SecurityBundle', $dialog->ask($this->getOutputStream(), 'Please select a bundle', 'FrameworkBundle', $bundles)); - $this->assertEquals('FooBundleTest', $dialog->ask($this->getOutputStream(), 'Please select a bundle', 'FrameworkBundle', $bundles)); - $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->getOutputStream(), 'Please select a bundle', 'FrameworkBundle', $bundles)); - $this->assertEquals('AsseticBundle', $dialog->ask($this->getOutputStream(), 'Please select a bundle', 'FrameworkBundle', $bundles)); - $this->assertEquals('FooBundle', $dialog->ask($this->getOutputStream(), 'Please select a bundle', 'FrameworkBundle', $bundles)); - } - - /** - * @group tty - */ - public function testAskHiddenResponse() - { - if ('\\' === DIRECTORY_SEPARATOR) { - $this->markTestSkipped('This test is not supported on Windows'); - } - - $dialog = new DialogHelper(); - - $dialog->setInputStream($this->getInputStream("8AM\n")); - - $this->assertEquals('8AM', $dialog->askHiddenResponse($this->getOutputStream(), 'What time is it?')); - } - - /** - * @group tty - */ - public function testAskHiddenResponseOnErrorOutput() - { - if ('\\' === DIRECTORY_SEPARATOR) { - $this->markTestSkipped('This test is not supported on Windows'); - } - - $dialog = new DialogHelper(); - - $dialog->setInputStream($this->getInputStream("8AM\n")); - - $this->assertEquals('8AM', $dialog->askHiddenResponse($output = $this->getConsoleOutput($this->getOutputStream()), 'What time is it?')); - - rewind($output->getErrorOutput()->getStream()); - $this->assertContains('What time is it?', stream_get_contents($output->getErrorOutput()->getStream())); - } - - public function testAskConfirmation() - { - $dialog = new DialogHelper(); - - $dialog->setInputStream($this->getInputStream("\n\n")); - $this->assertTrue($dialog->askConfirmation($this->getOutputStream(), 'Do you like French fries?')); - $this->assertFalse($dialog->askConfirmation($this->getOutputStream(), 'Do you like French fries?', false)); - - $dialog->setInputStream($this->getInputStream("y\nyes\n")); - $this->assertTrue($dialog->askConfirmation($this->getOutputStream(), 'Do you like French fries?', false)); - $this->assertTrue($dialog->askConfirmation($this->getOutputStream(), 'Do you like French fries?', false)); - - $dialog->setInputStream($this->getInputStream("n\nno\n")); - $this->assertFalse($dialog->askConfirmation($this->getOutputStream(), 'Do you like French fries?', true)); - $this->assertFalse($dialog->askConfirmation($this->getOutputStream(), 'Do you like French fries?', true)); - } - - public function testAskAndValidate() - { - $dialog = new DialogHelper(); - $helperSet = new HelperSet(array(new FormatterHelper())); - $dialog->setHelperSet($helperSet); - - $question = 'What color was the white horse of Henry IV?'; - $error = 'This is not a color!'; - $validator = function ($color) use ($error) { - if (!in_array($color, array('white', 'black'))) { - throw new InvalidArgumentException($error); - } - - return $color; - }; - - $dialog->setInputStream($this->getInputStream("\nblack\n")); - $this->assertEquals('white', $dialog->askAndValidate($this->getOutputStream(), $question, $validator, 2, 'white')); - $this->assertEquals('black', $dialog->askAndValidate($this->getOutputStream(), $question, $validator, 2, 'white')); - - $dialog->setInputStream($this->getInputStream("green\nyellow\norange\n")); - try { - $this->assertEquals('white', $dialog->askAndValidate($output = $this->getConsoleOutput($this->getOutputStream()), $question, $validator, 2, 'white')); - $this->fail(); - } catch (\InvalidArgumentException $e) { - $this->assertEquals($error, $e->getMessage()); - rewind($output->getErrorOutput()->getStream()); - $this->assertContains('What color was the white horse of Henry IV?', stream_get_contents($output->getErrorOutput()->getStream())); - } - } - - public function testNoInteraction() - { - $dialog = new DialogHelper(); - - $input = new ArrayInput(array()); - $input->setInteractive(false); - - $dialog->setInput($input); - - $this->assertEquals('not yet', $dialog->ask($this->getOutputStream(), 'Do you have a job?', 'not yet')); - } - - protected function getInputStream($input) - { - $stream = fopen('php://memory', 'r+', false); - fwrite($stream, $input); - rewind($stream); - - return $stream; - } - - protected function getOutputStream() - { - return new StreamOutput(fopen('php://memory', 'r+', false)); - } - - protected function getConsoleOutput($stderr) - { - $output = new ConsoleOutput(); - $output->setErrorOutput($stderr); - - return $output; - } - - private function hasStderrSupport() - { - return false === $this->isRunningOS400(); - } - - private function hasSttyAvailable() - { - exec('stty 2>&1', $output, $exitcode); - - return $exitcode === 0; - } -} diff --git a/vendor/symfony/console/Tests/Helper/LegacyProgressHelperTest.php b/vendor/symfony/console/Tests/Helper/LegacyProgressHelperTest.php deleted file mode 100644 index f835a71e..00000000 --- a/vendor/symfony/console/Tests/Helper/LegacyProgressHelperTest.php +++ /dev/null @@ -1,224 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Helper; - -use Symfony\Component\Console\Helper\ProgressHelper; -use Symfony\Component\Console\Output\StreamOutput; - -/** - * @group legacy - * @group time-sensitive - */ -class LegacyProgressHelperTest extends \PHPUnit_Framework_TestCase -{ - public function testAdvance() - { - $progress = new ProgressHelper(); - $progress->start($output = $this->getOutputStream()); - $progress->advance(); - - rewind($output->getStream()); - $this->assertEquals($this->generateOutput(' 1 [->--------------------------]'), stream_get_contents($output->getStream())); - } - - public function testAdvanceWithStep() - { - $progress = new ProgressHelper(); - $progress->start($output = $this->getOutputStream()); - $progress->advance(5); - - rewind($output->getStream()); - $this->assertEquals($this->generateOutput(' 5 [----->----------------------]'), stream_get_contents($output->getStream())); - } - - public function testAdvanceMultipleTimes() - { - $progress = new ProgressHelper(); - $progress->start($output = $this->getOutputStream()); - $progress->advance(3); - $progress->advance(2); - - rewind($output->getStream()); - $this->assertEquals($this->generateOutput(' 3 [--->------------------------]').$this->generateOutput(' 5 [----->----------------------]'), stream_get_contents($output->getStream())); - } - - public function testCustomizations() - { - $progress = new ProgressHelper(); - $progress->setBarWidth(10); - $progress->setBarCharacter('_'); - $progress->setEmptyBarCharacter(' '); - $progress->setProgressCharacter('/'); - $progress->setFormat(' %current%/%max% [%bar%] %percent%%'); - $progress->start($output = $this->getOutputStream(), 10); - $progress->advance(); - - rewind($output->getStream()); - $this->assertEquals($this->generateOutput(' 1/10 [_/ ] 10%'), stream_get_contents($output->getStream())); - } - - public function testPercent() - { - $progress = new ProgressHelper(); - $progress->start($output = $this->getOutputStream(), 50); - $progress->display(); - $progress->advance(); - $progress->advance(); - - rewind($output->getStream()); - $this->assertEquals($this->generateOutput(' 0/50 [>---------------------------] 0%').$this->generateOutput(' 1/50 [>---------------------------] 2%').$this->generateOutput(' 2/50 [=>--------------------------] 4%'), stream_get_contents($output->getStream())); - } - - public function testOverwriteWithShorterLine() - { - $progress = new ProgressHelper(); - $progress->setFormat(' %current%/%max% [%bar%] %percent%%'); - $progress->start($output = $this->getOutputStream(), 50); - $progress->display(); - $progress->advance(); - - // set shorter format - $progress->setFormat(' %current%/%max% [%bar%]'); - $progress->advance(); - - rewind($output->getStream()); - $this->assertEquals( - $this->generateOutput(' 0/50 [>---------------------------] 0%'). - $this->generateOutput(' 1/50 [>---------------------------] 2%'). - $this->generateOutput(' 2/50 [=>--------------------------] '), - stream_get_contents($output->getStream()) - ); - } - - public function testSetCurrentProgress() - { - $progress = new ProgressHelper(); - $progress->start($output = $this->getOutputStream(), 50); - $progress->display(); - $progress->advance(); - $progress->setCurrent(15); - $progress->setCurrent(25); - - rewind($output->getStream()); - $this->assertEquals( - $this->generateOutput(' 0/50 [>---------------------------] 0%'). - $this->generateOutput(' 1/50 [>---------------------------] 2%'). - $this->generateOutput(' 15/50 [========>-------------------] 30%'). - $this->generateOutput(' 25/50 [==============>-------------] 50%'), - stream_get_contents($output->getStream()) - ); - } - - /** - * @expectedException \LogicException - * @expectedExceptionMessage You must start the progress bar - */ - public function testSetCurrentBeforeStarting() - { - $progress = new ProgressHelper(); - $progress->setCurrent(15); - } - - /** - * @expectedException \LogicException - * @expectedExceptionMessage You can't regress the progress bar - */ - public function testRegressProgress() - { - $progress = new ProgressHelper(); - $progress->start($output = $this->getOutputStream(), 50); - $progress->setCurrent(15); - $progress->setCurrent(10); - } - - public function testRedrawFrequency() - { - $progress = $this->getMock('Symfony\Component\Console\Helper\ProgressHelper', array('display')); - $progress->expects($this->exactly(4)) - ->method('display'); - - $progress->setRedrawFrequency(2); - - $progress->start($output = $this->getOutputStream(), 6); - $progress->setCurrent(1); - $progress->advance(2); - $progress->advance(2); - $progress->advance(1); - } - - public function testMultiByteSupport() - { - $progress = new ProgressHelper(); - $progress->start($output = $this->getOutputStream()); - $progress->setBarCharacter('■'); - $progress->advance(3); - - rewind($output->getStream()); - $this->assertEquals($this->generateOutput(' 3 [■■■>------------------------]'), stream_get_contents($output->getStream())); - } - - public function testClear() - { - $progress = new ProgressHelper(); - $progress->start($output = $this->getOutputStream(), 50); - $progress->setCurrent(25); - $progress->clear(); - - rewind($output->getStream()); - $this->assertEquals( - $this->generateOutput(' 25/50 [==============>-------------] 50%').$this->generateOutput(''), - stream_get_contents($output->getStream()) - ); - } - - public function testPercentNotHundredBeforeComplete() - { - $progress = new ProgressHelper(); - $progress->start($output = $this->getOutputStream(), 200); - $progress->display(); - $progress->advance(199); - $progress->advance(); - - rewind($output->getStream()); - $this->assertEquals($this->generateOutput(' 0/200 [>---------------------------] 0%').$this->generateOutput(' 199/200 [===========================>] 99%').$this->generateOutput(' 200/200 [============================] 100%'), stream_get_contents($output->getStream())); - } - - public function testNonDecoratedOutput() - { - $progress = new ProgressHelper(); - $progress->start($output = $this->getOutputStream(false)); - $progress->advance(); - - rewind($output->getStream()); - $this->assertEquals('', stream_get_contents($output->getStream())); - } - - protected function getOutputStream($decorated = true) - { - return new StreamOutput(fopen('php://memory', 'r+', false), StreamOutput::VERBOSITY_NORMAL, $decorated); - } - - protected $lastMessagesLength; - - protected function generateOutput($expected) - { - $expectedout = $expected; - - if ($this->lastMessagesLength !== null) { - $expectedout = str_pad($expected, $this->lastMessagesLength, "\x20", STR_PAD_RIGHT); - } - - $this->lastMessagesLength = strlen($expectedout); - - return "\x0D".$expectedout; - } -} diff --git a/vendor/symfony/console/Tests/Helper/LegacyTableHelperTest.php b/vendor/symfony/console/Tests/Helper/LegacyTableHelperTest.php deleted file mode 100644 index 557dc14f..00000000 --- a/vendor/symfony/console/Tests/Helper/LegacyTableHelperTest.php +++ /dev/null @@ -1,316 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Helper; - -use Symfony\Component\Console\Helper\TableHelper; -use Symfony\Component\Console\Output\StreamOutput; - -/** - * @group legacy - */ -class LegacyTableHelperTest extends \PHPUnit_Framework_TestCase -{ - protected $stream; - - protected function setUp() - { - $this->stream = fopen('php://memory', 'r+'); - } - - protected function tearDown() - { - fclose($this->stream); - $this->stream = null; - } - - /** - * @dataProvider testRenderProvider - */ - public function testRender($headers, $rows, $layout, $expected) - { - $table = new TableHelper(); - $table - ->setHeaders($headers) - ->setRows($rows) - ->setLayout($layout) - ; - $table->render($output = $this->getOutputStream()); - - $this->assertEquals($expected, $this->getOutputContent($output)); - } - - /** - * @dataProvider testRenderProvider - */ - public function testRenderAddRows($headers, $rows, $layout, $expected) - { - $table = new TableHelper(); - $table - ->setHeaders($headers) - ->addRows($rows) - ->setLayout($layout) - ; - $table->render($output = $this->getOutputStream()); - - $this->assertEquals($expected, $this->getOutputContent($output)); - } - - /** - * @dataProvider testRenderProvider - */ - public function testRenderAddRowsOneByOne($headers, $rows, $layout, $expected) - { - $table = new TableHelper(); - $table - ->setHeaders($headers) - ->setLayout($layout) - ; - foreach ($rows as $row) { - $table->addRow($row); - } - $table->render($output = $this->getOutputStream()); - - $this->assertEquals($expected, $this->getOutputContent($output)); - } - - public function testRenderProvider() - { - $books = array( - array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'), - array('9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens'), - array('960-425-059-0', 'The Lord of the Rings', 'J. R. R. Tolkien'), - array('80-902734-1-6', 'And Then There Were None', 'Agatha Christie'), - ); - - return array( - array( - array('ISBN', 'Title', 'Author'), - $books, - TableHelper::LAYOUT_DEFAULT, -<<<'TABLE' -+---------------+--------------------------+------------------+ -| ISBN | Title | Author | -+---------------+--------------------------+------------------+ -| 99921-58-10-7 | Divine Comedy | Dante Alighieri | -| 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | -| 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien | -| 80-902734-1-6 | And Then There Were None | Agatha Christie | -+---------------+--------------------------+------------------+ - -TABLE - ), - array( - array('ISBN', 'Title', 'Author'), - $books, - TableHelper::LAYOUT_COMPACT, -<<<TABLE - ISBN Title Author - 99921-58-10-7 Divine Comedy Dante Alighieri - 9971-5-0210-0 A Tale of Two Cities Charles Dickens - 960-425-059-0 The Lord of the Rings J. R. R. Tolkien - 80-902734-1-6 And Then There Were None Agatha Christie - -TABLE - ), - array( - array('ISBN', 'Title', 'Author'), - $books, - TableHelper::LAYOUT_BORDERLESS, -<<<TABLE - =============== ========================== ================== - ISBN Title Author - =============== ========================== ================== - 99921-58-10-7 Divine Comedy Dante Alighieri - 9971-5-0210-0 A Tale of Two Cities Charles Dickens - 960-425-059-0 The Lord of the Rings J. R. R. Tolkien - 80-902734-1-6 And Then There Were None Agatha Christie - =============== ========================== ================== - -TABLE - ), - array( - array('ISBN', 'Title'), - array( - array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'), - array('9971-5-0210-0'), - array('960-425-059-0', 'The Lord of the Rings', 'J. R. R. Tolkien'), - array('80-902734-1-6', 'And Then There Were None', 'Agatha Christie'), - ), - TableHelper::LAYOUT_DEFAULT, -<<<'TABLE' -+---------------+--------------------------+------------------+ -| ISBN | Title | | -+---------------+--------------------------+------------------+ -| 99921-58-10-7 | Divine Comedy | Dante Alighieri | -| 9971-5-0210-0 | | | -| 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien | -| 80-902734-1-6 | And Then There Were None | Agatha Christie | -+---------------+--------------------------+------------------+ - -TABLE - ), - array( - array(), - array( - array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'), - array('9971-5-0210-0'), - array('960-425-059-0', 'The Lord of the Rings', 'J. R. R. Tolkien'), - array('80-902734-1-6', 'And Then There Were None', 'Agatha Christie'), - ), - TableHelper::LAYOUT_DEFAULT, -<<<'TABLE' -+---------------+--------------------------+------------------+ -| 99921-58-10-7 | Divine Comedy | Dante Alighieri | -| 9971-5-0210-0 | | | -| 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien | -| 80-902734-1-6 | And Then There Were None | Agatha Christie | -+---------------+--------------------------+------------------+ - -TABLE - ), - array( - array('ISBN', 'Title', 'Author'), - array( - array('99921-58-10-7', "Divine\nComedy", 'Dante Alighieri'), - array('9971-5-0210-2', "Harry Potter\nand the Chamber of Secrets", "Rowling\nJoanne K."), - array('9971-5-0210-2', "Harry Potter\nand the Chamber of Secrets", "Rowling\nJoanne K."), - array('960-425-059-0', 'The Lord of the Rings', "J. R. R.\nTolkien"), - ), - TableHelper::LAYOUT_DEFAULT, -<<<'TABLE' -+---------------+----------------------------+-----------------+ -| ISBN | Title | Author | -+---------------+----------------------------+-----------------+ -| 99921-58-10-7 | Divine | Dante Alighieri | -| | Comedy | | -| 9971-5-0210-2 | Harry Potter | Rowling | -| | and the Chamber of Secrets | Joanne K. | -| 9971-5-0210-2 | Harry Potter | Rowling | -| | and the Chamber of Secrets | Joanne K. | -| 960-425-059-0 | The Lord of the Rings | J. R. R. | -| | | Tolkien | -+---------------+----------------------------+-----------------+ - -TABLE - ), - array( - array('ISBN', 'Title'), - array(), - TableHelper::LAYOUT_DEFAULT, -<<<'TABLE' -+------+-------+ -| ISBN | Title | -+------+-------+ - -TABLE - ), - array( - array(), - array(), - TableHelper::LAYOUT_DEFAULT, - '', - ), - 'Cell text with tags used for Output styling' => array( - array('ISBN', 'Title', 'Author'), - array( - array('<info>99921-58-10-7</info>', '<error>Divine Comedy</error>', '<fg=blue;bg=white>Dante Alighieri</fg=blue;bg=white>'), - array('9971-5-0210-0', 'A Tale of Two Cities', '<info>Charles Dickens</>'), - ), - TableHelper::LAYOUT_DEFAULT, -<<<'TABLE' -+---------------+----------------------+-----------------+ -| ISBN | Title | Author | -+---------------+----------------------+-----------------+ -| 99921-58-10-7 | Divine Comedy | Dante Alighieri | -| 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | -+---------------+----------------------+-----------------+ - -TABLE - ), - 'Cell text with tags not used for Output styling' => array( - array('ISBN', 'Title', 'Author'), - array( - array('<strong>99921-58-10-700</strong>', '<f>Divine Com</f>', 'Dante Alighieri'), - array('9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens'), - ), - TableHelper::LAYOUT_DEFAULT, -<<<'TABLE' -+----------------------------------+----------------------+-----------------+ -| ISBN | Title | Author | -+----------------------------------+----------------------+-----------------+ -| <strong>99921-58-10-700</strong> | <f>Divine Com</f> | Dante Alighieri | -| 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | -+----------------------------------+----------------------+-----------------+ - -TABLE - ), - ); - } - - public function testRenderMultiByte() - { - $table = new TableHelper(); - $table - ->setHeaders(array('■■')) - ->setRows(array(array(1234))) - ->setLayout(TableHelper::LAYOUT_DEFAULT) - ; - $table->render($output = $this->getOutputStream()); - - $expected = -<<<'TABLE' -+------+ -| ■■ | -+------+ -| 1234 | -+------+ - -TABLE; - - $this->assertEquals($expected, $this->getOutputContent($output)); - } - - public function testRenderFullWidthCharacters() - { - $table = new TableHelper(); - $table - ->setHeaders(array('あいうえお')) - ->setRows(array(array(1234567890))) - ->setLayout(TableHelper::LAYOUT_DEFAULT) - ; - $table->render($output = $this->getOutputStream()); - - $expected = - <<<'TABLE' -+------------+ -| あいうえお | -+------------+ -| 1234567890 | -+------------+ - -TABLE; - - $this->assertEquals($expected, $this->getOutputContent($output)); - } - - protected function getOutputStream() - { - return new StreamOutput($this->stream, StreamOutput::VERBOSITY_NORMAL, false); - } - - protected function getOutputContent(StreamOutput $output) - { - rewind($output->getStream()); - - return str_replace(PHP_EOL, "\n", stream_get_contents($output->getStream())); - } -} diff --git a/vendor/symfony/console/Tests/Helper/ProcessHelperTest.php b/vendor/symfony/console/Tests/Helper/ProcessHelperTest.php index a51fb435..eb619539 100644 --- a/vendor/symfony/console/Tests/Helper/ProcessHelperTest.php +++ b/vendor/symfony/console/Tests/Helper/ProcessHelperTest.php @@ -11,13 +11,14 @@ namespace Symfony\Component\Console\Tests\Helper; +use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Helper\DebugFormatterHelper; use Symfony\Component\Console\Helper\HelperSet; use Symfony\Component\Console\Output\StreamOutput; use Symfony\Component\Console\Helper\ProcessHelper; use Symfony\Component\Process\Process; -class ProcessHelperTest extends \PHPUnit_Framework_TestCase +class ProcessHelperTest extends TestCase { /** * @dataProvider provideCommandsAndOutput @@ -46,35 +47,35 @@ class ProcessHelperTest extends \PHPUnit_Framework_TestCase public function provideCommandsAndOutput() { - $successOutputVerbose = <<<EOT + $successOutputVerbose = <<<'EOT' RUN php -r "echo 42;" RES Command ran successfully EOT; - $successOutputDebug = <<<EOT + $successOutputDebug = <<<'EOT' RUN php -r "echo 42;" OUT 42 RES Command ran successfully EOT; - $successOutputDebugWithTags = <<<EOT + $successOutputDebugWithTags = <<<'EOT' RUN php -r "echo '<info>42</info>';" OUT <info>42</info> RES Command ran successfully EOT; - $successOutputProcessDebug = <<<EOT + $successOutputProcessDebug = <<<'EOT' RUN 'php' '-r' 'echo 42;' OUT 42 RES Command ran successfully EOT; - $syntaxErrorOutputVerbose = <<<EOT + $syntaxErrorOutputVerbose = <<<'EOT' RUN php -r "fwrite(STDERR, 'error message');usleep(50000);fwrite(STDOUT, 'out message');exit(252);" RES 252 Command did not run successfully EOT; - $syntaxErrorOutputDebug = <<<EOT + $syntaxErrorOutputDebug = <<<'EOT' RUN php -r "fwrite(STDERR, 'error message');usleep(500000);fwrite(STDOUT, 'out message');exit(252);" ERR error message OUT out message @@ -83,9 +84,9 @@ EOT; EOT; $errorMessage = 'An error occurred'; - if ('\\' === DIRECTORY_SEPARATOR) { - $successOutputProcessDebug = str_replace("'", '"', $successOutputProcessDebug); - } + $args = new Process(array('php', '-r', 'echo 42;')); + $args = $args->getCommandLine(); + $successOutputProcessDebug = str_replace("'php' '-r' 'echo 42;'", $args, $successOutputProcessDebug); return array( array('', 'php -r "echo 42;"', StreamOutput::VERBOSITY_VERBOSE, null), diff --git a/vendor/symfony/console/Tests/Helper/ProgressBarTest.php b/vendor/symfony/console/Tests/Helper/ProgressBarTest.php index 261908b5..aca64914 100644 --- a/vendor/symfony/console/Tests/Helper/ProgressBarTest.php +++ b/vendor/symfony/console/Tests/Helper/ProgressBarTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Console\Tests\Helper; +use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Helper\ProgressBar; use Symfony\Component\Console\Helper\Helper; use Symfony\Component\Console\Output\StreamOutput; @@ -18,7 +19,7 @@ use Symfony\Component\Console\Output\StreamOutput; /** * @group time-sensitive */ -class ProgressBarTest extends \PHPUnit_Framework_TestCase +class ProgressBarTest extends TestCase { public function testMultipleStart() { @@ -29,7 +30,7 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase rewind($output->getStream()); $this->assertEquals( - $this->generateOutput(' 0 [>---------------------------]'). + ' 0 [>---------------------------]'. $this->generateOutput(' 1 [->--------------------------]'). $this->generateOutput(' 0 [>---------------------------]'), stream_get_contents($output->getStream()) @@ -44,7 +45,7 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase rewind($output->getStream()); $this->assertEquals( - $this->generateOutput(' 0 [>---------------------------]'). + ' 0 [>---------------------------]'. $this->generateOutput(' 1 [->--------------------------]'), stream_get_contents($output->getStream()) ); @@ -58,7 +59,7 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase rewind($output->getStream()); $this->assertEquals( - $this->generateOutput(' 0 [>---------------------------]'). + ' 0 [>---------------------------]'. $this->generateOutput(' 5 [----->----------------------]'), stream_get_contents($output->getStream()) ); @@ -73,7 +74,7 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase rewind($output->getStream()); $this->assertEquals( - $this->generateOutput(' 0 [>---------------------------]'). + ' 0 [>---------------------------]'. $this->generateOutput(' 3 [--->------------------------]'). $this->generateOutput(' 5 [----->----------------------]'), stream_get_contents($output->getStream()) @@ -89,17 +90,88 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase rewind($output->getStream()); $this->assertEquals( - $this->generateOutput(' 9/10 [=========================>--] 90%'). + ' 9/10 [=========================>--] 90%'. $this->generateOutput(' 10/10 [============================] 100%'). $this->generateOutput(' 11/11 [============================] 100%'), stream_get_contents($output->getStream()) ); } + public function testRegress() + { + $bar = new ProgressBar($output = $this->getOutputStream()); + $bar->start(); + $bar->advance(); + $bar->advance(); + $bar->advance(-1); + + rewind($output->getStream()); + $this->assertEquals( + ' 0 [>---------------------------]'. + $this->generateOutput(' 1 [->--------------------------]'). + $this->generateOutput(' 2 [-->-------------------------]'). + $this->generateOutput(' 1 [->--------------------------]'), + stream_get_contents($output->getStream()) + ); + } + + public function testRegressWithStep() + { + $bar = new ProgressBar($output = $this->getOutputStream()); + $bar->start(); + $bar->advance(4); + $bar->advance(4); + $bar->advance(-2); + + rewind($output->getStream()); + $this->assertEquals( + ' 0 [>---------------------------]'. + $this->generateOutput(' 4 [---->-----------------------]'). + $this->generateOutput(' 8 [-------->-------------------]'). + $this->generateOutput(' 6 [------>---------------------]'), + stream_get_contents($output->getStream()) + ); + } + + public function testRegressMultipleTimes() + { + $bar = new ProgressBar($output = $this->getOutputStream()); + $bar->start(); + $bar->advance(3); + $bar->advance(3); + $bar->advance(-1); + $bar->advance(-2); + + rewind($output->getStream()); + $this->assertEquals( + ' 0 [>---------------------------]'. + $this->generateOutput(' 3 [--->------------------------]'). + $this->generateOutput(' 6 [------>---------------------]'). + $this->generateOutput(' 5 [----->----------------------]'). + $this->generateOutput(' 3 [--->------------------------]'), + stream_get_contents($output->getStream()) + ); + } + + public function testRegressBelowMin() + { + $bar = new ProgressBar($output = $this->getOutputStream(), 10); + $bar->setProgress(1); + $bar->advance(-1); + $bar->advance(-1); + + rewind($output->getStream()); + $this->assertEquals( + ' 1/10 [==>-------------------------] 10%'. + $this->generateOutput(' 0/10 [>---------------------------] 0%'), + stream_get_contents($output->getStream()) + ); + } + public function testFormat() { $expected = - $this->generateOutput(' 0/10 [>---------------------------] 0%'). + ' 0/10 [>---------------------------] 0%'. $this->generateOutput(' 10/10 [============================] 100%'). $this->generateOutput(' 10/10 [============================] 100%') ; @@ -156,7 +228,7 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase rewind($output->getStream()); $this->assertEquals( - $this->generateOutput(' 0/10 [/ ] 0%'). + ' 0/10 [/ ] 0%'. $this->generateOutput(' 1/10 [_/ ] 10%'), stream_get_contents($output->getStream()) ); @@ -169,7 +241,7 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase rewind($output->getStream()); $this->assertEquals( - $this->generateOutput(' 0/50 [>---------------------------] 0%'), + ' 0/50 [>---------------------------] 0%', stream_get_contents($output->getStream()) ); } @@ -193,7 +265,7 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase rewind($output->getStream()); $this->assertEquals( - $this->generateOutput(' 50/50 [============================] 100%'), + ' 50/50 [============================] 100%', stream_get_contents($output->getStream()) ); } @@ -208,7 +280,7 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase rewind($output->getStream()); $this->assertEquals( - $this->generateOutput(' 0/50 [>---------------------------] 0%'). + ' 0/50 [>---------------------------] 0%'. $this->generateOutput(' 0/50 [>---------------------------] 0%'). $this->generateOutput(' 1/50 [>---------------------------] 2%'). $this->generateOutput(' 2/50 [=>--------------------------] 4%'), @@ -230,7 +302,7 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase rewind($output->getStream()); $this->assertEquals( - $this->generateOutput(' 0/50 [>---------------------------] 0%'). + ' 0/50 [>---------------------------] 0%'. $this->generateOutput(' 0/50 [>---------------------------] 0%'). $this->generateOutput(' 1/50 [>---------------------------] 2%'). $this->generateOutput(' 2/50 [=>--------------------------]'), @@ -247,7 +319,7 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase rewind($output->getStream()); $this->assertEquals( - $this->generateOutput(' 0/50 [>---------------------------]'). + ' 0/50 [>---------------------------]'. $this->generateOutput(' 1/50 [>---------------------------]'), stream_get_contents($output->getStream()) ); @@ -264,7 +336,7 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase rewind($output->getStream()); $this->assertEquals( - $this->generateOutput(' 0/50 [>---------------------------] 0%'). + ' 0/50 [>---------------------------] 0%'. $this->generateOutput(' 0/50 [>---------------------------] 0%'). $this->generateOutput(' 1/50 [>---------------------------] 2%'). $this->generateOutput(' 15/50 [========>-------------------] 30%'). @@ -273,8 +345,6 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase ); } - /** - */ public function testSetCurrentBeforeStarting() { $bar = new ProgressBar($this->getOutputStream()); @@ -282,49 +352,54 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase $this->assertNotNull($bar->getStartTime()); } - /** - * @expectedException \LogicException - * @expectedExceptionMessage You can't regress the progress bar - */ - public function testRegressProgress() - { - $bar = new ProgressBar($output = $this->getOutputStream(), 50); - $bar->start(); - $bar->setProgress(15); - $bar->setProgress(10); - } - public function testRedrawFrequency() { - $bar = $this->getMock('Symfony\Component\Console\Helper\ProgressBar', array('display'), array($this->getOutputStream(), 6)); - $bar->expects($this->exactly(4))->method('display'); - + $bar = new ProgressBar($output = $this->getOutputStream(), 6); $bar->setRedrawFrequency(2); $bar->start(); $bar->setProgress(1); $bar->advance(2); $bar->advance(2); $bar->advance(1); + + rewind($output->getStream()); + $this->assertEquals( + ' 0/6 [>---------------------------] 0%'. + $this->generateOutput(' 3/6 [==============>-------------] 50%'). + $this->generateOutput(' 5/6 [=======================>----] 83%'). + $this->generateOutput(' 6/6 [============================] 100%'), + stream_get_contents($output->getStream()) + ); } public function testRedrawFrequencyIsAtLeastOneIfZeroGiven() { - $bar = $this->getMock('Symfony\Component\Console\Helper\ProgressBar', array('display'), array($this->getOutputStream())); - - $bar->expects($this->exactly(2))->method('display'); + $bar = new ProgressBar($output = $this->getOutputStream()); $bar->setRedrawFrequency(0); $bar->start(); $bar->advance(); + + rewind($output->getStream()); + $this->assertEquals( + ' 0 [>---------------------------]'. + $this->generateOutput(' 1 [->--------------------------]'), + stream_get_contents($output->getStream()) + ); } public function testRedrawFrequencyIsAtLeastOneIfSmallerOneGiven() { - $bar = $this->getMock('Symfony\Component\Console\Helper\ProgressBar', array('display'), array($this->getOutputStream())); - - $bar->expects($this->exactly(2))->method('display'); + $bar = new ProgressBar($output = $this->getOutputStream()); $bar->setRedrawFrequency(0.9); $bar->start(); $bar->advance(); + + rewind($output->getStream()); + $this->assertEquals( + ' 0 [>---------------------------]'. + $this->generateOutput(' 1 [->--------------------------]'), + stream_get_contents($output->getStream()) + ); } public function testMultiByteSupport() @@ -336,7 +411,7 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase rewind($output->getStream()); $this->assertEquals( - $this->generateOutput(' 0 [>---------------------------]'). + ' 0 [>---------------------------]'. $this->generateOutput(' 3 [■■■>------------------------]'), stream_get_contents($output->getStream()) ); @@ -351,7 +426,7 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase rewind($output->getStream()); $this->assertEquals( - $this->generateOutput(' 0/50 [>---------------------------] 0%'). + ' 0/50 [>---------------------------] 0%'. $this->generateOutput(' 25/50 [==============>-------------] 50%'). $this->generateOutput(''), stream_get_contents($output->getStream()) @@ -368,7 +443,7 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase rewind($output->getStream()); $this->assertEquals( - $this->generateOutput(' 0/200 [>---------------------------] 0%'). + ' 0/200 [>---------------------------] 0%'. $this->generateOutput(' 0/200 [>---------------------------] 0%'). $this->generateOutput(' 199/200 [===========================>] 99%'). $this->generateOutput(' 200/200 [============================] 100%'), @@ -468,9 +543,9 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase rewind($output->getStream()); $this->assertEquals( - $this->generateOutput(' 0/2 [>---------------------------] 0%')."\n". - $this->generateOutput(' 0/3 [#---------------------------] 0%')."\n". - rtrim($this->generateOutput(' 0 [>---------------------------]')). + ' 0/2 [>---------------------------] 0%'."\n". + ' 0/3 [#---------------------------] 0%'."\n". + rtrim(' 0 [>---------------------------]'). "\033[2A". $this->generateOutput(' 1/2 [==============>-------------] 50%')."\n". @@ -508,7 +583,7 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase rewind($output->getStream()); $this->assertEquals( - rtrim($this->generateOutput(' 0 [>---------------------------]')). + rtrim(' 0 [>---------------------------]'). rtrim($this->generateOutput(' 1 [->--------------------------]')). rtrim($this->generateOutput(' 2 [-->-------------------------]')). rtrim($this->generateOutput(' 3 [--->------------------------]')). @@ -517,6 +592,24 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase ); } + public function testWithSmallScreen() + { + $output = $this->getOutputStream(); + + $bar = new ProgressBar($output); + putenv('COLUMNS=12'); + $bar->start(); + $bar->advance(); + putenv('COLUMNS=120'); + + rewind($output->getStream()); + $this->assertEquals( + ' 0 [>---]'. + $this->generateOutput(' 1 [->--]'), + stream_get_contents($output->getStream()) + ); + } + public function testAddingPlaceholderFormatter() { ProgressBar::setPlaceholderFormatterDefinition('remaining_steps', function (ProgressBar $bar) { @@ -531,7 +624,7 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase rewind($output->getStream()); $this->assertEquals( - $this->generateOutput(' 3 [>---------------------------]'). + ' 3 [>---------------------------]'. $this->generateOutput(' 2 [=========>------------------]'). $this->generateOutput(' 0 [============================]'), stream_get_contents($output->getStream()) @@ -550,7 +643,7 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase rewind($output->getStream()); $this->assertEquals( - $this->generateOutput(">---------------------------\nfoobar"). + ">---------------------------\nfoobar". $this->generateOutput("=========>------------------\nfoobar"). "\x0D\x1B[2K\x1B[1A\x1B[2K". $this->generateOutput("============================\nfoobar"), @@ -560,6 +653,8 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase public function testAnsiColorsAndEmojis() { + putenv('COLUMNS=156'); + $bar = new ProgressBar($output = $this->getOutputStream(), 15); ProgressBar::setPlaceholderFormatterDefinition('memory', function (ProgressBar $bar) { static $i = 0; @@ -575,23 +670,37 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase $bar->setMessage('Starting the demo... fingers crossed', 'title'); $bar->start(); + + rewind($output->getStream()); + $this->assertEquals( + " \033[44;37m Starting the demo... fingers crossed \033[0m\n". + ' 0/15 '.$progress.str_repeat($empty, 26)." 0%\n". + " \xf0\x9f\x8f\x81 < 1 sec \033[44;37m 0 B \033[0m", + stream_get_contents($output->getStream()) + ); + ftruncate($output->getStream(), 0); + rewind($output->getStream()); + $bar->setMessage('Looks good to me...', 'title'); $bar->advance(4); - $bar->setMessage('Thanks, bye', 'title'); - $bar->finish(); rewind($output->getStream()); $this->assertEquals( $this->generateOutput( - " \033[44;37m Starting the demo... fingers crossed \033[0m\n". - ' 0/15 '.$progress.str_repeat($empty, 26)." 0%\n". - " \xf0\x9f\x8f\x81 < 1 sec \033[44;37m 0 B \033[0m" - ). - $this->generateOutput( " \033[44;37m Looks good to me... \033[0m\n". ' 4/15 '.str_repeat($done, 7).$progress.str_repeat($empty, 19)." 26%\n". " \xf0\x9f\x8f\x81 < 1 sec \033[41;37m 97 KiB \033[0m" - ). + ), + stream_get_contents($output->getStream()) + ); + ftruncate($output->getStream(), 0); + rewind($output->getStream()); + + $bar->setMessage('Thanks, bye', 'title'); + $bar->finish(); + + rewind($output->getStream()); + $this->assertEquals( $this->generateOutput( " \033[44;37m Thanks, bye \033[0m\n". ' 15/15 '.str_repeat($done, 28)." 100%\n". @@ -599,6 +708,7 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase ), stream_get_contents($output->getStream()) ); + putenv('COLUMNS=120'); } public function testSetFormat() @@ -608,7 +718,7 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase $bar->start(); rewind($output->getStream()); $this->assertEquals( - $this->generateOutput(' 0 [>---------------------------]'), + ' 0 [>---------------------------]', stream_get_contents($output->getStream()) ); @@ -617,7 +727,7 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase $bar->start(); rewind($output->getStream()); $this->assertEquals( - $this->generateOutput(' 0/10 [>---------------------------] 0%'), + ' 0/10 [>---------------------------] 0%', stream_get_contents($output->getStream()) ); } @@ -661,4 +771,22 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase return "\x0D\x1B[2K".($count ? str_repeat("\x1B[1A\x1B[2K", $count) : '').$expected; } + + public function testBarWidthWithMultilineFormat() + { + putenv('COLUMNS=10'); + + $bar = new ProgressBar($output = $this->getOutputStream()); + $bar->setFormat("%bar%\n0123456789"); + + // before starting + $bar->setBarWidth(5); + $this->assertEquals(5, $bar->getBarWidth()); + + // after starting + $bar->start(); + rewind($output->getStream()); + $this->assertEquals(5, $bar->getBarWidth(), stream_get_contents($output->getStream())); + putenv('COLUMNS=120'); + } } diff --git a/vendor/symfony/console/Tests/Helper/ProgressIndicatorTest.php b/vendor/symfony/console/Tests/Helper/ProgressIndicatorTest.php index 19262526..c85018de 100644 --- a/vendor/symfony/console/Tests/Helper/ProgressIndicatorTest.php +++ b/vendor/symfony/console/Tests/Helper/ProgressIndicatorTest.php @@ -2,13 +2,14 @@ namespace Symfony\Component\Console\Tests\Helper; +use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Helper\ProgressIndicator; use Symfony\Component\Console\Output\StreamOutput; /** * @group time-sensitive */ -class ProgressIndicatorTest extends \PHPUnit_Framework_TestCase +class ProgressIndicatorTest extends TestCase { public function testDefaultIndicator() { @@ -44,11 +45,11 @@ class ProgressIndicatorTest extends \PHPUnit_Framework_TestCase $this->generateOutput(' \\ Starting...'). $this->generateOutput(' \\ Advancing...'). $this->generateOutput(' | Advancing...'). - $this->generateOutput(' | Done... '). + $this->generateOutput(' | Done...'). PHP_EOL. $this->generateOutput(' - Starting Again...'). $this->generateOutput(' \\ Starting Again...'). - $this->generateOutput(' \\ Done Again... '). + $this->generateOutput(' \\ Done Again...'). PHP_EOL, stream_get_contents($output->getStream()) ); @@ -70,8 +71,8 @@ class ProgressIndicatorTest extends \PHPUnit_Framework_TestCase $this->assertEquals( ' Starting...'.PHP_EOL. - ' Midway... '.PHP_EOL. - ' Done... '.PHP_EOL.PHP_EOL, + ' Midway...'.PHP_EOL. + ' Done...'.PHP_EOL.PHP_EOL, stream_get_contents($output->getStream()) ); } @@ -177,6 +178,6 @@ class ProgressIndicatorTest extends \PHPUnit_Framework_TestCase { $count = substr_count($expected, "\n"); - return "\x0D".($count ? sprintf("\033[%dA", $count) : '').$expected; + return "\x0D\x1B[2K".($count ? sprintf("\033[%dA", $count) : '').$expected; } } diff --git a/vendor/symfony/console/Tests/Helper/QuestionHelperTest.php b/vendor/symfony/console/Tests/Helper/QuestionHelperTest.php index 6a4f8ace..9a2887a2 100644 --- a/vendor/symfony/console/Tests/Helper/QuestionHelperTest.php +++ b/vendor/symfony/console/Tests/Helper/QuestionHelperTest.php @@ -23,7 +23,7 @@ use Symfony\Component\Console\Question\Question; /** * @group tty */ -class QuestionHelperTest extends \PHPUnit_Framework_TestCase +class QuestionHelperTest extends AbstractQuestionHelperTest { public function testAskChoice() { @@ -34,22 +34,22 @@ class QuestionHelperTest extends \PHPUnit_Framework_TestCase $heroes = array('Superman', 'Batman', 'Spiderman'); - $questionHelper->setInputStream($this->getInputStream("\n1\n 1 \nFabien\n1\nFabien\n1\n0,2\n 0 , 2 \n\n\n")); + $inputStream = $this->getInputStream("\n1\n 1 \nFabien\n1\nFabien\n1\n0,2\n 0 , 2 \n\n\n"); $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, '2'); $question->setMaxAttempts(1); // first answer is an empty answer, we're supposed to receive the default value - $this->assertEquals('Spiderman', $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + $this->assertEquals('Spiderman', $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); $question = new ChoiceQuestion('What is your favorite superhero?', $heroes); $question->setMaxAttempts(1); - $this->assertEquals('Batman', $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - $this->assertEquals('Batman', $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + $this->assertEquals('Batman', $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); + $this->assertEquals('Batman', $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); $question = new ChoiceQuestion('What is your favorite superhero?', $heroes); $question->setErrorMessage('Input "%s" is not a superhero!'); $question->setMaxAttempts(2); - $this->assertEquals('Batman', $questionHelper->ask($this->createInputInterfaceMock(), $output = $this->createOutputInterface(), $question)); + $this->assertEquals('Batman', $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $output = $this->createOutputInterface(), $question)); rewind($output->getStream()); $stream = stream_get_contents($output->getStream()); @@ -58,7 +58,7 @@ class QuestionHelperTest extends \PHPUnit_Framework_TestCase try { $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, '1'); $question->setMaxAttempts(1); - $questionHelper->ask($this->createInputInterfaceMock(), $output = $this->createOutputInterface(), $question); + $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $output = $this->createOutputInterface(), $question); $this->fail(); } catch (\InvalidArgumentException $e) { $this->assertEquals('Value "Fabien" is invalid', $e->getMessage()); @@ -68,34 +68,34 @@ class QuestionHelperTest extends \PHPUnit_Framework_TestCase $question->setMaxAttempts(1); $question->setMultiselect(true); - $this->assertEquals(array('Batman'), $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - $this->assertEquals(array('Superman', 'Spiderman'), $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - $this->assertEquals(array('Superman', 'Spiderman'), $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + $this->assertEquals(array('Batman'), $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); + $this->assertEquals(array('Superman', 'Spiderman'), $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); + $this->assertEquals(array('Superman', 'Spiderman'), $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, '0,1'); $question->setMaxAttempts(1); $question->setMultiselect(true); - $this->assertEquals(array('Superman', 'Batman'), $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + $this->assertEquals(array('Superman', 'Batman'), $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, ' 0 , 1 '); $question->setMaxAttempts(1); $question->setMultiselect(true); - $this->assertEquals(array('Superman', 'Batman'), $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + $this->assertEquals(array('Superman', 'Batman'), $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); } public function testAsk() { $dialog = new QuestionHelper(); - $dialog->setInputStream($this->getInputStream("\n8AM\n")); + $inputStream = $this->getInputStream("\n8AM\n"); $question = new Question('What time is it?', '2PM'); - $this->assertEquals('2PM', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + $this->assertEquals('2PM', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); $question = new Question('What time is it?', '2PM'); - $this->assertEquals('8AM', $dialog->ask($this->createInputInterfaceMock(), $output = $this->createOutputInterface(), $question)); + $this->assertEquals('8AM', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $output = $this->createOutputInterface(), $question)); rewind($output->getStream()); $this->assertEquals('What time is it?', stream_get_contents($output->getStream())); @@ -118,21 +118,20 @@ class QuestionHelperTest extends \PHPUnit_Framework_TestCase $inputStream = $this->getInputStream("Acm\nAc\177\177s\tTest\n\n\033[A\033[A\n\033[A\033[A\033[A\033[A\033[A\tTest\n\033[B\nS\177\177\033[B\033[B\nF00\177\177oo\t\n"); $dialog = new QuestionHelper(); - $dialog->setInputStream($inputStream); $helperSet = new HelperSet(array(new FormatterHelper())); $dialog->setHelperSet($helperSet); $question = new Question('Please select a bundle', 'FrameworkBundle'); $question->setAutocompleterValues(array('AcmeDemoBundle', 'AsseticBundle', 'SecurityBundle', 'FooBundle')); - $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - $this->assertEquals('AsseticBundleTest', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - $this->assertEquals('FrameworkBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - $this->assertEquals('SecurityBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - $this->assertEquals('FooBundleTest', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - $this->assertEquals('AsseticBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - $this->assertEquals('FooBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); + $this->assertEquals('AsseticBundleTest', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); + $this->assertEquals('FrameworkBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); + $this->assertEquals('SecurityBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); + $this->assertEquals('FooBundleTest', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); + $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); + $this->assertEquals('AsseticBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); + $this->assertEquals('FooBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); } public function testAskWithAutocompleteWithNonSequentialKeys() @@ -145,14 +144,52 @@ class QuestionHelperTest extends \PHPUnit_Framework_TestCase $inputStream = $this->getInputStream("\033[A\033[A\n\033[B\033[B\n"); $dialog = new QuestionHelper(); - $dialog->setInputStream($inputStream); $dialog->setHelperSet(new HelperSet(array(new FormatterHelper()))); $question = new ChoiceQuestion('Please select a bundle', array(1 => 'AcmeDemoBundle', 4 => 'AsseticBundle')); $question->setMaxAttempts(1); - $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - $this->assertEquals('AsseticBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); + $this->assertEquals('AsseticBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); + } + + public function testAutocompleteWithTrailingBackslash() + { + if (!$this->hasSttyAvailable()) { + $this->markTestSkipped('`stty` is required to test autocomplete functionality'); + } + + $inputStream = $this->getInputStream('E'); + + $dialog = new QuestionHelper(); + $helperSet = new HelperSet(array(new FormatterHelper())); + $dialog->setHelperSet($helperSet); + + $question = new Question(''); + $expectedCompletion = 'ExampleNamespace\\'; + $question->setAutocompleterValues(array($expectedCompletion)); + + $output = $this->createOutputInterface(); + $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $output, $question); + + $outputStream = $output->getStream(); + rewind($outputStream); + $actualOutput = stream_get_contents($outputStream); + + // Shell control (esc) sequences are not so important: we only care that + // <hl> tag is interpreted correctly and replaced + $irrelevantEscSequences = array( + "\0337" => '', // Save cursor position + "\0338" => '', // Restore cursor position + "\033[K" => '', // Clear line from cursor till the end + ); + + $importantActualOutput = strtr($actualOutput, $irrelevantEscSequences); + + // Remove colors (e.g. "\033[30m", "\033[31;41m") + $importantActualOutput = preg_replace('/\033\[\d+(;\d+)?m/', '', $importantActualOutput); + + $this->assertEquals($expectedCompletion, $importantActualOutput); } public function testAskHiddenResponse() @@ -162,12 +199,11 @@ class QuestionHelperTest extends \PHPUnit_Framework_TestCase } $dialog = new QuestionHelper(); - $dialog->setInputStream($this->getInputStream("8AM\n")); $question = new Question('What time is it?'); $question->setHidden(true); - $this->assertEquals('8AM', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + $this->assertEquals('8AM', $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream("8AM\n")), $this->createOutputInterface(), $question)); } /** @@ -177,9 +213,9 @@ class QuestionHelperTest extends \PHPUnit_Framework_TestCase { $dialog = new QuestionHelper(); - $dialog->setInputStream($this->getInputStream($question."\n")); + $inputStream = $this->getInputStream($question."\n"); $question = new ConfirmationQuestion('Do you like French fries?', $default); - $this->assertEquals($expected, $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question), 'confirmation question should '.($expected ? 'pass' : 'cancel')); + $this->assertEquals($expected, $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question), 'confirmation question should '.($expected ? 'pass' : 'cancel')); } public function getAskConfirmationData() @@ -198,11 +234,11 @@ class QuestionHelperTest extends \PHPUnit_Framework_TestCase { $dialog = new QuestionHelper(); - $dialog->setInputStream($this->getInputStream("j\ny\n")); + $inputStream = $this->getInputStream("j\ny\n"); $question = new ConfirmationQuestion('Do you like French fries?', false, '/^(j|y)/i'); - $this->assertTrue($dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + $this->assertTrue($dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); $question = new ConfirmationQuestion('Do you like French fries?', false, '/^(j|y)/i'); - $this->assertTrue($dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + $this->assertTrue($dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); } public function testAskAndValidate() @@ -224,13 +260,12 @@ class QuestionHelperTest extends \PHPUnit_Framework_TestCase $question->setValidator($validator); $question->setMaxAttempts(2); - $dialog->setInputStream($this->getInputStream("\nblack\n")); - $this->assertEquals('white', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - $this->assertEquals('black', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + $inputStream = $this->getInputStream("\nblack\n"); + $this->assertEquals('white', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); + $this->assertEquals('black', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); - $dialog->setInputStream($this->getInputStream("green\nyellow\norange\n")); try { - $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question); + $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream("green\nyellow\norange\n")), $this->createOutputInterface(), $question); $this->fail(); } catch (\InvalidArgumentException $e) { $this->assertEquals($error, $e->getMessage()); @@ -249,13 +284,12 @@ class QuestionHelperTest extends \PHPUnit_Framework_TestCase ); $dialog = new QuestionHelper(); - $dialog->setInputStream($this->getInputStream($providedAnswer."\n")); $helperSet = new HelperSet(array(new FormatterHelper())); $dialog->setHelperSet($helperSet); $question = new ChoiceQuestion('Please select the environment to load', $possibleChoices); $question->setMaxAttempts(1); - $answer = $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question); + $answer = $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream($providedAnswer."\n")), $this->createOutputInterface(), $question); $this->assertSame($expectedValue, $answer); } @@ -273,6 +307,37 @@ class QuestionHelperTest extends \PHPUnit_Framework_TestCase } /** + * @dataProvider specialCharacterInMultipleChoice + */ + public function testSpecialCharacterChoiceFromMultipleChoiceList($providedAnswer, $expectedValue) + { + $possibleChoices = array( + '.', + 'src', + ); + + $dialog = new QuestionHelper(); + $inputStream = $this->getInputStream($providedAnswer."\n"); + $helperSet = new HelperSet(array(new FormatterHelper())); + $dialog->setHelperSet($helperSet); + + $question = new ChoiceQuestion('Please select the directory', $possibleChoices); + $question->setMaxAttempts(1); + $question->setMultiselect(true); + $answer = $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question); + + $this->assertSame($expectedValue, $answer); + } + + public function specialCharacterInMultipleChoice() + { + return array( + array('.', array('.')), + array('., src', array('.', 'src')), + ); + } + + /** * @dataProvider mixedKeysChoiceListAnswerProvider */ public function testChoiceFromChoicelistWithMixedKeys($providedAnswer, $expectedValue) @@ -285,13 +350,12 @@ class QuestionHelperTest extends \PHPUnit_Framework_TestCase ); $dialog = new QuestionHelper(); - $dialog->setInputStream($this->getInputStream($providedAnswer."\n")); $helperSet = new HelperSet(array(new FormatterHelper())); $dialog->setHelperSet($helperSet); $question = new ChoiceQuestion('Please select the environment to load', $possibleChoices); $question->setMaxAttempts(1); - $answer = $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question); + $answer = $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream($providedAnswer."\n")), $this->createOutputInterface(), $question); $this->assertSame($expectedValue, $answer); } @@ -320,13 +384,12 @@ class QuestionHelperTest extends \PHPUnit_Framework_TestCase ); $dialog = new QuestionHelper(); - $dialog->setInputStream($this->getInputStream($providedAnswer."\n")); $helperSet = new HelperSet(array(new FormatterHelper())); $dialog->setHelperSet($helperSet); $question = new ChoiceQuestion('Please select the environment to load', $possibleChoices); $question->setMaxAttempts(1); - $answer = $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question); + $answer = $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream($providedAnswer."\n")), $this->createOutputInterface(), $question); $this->assertSame($expectedValue, $answer); } @@ -344,14 +407,13 @@ class QuestionHelperTest extends \PHPUnit_Framework_TestCase ); $dialog = new QuestionHelper(); - $dialog->setInputStream($this->getInputStream("My environment\n")); $helperSet = new HelperSet(array(new FormatterHelper())); $dialog->setHelperSet($helperSet); $question = new ChoiceQuestion('Please select the environment to load', $possibleChoices); $question->setMaxAttempts(1); - $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question); + $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream("My environment\n")), $this->createOutputInterface(), $question); } public function answerProvider() @@ -368,7 +430,7 @@ class QuestionHelperTest extends \PHPUnit_Framework_TestCase { $dialog = new QuestionHelper(); $question = new Question('Do you have a job?', 'not yet'); - $this->assertEquals('not yet', $dialog->ask($this->createInputInterfaceMock(false), $this->createOutputInterface(), $question)); + $this->assertEquals('not yet', $dialog->ask($this->createStreamableInputInterfaceMock(null, false), $this->createOutputInterface(), $question)); } /** @@ -388,7 +450,357 @@ class QuestionHelperTest extends \PHPUnit_Framework_TestCase ' [<info>żółw </info>] bar', ' [<info>łabądź</info>] baz', ); - $output = $this->getMock('\Symfony\Component\Console\Output\OutputInterface'); + $output = $this->getMockBuilder('\Symfony\Component\Console\Output\OutputInterface')->getMock(); + $output->method('getFormatter')->willReturn(new OutputFormatter()); + + $dialog = new QuestionHelper(); + $helperSet = new HelperSet(array(new FormatterHelper())); + $dialog->setHelperSet($helperSet); + + $output->expects($this->once())->method('writeln')->with($this->equalTo($outputShown)); + + $question = new ChoiceQuestion($question, $possibleChoices, 'foo'); + $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream("\n")), $output, $question); + } + + /** + * @group legacy + */ + public function testLegacyAskChoice() + { + $questionHelper = new QuestionHelper(); + + $helperSet = new HelperSet(array(new FormatterHelper())); + $questionHelper->setHelperSet($helperSet); + + $heroes = array('Superman', 'Batman', 'Spiderman'); + + $questionHelper->setInputStream($this->getInputStream("\n1\n 1 \nFabien\n1\nFabien\n1\n0,2\n 0 , 2 \n\n\n")); + + $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, '2'); + $question->setMaxAttempts(1); + // first answer is an empty answer, we're supposed to receive the default value + $this->assertEquals('Spiderman', $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + + $question = new ChoiceQuestion('What is your favorite superhero?', $heroes); + $question->setMaxAttempts(1); + $this->assertEquals('Batman', $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + $this->assertEquals('Batman', $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + + $question = new ChoiceQuestion('What is your favorite superhero?', $heroes); + $question->setErrorMessage('Input "%s" is not a superhero!'); + $question->setMaxAttempts(2); + $this->assertEquals('Batman', $questionHelper->ask($this->createInputInterfaceMock(), $output = $this->createOutputInterface(), $question)); + + rewind($output->getStream()); + $stream = stream_get_contents($output->getStream()); + $this->assertContains('Input "Fabien" is not a superhero!', $stream); + + try { + $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, '1'); + $question->setMaxAttempts(1); + $questionHelper->ask($this->createInputInterfaceMock(), $output = $this->createOutputInterface(), $question); + $this->fail(); + } catch (\InvalidArgumentException $e) { + $this->assertEquals('Value "Fabien" is invalid', $e->getMessage()); + } + + $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, null); + $question->setMaxAttempts(1); + $question->setMultiselect(true); + + $this->assertEquals(array('Batman'), $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + $this->assertEquals(array('Superman', 'Spiderman'), $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + $this->assertEquals(array('Superman', 'Spiderman'), $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + + $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, '0,1'); + $question->setMaxAttempts(1); + $question->setMultiselect(true); + + $this->assertEquals(array('Superman', 'Batman'), $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + + $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, ' 0 , 1 '); + $question->setMaxAttempts(1); + $question->setMultiselect(true); + + $this->assertEquals(array('Superman', 'Batman'), $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + } + + /** + * @group legacy + */ + public function testLegacyAsk() + { + $dialog = new QuestionHelper(); + + $dialog->setInputStream($this->getInputStream("\n8AM\n")); + + $question = new Question('What time is it?', '2PM'); + $this->assertEquals('2PM', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + + $question = new Question('What time is it?', '2PM'); + $this->assertEquals('8AM', $dialog->ask($this->createInputInterfaceMock(), $output = $this->createOutputInterface(), $question)); + + rewind($output->getStream()); + $this->assertEquals('What time is it?', stream_get_contents($output->getStream())); + } + + /** + * @group legacy + */ + public function testLegacyAskWithAutocomplete() + { + if (!$this->hasSttyAvailable()) { + $this->markTestSkipped('`stty` is required to test autocomplete functionality'); + } + + // Acm<NEWLINE> + // Ac<BACKSPACE><BACKSPACE>s<TAB>Test<NEWLINE> + // <NEWLINE> + // <UP ARROW><UP ARROW><NEWLINE> + // <UP ARROW><UP ARROW><UP ARROW><UP ARROW><UP ARROW><TAB>Test<NEWLINE> + // <DOWN ARROW><NEWLINE> + // S<BACKSPACE><BACKSPACE><DOWN ARROW><DOWN ARROW><NEWLINE> + // F00<BACKSPACE><BACKSPACE>oo<TAB><NEWLINE> + $inputStream = $this->getInputStream("Acm\nAc\177\177s\tTest\n\n\033[A\033[A\n\033[A\033[A\033[A\033[A\033[A\tTest\n\033[B\nS\177\177\033[B\033[B\nF00\177\177oo\t\n"); + + $dialog = new QuestionHelper(); + $dialog->setInputStream($inputStream); + $helperSet = new HelperSet(array(new FormatterHelper())); + $dialog->setHelperSet($helperSet); + + $question = new Question('Please select a bundle', 'FrameworkBundle'); + $question->setAutocompleterValues(array('AcmeDemoBundle', 'AsseticBundle', 'SecurityBundle', 'FooBundle')); + + $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + $this->assertEquals('AsseticBundleTest', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + $this->assertEquals('FrameworkBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + $this->assertEquals('SecurityBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + $this->assertEquals('FooBundleTest', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + $this->assertEquals('AsseticBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + $this->assertEquals('FooBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + } + + /** + * @group legacy + */ + public function testLegacyAskWithAutocompleteWithNonSequentialKeys() + { + if (!$this->hasSttyAvailable()) { + $this->markTestSkipped('`stty` is required to test autocomplete functionality'); + } + + // <UP ARROW><UP ARROW><NEWLINE><DOWN ARROW><DOWN ARROW><NEWLINE> + $inputStream = $this->getInputStream("\033[A\033[A\n\033[B\033[B\n"); + + $dialog = new QuestionHelper(); + $dialog->setInputStream($inputStream); + $dialog->setHelperSet(new HelperSet(array(new FormatterHelper()))); + + $question = new ChoiceQuestion('Please select a bundle', array(1 => 'AcmeDemoBundle', 4 => 'AsseticBundle')); + $question->setMaxAttempts(1); + + $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + $this->assertEquals('AsseticBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + } + + /** + * @group legacy + */ + public function testLegacyAskHiddenResponse() + { + if ('\\' === DIRECTORY_SEPARATOR) { + $this->markTestSkipped('This test is not supported on Windows'); + } + + $dialog = new QuestionHelper(); + $dialog->setInputStream($this->getInputStream("8AM\n")); + + $question = new Question('What time is it?'); + $question->setHidden(true); + + $this->assertEquals('8AM', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + } + + /** + * @group legacy + * @dataProvider getAskConfirmationData + */ + public function testLegacyAskConfirmation($question, $expected, $default = true) + { + $dialog = new QuestionHelper(); + + $dialog->setInputStream($this->getInputStream($question."\n")); + $question = new ConfirmationQuestion('Do you like French fries?', $default); + $this->assertEquals($expected, $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question), 'confirmation question should '.($expected ? 'pass' : 'cancel')); + } + + /** + * @group legacy + */ + public function testLegacyAskConfirmationWithCustomTrueAnswer() + { + $dialog = new QuestionHelper(); + + $dialog->setInputStream($this->getInputStream("j\ny\n")); + $question = new ConfirmationQuestion('Do you like French fries?', false, '/^(j|y)/i'); + $this->assertTrue($dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + $question = new ConfirmationQuestion('Do you like French fries?', false, '/^(j|y)/i'); + $this->assertTrue($dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + } + + /** + * @group legacy + */ + public function testLegacyAskAndValidate() + { + $dialog = new QuestionHelper(); + $helperSet = new HelperSet(array(new FormatterHelper())); + $dialog->setHelperSet($helperSet); + + $error = 'This is not a color!'; + $validator = function ($color) use ($error) { + if (!in_array($color, array('white', 'black'))) { + throw new \InvalidArgumentException($error); + } + + return $color; + }; + + $question = new Question('What color was the white horse of Henry IV?', 'white'); + $question->setValidator($validator); + $question->setMaxAttempts(2); + + $dialog->setInputStream($this->getInputStream("\nblack\n")); + $this->assertEquals('white', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + $this->assertEquals('black', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); + + $dialog->setInputStream($this->getInputStream("green\nyellow\norange\n")); + try { + $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question); + $this->fail(); + } catch (\InvalidArgumentException $e) { + $this->assertEquals($error, $e->getMessage()); + } + } + + /** + * @group legacy + * @dataProvider simpleAnswerProvider + */ + public function testLegacySelectChoiceFromSimpleChoices($providedAnswer, $expectedValue) + { + $possibleChoices = array( + 'My environment 1', + 'My environment 2', + 'My environment 3', + ); + + $dialog = new QuestionHelper(); + $dialog->setInputStream($this->getInputStream($providedAnswer."\n")); + $helperSet = new HelperSet(array(new FormatterHelper())); + $dialog->setHelperSet($helperSet); + + $question = new ChoiceQuestion('Please select the environment to load', $possibleChoices); + $question->setMaxAttempts(1); + $answer = $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question); + + $this->assertSame($expectedValue, $answer); + } + + /** + * @group legacy + * @dataProvider mixedKeysChoiceListAnswerProvider + */ + public function testLegacyChoiceFromChoicelistWithMixedKeys($providedAnswer, $expectedValue) + { + $possibleChoices = array( + '0' => 'No environment', + '1' => 'My environment 1', + 'env_2' => 'My environment 2', + 3 => 'My environment 3', + ); + + $dialog = new QuestionHelper(); + $dialog->setInputStream($this->getInputStream($providedAnswer."\n")); + $helperSet = new HelperSet(array(new FormatterHelper())); + $dialog->setHelperSet($helperSet); + + $question = new ChoiceQuestion('Please select the environment to load', $possibleChoices); + $question->setMaxAttempts(1); + $answer = $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question); + + $this->assertSame($expectedValue, $answer); + } + + /** + * @group legacy + * @dataProvider answerProvider + */ + public function testLegacySelectChoiceFromChoiceList($providedAnswer, $expectedValue) + { + $possibleChoices = array( + 'env_1' => 'My environment 1', + 'env_2' => 'My environment', + 'env_3' => 'My environment', + ); + + $dialog = new QuestionHelper(); + $dialog->setInputStream($this->getInputStream($providedAnswer."\n")); + $helperSet = new HelperSet(array(new FormatterHelper())); + $dialog->setHelperSet($helperSet); + + $question = new ChoiceQuestion('Please select the environment to load', $possibleChoices); + $question->setMaxAttempts(1); + $answer = $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question); + + $this->assertSame($expectedValue, $answer); + } + + /** + * @group legacy + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage The provided answer is ambiguous. Value should be one of env_2 or env_3. + */ + public function testLegacyAmbiguousChoiceFromChoicelist() + { + $possibleChoices = array( + 'env_1' => 'My first environment', + 'env_2' => 'My environment', + 'env_3' => 'My environment', + ); + + $dialog = new QuestionHelper(); + $dialog->setInputStream($this->getInputStream("My environment\n")); + $helperSet = new HelperSet(array(new FormatterHelper())); + $dialog->setHelperSet($helperSet); + + $question = new ChoiceQuestion('Please select the environment to load', $possibleChoices); + $question->setMaxAttempts(1); + + $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question); + } + + /** + * @requires function mb_strwidth + * @group legacy + */ + public function testLegacyChoiceOutputFormattingQuestionForUtf8Keys() + { + $question = 'Lorem ipsum?'; + $possibleChoices = array( + 'foo' => 'foo', + 'żółw' => 'bar', + 'łabądź' => 'baz', + ); + $outputShown = array( + $question, + ' [<info>foo </info>] foo', + ' [<info>żółw </info>] bar', + ' [<info>łabądź</info>] baz', + ); + $output = $this->getMockBuilder('\Symfony\Component\Console\Output\OutputInterface')->getMock(); $output->method('getFormatter')->willReturn(new OutputFormatter()); $dialog = new QuestionHelper(); @@ -402,6 +814,76 @@ class QuestionHelperTest extends \PHPUnit_Framework_TestCase $dialog->ask($this->createInputInterfaceMock(), $output, $question); } + /** + * @expectedException \Symfony\Component\Console\Exception\RuntimeException + * @expectedExceptionMessage Aborted + */ + public function testAskThrowsExceptionOnMissingInput() + { + $dialog = new QuestionHelper(); + $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream('')), $this->createOutputInterface(), new Question('What\'s your name?')); + } + + /** + * @expectedException \Symfony\Component\Console\Exception\RuntimeException + * @expectedExceptionMessage Aborted + */ + public function testAskThrowsExceptionOnMissingInputWithValidator() + { + $dialog = new QuestionHelper(); + + $question = new Question('What\'s your name?'); + $question->setValidator(function () { + if (!$value) { + throw new \Exception('A value is required.'); + } + }); + + $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream('')), $this->createOutputInterface(), $question); + } + + /** + * @expectedException \LogicException + * @expectedExceptionMessage Choice question must have at least 1 choice available. + */ + public function testEmptyChoices() + { + new ChoiceQuestion('Question', array(), 'irrelevant'); + } + + public function testTraversableAutocomplete() + { + if (!$this->hasSttyAvailable()) { + $this->markTestSkipped('`stty` is required to test autocomplete functionality'); + } + + // Acm<NEWLINE> + // Ac<BACKSPACE><BACKSPACE>s<TAB>Test<NEWLINE> + // <NEWLINE> + // <UP ARROW><UP ARROW><NEWLINE> + // <UP ARROW><UP ARROW><UP ARROW><UP ARROW><UP ARROW><TAB>Test<NEWLINE> + // <DOWN ARROW><NEWLINE> + // S<BACKSPACE><BACKSPACE><DOWN ARROW><DOWN ARROW><NEWLINE> + // F00<BACKSPACE><BACKSPACE>oo<TAB><NEWLINE> + $inputStream = $this->getInputStream("Acm\nAc\177\177s\tTest\n\n\033[A\033[A\n\033[A\033[A\033[A\033[A\033[A\tTest\n\033[B\nS\177\177\033[B\033[B\nF00\177\177oo\t\n"); + + $dialog = new QuestionHelper(); + $helperSet = new HelperSet(array(new FormatterHelper())); + $dialog->setHelperSet($helperSet); + + $question = new Question('Please select a bundle', 'FrameworkBundle'); + $question->setAutocompleterValues(new AutocompleteValues(array('irrelevant' => 'AcmeDemoBundle', 'AsseticBundle', 'SecurityBundle', 'FooBundle'))); + + $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); + $this->assertEquals('AsseticBundleTest', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); + $this->assertEquals('FrameworkBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); + $this->assertEquals('SecurityBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); + $this->assertEquals('FooBundleTest', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); + $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); + $this->assertEquals('AsseticBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); + $this->assertEquals('FooBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); + } + protected function getInputStream($input) { $stream = fopen('php://memory', 'r+', false); @@ -418,7 +900,7 @@ class QuestionHelperTest extends \PHPUnit_Framework_TestCase protected function createInputInterfaceMock($interactive = true) { - $mock = $this->getMock('Symfony\Component\Console\Input\InputInterface'); + $mock = $this->getMockBuilder('Symfony\Component\Console\Input\InputInterface')->getMock(); $mock->expects($this->any()) ->method('isInteractive') ->will($this->returnValue($interactive)); @@ -430,6 +912,21 @@ class QuestionHelperTest extends \PHPUnit_Framework_TestCase { exec('stty 2>&1', $output, $exitcode); - return $exitcode === 0; + return 0 === $exitcode; + } +} + +class AutocompleteValues implements \IteratorAggregate +{ + private $values; + + public function __construct(array $values) + { + $this->values = $values; + } + + public function getIterator() + { + return new \ArrayIterator($this->values); } } diff --git a/vendor/symfony/console/Tests/Helper/SymfonyQuestionHelperTest.php b/vendor/symfony/console/Tests/Helper/SymfonyQuestionHelperTest.php new file mode 100644 index 00000000..ce946e5b --- /dev/null +++ b/vendor/symfony/console/Tests/Helper/SymfonyQuestionHelperTest.php @@ -0,0 +1,156 @@ +<?php + +namespace Symfony\Component\Console\Tests\Helper; + +use Symfony\Component\Console\Helper\FormatterHelper; +use Symfony\Component\Console\Helper\HelperSet; +use Symfony\Component\Console\Helper\SymfonyQuestionHelper; +use Symfony\Component\Console\Output\StreamOutput; +use Symfony\Component\Console\Question\Question; +use Symfony\Component\Console\Question\ChoiceQuestion; + +/** + * @group tty + */ +class SymfonyQuestionHelperTest extends AbstractQuestionHelperTest +{ + public function testAskChoice() + { + $questionHelper = new SymfonyQuestionHelper(); + + $helperSet = new HelperSet(array(new FormatterHelper())); + $questionHelper->setHelperSet($helperSet); + + $heroes = array('Superman', 'Batman', 'Spiderman'); + + $inputStream = $this->getInputStream("\n1\n 1 \nFabien\n1\nFabien\n1\n0,2\n 0 , 2 \n\n\n"); + + $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, '2'); + $question->setMaxAttempts(1); + // first answer is an empty answer, we're supposed to receive the default value + $this->assertEquals('Spiderman', $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $output = $this->createOutputInterface(), $question)); + $this->assertOutputContains('What is your favorite superhero? [Spiderman]', $output); + + $question = new ChoiceQuestion('What is your favorite superhero?', $heroes); + $question->setMaxAttempts(1); + $this->assertEquals('Batman', $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); + $this->assertEquals('Batman', $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); + + $question = new ChoiceQuestion('What is your favorite superhero?', $heroes); + $question->setErrorMessage('Input "%s" is not a superhero!'); + $question->setMaxAttempts(2); + $this->assertEquals('Batman', $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $output = $this->createOutputInterface(), $question)); + $this->assertOutputContains('Input "Fabien" is not a superhero!', $output); + + try { + $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, '1'); + $question->setMaxAttempts(1); + $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $output = $this->createOutputInterface(), $question); + $this->fail(); + } catch (\InvalidArgumentException $e) { + $this->assertEquals('Value "Fabien" is invalid', $e->getMessage()); + } + + $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, null); + $question->setMaxAttempts(1); + $question->setMultiselect(true); + + $this->assertEquals(array('Batman'), $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); + $this->assertEquals(array('Superman', 'Spiderman'), $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); + $this->assertEquals(array('Superman', 'Spiderman'), $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); + + $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, '0,1'); + $question->setMaxAttempts(1); + $question->setMultiselect(true); + + $this->assertEquals(array('Superman', 'Batman'), $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $output = $this->createOutputInterface(), $question)); + $this->assertOutputContains('What is your favorite superhero? [Superman, Batman]', $output); + + $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, ' 0 , 1 '); + $question->setMaxAttempts(1); + $question->setMultiselect(true); + + $this->assertEquals(array('Superman', 'Batman'), $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $output = $this->createOutputInterface(), $question)); + $this->assertOutputContains('What is your favorite superhero? [Superman, Batman]', $output); + } + + public function testAskReturnsNullIfValidatorAllowsIt() + { + $questionHelper = new SymfonyQuestionHelper(); + $question = new Question('What is your favorite superhero?'); + $question->setValidator(function ($value) { return $value; }); + $input = $this->createStreamableInputInterfaceMock($this->getInputStream("\n")); + $this->assertNull($questionHelper->ask($input, $this->createOutputInterface(), $question)); + } + + public function testAskEscapeDefaultValue() + { + $helper = new SymfonyQuestionHelper(); + $input = $this->createStreamableInputInterfaceMock($this->getInputStream('\\')); + $helper->ask($input, $output = $this->createOutputInterface(), new Question('Can I have a backslash?', '\\')); + + $this->assertOutputContains('Can I have a backslash? [\]', $output); + } + + public function testAskEscapeAndFormatLabel() + { + $helper = new SymfonyQuestionHelper(); + $input = $this->createStreamableInputInterfaceMock($this->getInputStream('Foo\\Bar')); + $helper->ask($input, $output = $this->createOutputInterface(), new Question('Do you want to use Foo\\Bar <comment>or</comment> Foo\\Baz\\?', 'Foo\\Baz')); + + $this->assertOutputContains('Do you want to use Foo\\Bar or Foo\\Baz\\? [Foo\\Baz]:', $output); + } + + public function testLabelTrailingBackslash() + { + $helper = new SymfonyQuestionHelper(); + $input = $this->createStreamableInputInterfaceMock($this->getInputStream('sure')); + $helper->ask($input, $output = $this->createOutputInterface(), new Question('Question with a trailing \\')); + + $this->assertOutputContains('Question with a trailing \\', $output); + } + + /** + * @expectedException \Symfony\Component\Console\Exception\RuntimeException + * @expectedExceptionMessage Aborted + */ + public function testAskThrowsExceptionOnMissingInput() + { + $dialog = new SymfonyQuestionHelper(); + $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream('')), $this->createOutputInterface(), new Question('What\'s your name?')); + } + + protected function getInputStream($input) + { + $stream = fopen('php://memory', 'r+', false); + fwrite($stream, $input); + rewind($stream); + + return $stream; + } + + protected function createOutputInterface() + { + $output = new StreamOutput(fopen('php://memory', 'r+', false)); + $output->setDecorated(false); + + return $output; + } + + protected function createInputInterfaceMock($interactive = true) + { + $mock = $this->getMockBuilder('Symfony\Component\Console\Input\InputInterface')->getMock(); + $mock->expects($this->any()) + ->method('isInteractive') + ->will($this->returnValue($interactive)); + + return $mock; + } + + private function assertOutputContains($expected, StreamOutput $output) + { + rewind($output->getStream()); + $stream = stream_get_contents($output->getStream()); + $this->assertContains($expected, $stream); + } +} diff --git a/vendor/symfony/console/Tests/Helper/TableStyleTest.php b/vendor/symfony/console/Tests/Helper/TableStyleTest.php index 587d8414..13e918b3 100644 --- a/vendor/symfony/console/Tests/Helper/TableStyleTest.php +++ b/vendor/symfony/console/Tests/Helper/TableStyleTest.php @@ -11,9 +11,10 @@ namespace Symfony\Component\Console\Tests\Helper; +use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Helper\TableStyle; -class TableStyleTest extends \PHPUnit_Framework_TestCase +class TableStyleTest extends TestCase { /** * @expectedException \InvalidArgumentException diff --git a/vendor/symfony/console/Tests/Helper/TableTest.php b/vendor/symfony/console/Tests/Helper/TableTest.php index 9ecb381a..d8a8ff00 100644 --- a/vendor/symfony/console/Tests/Helper/TableTest.php +++ b/vendor/symfony/console/Tests/Helper/TableTest.php @@ -11,13 +11,14 @@ namespace Symfony\Component\Console\Tests\Helper; +use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Helper\Table; use Symfony\Component\Console\Helper\TableStyle; use Symfony\Component\Console\Helper\TableSeparator; use Symfony\Component\Console\Helper\TableCell; use Symfony\Component\Console\Output\StreamOutput; -class TableTest extends \PHPUnit_Framework_TestCase +class TableTest extends TestCase { protected $stream; @@ -33,11 +34,11 @@ class TableTest extends \PHPUnit_Framework_TestCase } /** - * @dataProvider testRenderProvider + * @dataProvider renderProvider */ - public function testRender($headers, $rows, $style, $expected) + public function testRender($headers, $rows, $style, $expected, $decorated = false) { - $table = new Table($output = $this->getOutputStream()); + $table = new Table($output = $this->getOutputStream($decorated)); $table ->setHeaders($headers) ->setRows($rows) @@ -49,11 +50,11 @@ class TableTest extends \PHPUnit_Framework_TestCase } /** - * @dataProvider testRenderProvider + * @dataProvider renderProvider */ - public function testRenderAddRows($headers, $rows, $style, $expected) + public function testRenderAddRows($headers, $rows, $style, $expected, $decorated = false) { - $table = new Table($output = $this->getOutputStream()); + $table = new Table($output = $this->getOutputStream($decorated)); $table ->setHeaders($headers) ->addRows($rows) @@ -65,11 +66,11 @@ class TableTest extends \PHPUnit_Framework_TestCase } /** - * @dataProvider testRenderProvider + * @dataProvider renderProvider */ - public function testRenderAddRowsOneByOne($headers, $rows, $style, $expected) + public function testRenderAddRowsOneByOne($headers, $rows, $style, $expected, $decorated = false) { - $table = new Table($output = $this->getOutputStream()); + $table = new Table($output = $this->getOutputStream($decorated)); $table ->setHeaders($headers) ->setStyle($style) @@ -82,7 +83,7 @@ class TableTest extends \PHPUnit_Framework_TestCase $this->assertEquals($expected, $this->getOutputContent($output)); } - public function testRenderProvider() + public function renderProvider() { $books = array( array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'), @@ -96,7 +97,7 @@ class TableTest extends \PHPUnit_Framework_TestCase array('ISBN', 'Title', 'Author'), $books, 'default', -<<<TABLE +<<<'TABLE' +---------------+--------------------------+------------------+ | ISBN | Title | Author | +---------------+--------------------------+------------------+ @@ -112,7 +113,7 @@ TABLE array('ISBN', 'Title', 'Author'), $books, 'compact', -<<<TABLE +<<<'TABLE' ISBN Title Author 99921-58-10-7 Divine Comedy Dante Alighieri 9971-5-0210-0 A Tale of Two Cities Charles Dickens @@ -125,7 +126,7 @@ TABLE array('ISBN', 'Title', 'Author'), $books, 'borderless', -<<<TABLE +<<<'TABLE' =============== ========================== ================== ISBN Title Author =============== ========================== ================== @@ -146,7 +147,7 @@ TABLE array('80-902734-1-6', 'And Then There Were None', 'Agatha Christie'), ), 'default', -<<<TABLE +<<<'TABLE' +---------------+--------------------------+------------------+ | ISBN | Title | | +---------------+--------------------------+------------------+ @@ -167,7 +168,7 @@ TABLE array('80-902734-1-6', 'And Then There Were None', 'Agatha Christie'), ), 'default', -<<<TABLE +<<<'TABLE' +---------------+--------------------------+------------------+ | 99921-58-10-7 | Divine Comedy | Dante Alighieri | | 9971-5-0210-0 | | | @@ -186,7 +187,7 @@ TABLE array('960-425-059-0', 'The Lord of the Rings', "J. R. R.\nTolkien"), ), 'default', -<<<TABLE +<<<'TABLE' +---------------+----------------------------+-----------------+ | ISBN | Title | Author | +---------------+----------------------------+-----------------+ @@ -206,7 +207,7 @@ TABLE array('ISBN', 'Title'), array(), 'default', -<<<TABLE +<<<'TABLE' +------+-------+ | ISBN | Title | +------+-------+ @@ -226,7 +227,7 @@ TABLE array('9971-5-0210-0', 'A Tale of Two Cities', '<info>Charles Dickens</>'), ), 'default', -<<<TABLE +<<<'TABLE' +---------------+----------------------+-----------------+ | ISBN | Title | Author | +---------------+----------------------+-----------------+ @@ -243,7 +244,7 @@ TABLE array('9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens'), ), 'default', -<<<TABLE +<<<'TABLE' +----------------------------------+----------------------+-----------------+ | ISBN | Title | Author | +----------------------------------+----------------------+-----------------+ @@ -275,7 +276,7 @@ TABLE ), ), 'default', -<<<TABLE +<<<'TABLE' +-------------------------------+-------------------------------+-----------------------------+ | ISBN | Title | Author | +-------------------------------+-------------------------------+-----------------------------+ @@ -298,29 +299,29 @@ TABLE array( array( new TableCell('9971-5-0210-0', array('rowspan' => 3)), - 'Divine Comedy', + new TableCell('Divine Comedy', array('rowspan' => 2)), 'Dante Alighieri', ), - array('A Tale of Two Cities', 'Charles Dickens'), + array(), array("The Lord of \nthe Rings", "J. R. \nR. Tolkien"), new TableSeparator(), array('80-902734-1-6', new TableCell("And Then \nThere \nWere None", array('rowspan' => 3)), 'Agatha Christie'), array('80-902734-1-7', 'Test'), ), 'default', -<<<TABLE -+---------------+----------------------+-----------------+ -| ISBN | Title | Author | -+---------------+----------------------+-----------------+ -| 9971-5-0210-0 | Divine Comedy | Dante Alighieri | -| | A Tale of Two Cities | Charles Dickens | -| | The Lord of | J. R. | -| | the Rings | R. Tolkien | -+---------------+----------------------+-----------------+ -| 80-902734-1-6 | And Then | Agatha Christie | -| 80-902734-1-7 | There | Test | -| | Were None | | -+---------------+----------------------+-----------------+ +<<<'TABLE' ++---------------+---------------+-----------------+ +| ISBN | Title | Author | ++---------------+---------------+-----------------+ +| 9971-5-0210-0 | Divine Comedy | Dante Alighieri | +| | | | +| | The Lord of | J. R. | +| | the Rings | R. Tolkien | ++---------------+---------------+-----------------+ +| 80-902734-1-6 | And Then | Agatha Christie | +| 80-902734-1-7 | There | Test | +| | Were None | | ++---------------+---------------+-----------------+ TABLE ), @@ -341,7 +342,7 @@ TABLE array('J. R. R'), ), 'default', -<<<TABLE +<<<'TABLE' +------------------+---------+-----------------+ | ISBN | Title | Author | +------------------+---------+-----------------+ @@ -376,7 +377,7 @@ TABLE ), ), 'default', -<<<TABLE +<<<'TABLE' +-----------------+-------+-----------------+ | ISBN | Title | Author | +-----------------+-------+-----------------+ @@ -413,7 +414,7 @@ TABLE array('Charles Dickens'), ), 'default', -<<<TABLE +<<<'TABLE' +-----------------+-------+-----------------+ | ISBN | Title | Author | +-----------------+-------+-----------------+ @@ -440,7 +441,7 @@ TABLE array('Charles Dickens'), ), 'default', -<<<TABLE +<<<'TABLE' +---------------+-----------------+ | ISBN | Author | +---------------+-----------------+ @@ -458,7 +459,7 @@ TABLE ), array(), 'default', -<<<TABLE +<<<'TABLE' +------+-------+--------+ | Main title | +------+-------+--------+ @@ -478,13 +479,71 @@ TABLE ), ), 'default', -<<<TABLE +<<<'TABLE' +---+--+--+---+--+---+--+---+--+ | 1 | 2 | 3 | 4 | +---+--+--+---+--+---+--+---+--+ TABLE ), + 'Coslpan and table cells with comment style' => array( + array( + new TableCell('<comment>Long Title</comment>', array('colspan' => 3)), + ), + array( + array( + new TableCell('9971-5-0210-0', array('colspan' => 3)), + ), + new TableSeparator(), + array( + 'Dante Alighieri', + 'J. R. R. Tolkien', + 'J. R. R', + ), + ), + 'default', + <<<TABLE ++-----------------+------------------+---------+ +|\033[32m \033[39m\033[33mLong Title\033[39m\033[32m \033[39m| ++-----------------+------------------+---------+ +| 9971-5-0210-0 | ++-----------------+------------------+---------+ +| Dante Alighieri | J. R. R. Tolkien | J. R. R | ++-----------------+------------------+---------+ + +TABLE + , + true, + ), + 'Row with formatted cells containing a newline' => array( + array(), + array( + array( + new TableCell('<error>Dont break'."\n".'here</error>', array('colspan' => 2)), + ), + new TableSeparator(), + array( + 'foo', + new TableCell('<error>Dont break'."\n".'here</error>', array('rowspan' => 2)), + ), + array( + 'bar', + ), + ), + 'default', + <<<'TABLE' ++-------+------------+ +[39;49m| [39;49m[37;41mDont break[39;49m[39;49m |[39;49m +[39;49m| [39;49m[37;41mhere[39;49m | ++-------+------------+ +[39;49m| foo | [39;49m[37;41mDont break[39;49m[39;49m |[39;49m +[39;49m| bar | [39;49m[37;41mhere[39;49m | ++-------+------------+ + +TABLE + , + true, + ), ); } @@ -499,7 +558,7 @@ TABLE $table->render(); $expected = -<<<TABLE +<<<'TABLE' +------+ | ■■ | +------+ @@ -511,6 +570,42 @@ TABLE; $this->assertEquals($expected, $this->getOutputContent($output)); } + public function testTableCellWithNumericIntValue() + { + $table = new Table($output = $this->getOutputStream()); + + $table->setRows(array(array(new TableCell(12345)))); + $table->render(); + + $expected = +<<<'TABLE' ++-------+ +| 12345 | ++-------+ + +TABLE; + + $this->assertEquals($expected, $this->getOutputContent($output)); + } + + public function testTableCellWithNumericFloatValue() + { + $table = new Table($output = $this->getOutputStream()); + + $table->setRows(array(array(new TableCell(12345.01)))); + $table->render(); + + $expected = +<<<'TABLE' ++----------+ +| 12345.01 | ++----------+ + +TABLE; + + $this->assertEquals($expected, $this->getOutputContent($output)); + } + public function testStyle() { $style = new TableStyle(); @@ -529,7 +624,7 @@ TABLE; $table->render(); $expected = -<<<TABLE +<<<'TABLE' ....... . Foo . ....... @@ -556,7 +651,7 @@ TABLE; $table->render(); $expected = -<<<TABLE +<<<'TABLE' +------+ | Foo | +------+ @@ -631,9 +726,91 @@ TABLE; $this->assertEquals($expected, $this->getOutputContent($output)); } - protected function getOutputStream() + public function testColumnWith() + { + $table = new Table($output = $this->getOutputStream()); + $table + ->setHeaders(array('ISBN', 'Title', 'Author', 'Price')) + ->setRows(array( + array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri', '9.95'), + array('9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens', '139.25'), + )) + ->setColumnWidth(0, 15) + ->setColumnWidth(3, 10); + + $style = new TableStyle(); + $style->setPadType(STR_PAD_LEFT); + $table->setColumnStyle(3, $style); + + $table->render(); + + $expected = + <<<TABLE ++-----------------+----------------------+-----------------+------------+ +| ISBN | Title | Author | Price | ++-----------------+----------------------+-----------------+------------+ +| 99921-58-10-7 | Divine Comedy | Dante Alighieri | 9.95 | +| 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | 139.25 | ++-----------------+----------------------+-----------------+------------+ + +TABLE; + + $this->assertEquals($expected, $this->getOutputContent($output)); + } + + public function testColumnWiths() + { + $table = new Table($output = $this->getOutputStream()); + $table + ->setHeaders(array('ISBN', 'Title', 'Author', 'Price')) + ->setRows(array( + array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri', '9.95'), + array('9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens', '139.25'), + )) + ->setColumnWidths(array(15, 0, -1, 10)); + + $style = new TableStyle(); + $style->setPadType(STR_PAD_LEFT); + $table->setColumnStyle(3, $style); + + $table->render(); + + $expected = + <<<TABLE ++-----------------+----------------------+-----------------+------------+ +| ISBN | Title | Author | Price | ++-----------------+----------------------+-----------------+------------+ +| 99921-58-10-7 | Divine Comedy | Dante Alighieri | 9.95 | +| 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | 139.25 | ++-----------------+----------------------+-----------------+------------+ + +TABLE; + + $this->assertEquals($expected, $this->getOutputContent($output)); + } + + /** + * @expectedException \Symfony\Component\Console\Exception\InvalidArgumentException + * @expectedExceptionMessage Style "absent" is not defined. + */ + public function testIsNotDefinedStyleException() + { + $table = new Table($this->getOutputStream()); + $table->setStyle('absent'); + } + + /** + * @expectedException \Symfony\Component\Console\Exception\InvalidArgumentException + * @expectedExceptionMessage Style "absent" is not defined. + */ + public function testGetStyleDefinition() + { + Table::getStyleDefinition('absent'); + } + + protected function getOutputStream($decorated = false) { - return new StreamOutput($this->stream, StreamOutput::VERBOSITY_NORMAL, false); + return new StreamOutput($this->stream, StreamOutput::VERBOSITY_NORMAL, $decorated); } protected function getOutputContent(StreamOutput $output) diff --git a/vendor/symfony/console/Tests/Input/ArgvInputTest.php b/vendor/symfony/console/Tests/Input/ArgvInputTest.php index d2c540e6..01d6e4b9 100644 --- a/vendor/symfony/console/Tests/Input/ArgvInputTest.php +++ b/vendor/symfony/console/Tests/Input/ArgvInputTest.php @@ -11,12 +11,13 @@ namespace Symfony\Component\Console\Tests\Input; +use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Input\ArgvInput; use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; -class ArgvInputTest extends \PHPUnit_Framework_TestCase +class ArgvInputTest extends TestCase { public function testConstructor() { @@ -47,7 +48,7 @@ class ArgvInputTest extends \PHPUnit_Framework_TestCase $input = new ArgvInput($input); $input->bind(new InputDefinition($options)); - $this->assertEquals($expectedOptions, $input->getOptions(), $message); + $this->assertSame($expectedOptions, $input->getOptions(), $message); } public function provideOptions() @@ -72,6 +73,36 @@ class ArgvInputTest extends \PHPUnit_Framework_TestCase '->parse() parses long options with a required value (with a space separator)', ), array( + array('cli.php', '--foo='), + array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL)), + array('foo' => ''), + '->parse() parses long options with optional value which is empty (with a = separator) as empty string', + ), + array( + array('cli.php', '--foo=', 'bar'), + array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputArgument('name', InputArgument::REQUIRED)), + array('foo' => ''), + '->parse() parses long options with optional value without value specified or an empty string (with a = separator) followed by an argument as empty string', + ), + array( + array('cli.php', 'bar', '--foo'), + array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputArgument('name', InputArgument::REQUIRED)), + array('foo' => null), + '->parse() parses long options with optional value which is empty (with a = separator) preceded by an argument', + ), + array( + array('cli.php', '--foo', '', 'bar'), + array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputArgument('name', InputArgument::REQUIRED)), + array('foo' => ''), + '->parse() parses long options with optional value which is empty as empty string even followed by an argument', + ), + array( + array('cli.php', '--foo'), + array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL)), + array('foo' => null), + '->parse() parses long options with optional value specified with no separator and no value as null', + ), + array( array('cli.php', '-f'), array(new InputOption('foo', 'f')), array('foo' => true), @@ -151,7 +182,12 @@ class ArgvInputTest extends \PHPUnit_Framework_TestCase */ public function testInvalidInput($argv, $definition, $expectedExceptionMessage) { - $this->setExpectedException('RuntimeException', $expectedExceptionMessage); + if (method_exists($this, 'expectException')) { + $this->expectException('RuntimeException'); + $this->expectExceptionMessage($expectedExceptionMessage); + } else { + $this->setExpectedException('RuntimeException', $expectedExceptionMessage); + } $input = new ArgvInput($argv); $input->bind($definition); @@ -183,7 +219,17 @@ class ArgvInputTest extends \PHPUnit_Framework_TestCase array( array('cli.php', 'foo', 'bar'), new InputDefinition(), - 'Too many arguments.', + 'No arguments expected, got "foo".', + ), + array( + array('cli.php', 'foo', 'bar'), + new InputDefinition(array(new InputArgument('number'))), + 'Too many arguments, expected arguments "number".', + ), + array( + array('cli.php', 'foo', 'bar', 'zzz'), + new InputDefinition(array(new InputArgument('number'), new InputArgument('county'))), + 'Too many arguments, expected arguments "number" "county".', ), array( array('cli.php', '--foo'), @@ -224,14 +270,14 @@ class ArgvInputTest extends \PHPUnit_Framework_TestCase $input = new ArgvInput(array('cli.php', '--name=foo', '--name=bar', '--name=')); $input->bind(new InputDefinition(array(new InputOption('name', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY)))); - $this->assertSame(array('name' => array('foo', 'bar', null)), $input->getOptions(), '->parse() parses empty array options as null ("--option=value" syntax)'); + $this->assertSame(array('name' => array('foo', 'bar', '')), $input->getOptions(), '->parse() parses empty array options as null ("--option=value" syntax)'); $input = new ArgvInput(array('cli.php', '--name', 'foo', '--name', 'bar', '--name', '--anotherOption')); $input->bind(new InputDefinition(array( new InputOption('name', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY), new InputOption('anotherOption', null, InputOption::VALUE_NONE), ))); - $this->assertSame(array('name' => array('foo', 'bar', null), 'anotherOption' => true), $input->getOptions(), '->parse() parses empty array options as null ("--option value" syntax)'); + $this->assertSame(array('name' => array('foo', 'bar', null), 'anotherOption' => true), $input->getOptions(), '->parse() parses empty array options ("--option value" syntax)'); } public function testParseNegativeNumberAfterDoubleDash() @@ -268,6 +314,12 @@ class ArgvInputTest extends \PHPUnit_Framework_TestCase $input = new ArgvInput(array('cli.php', '-f', 'foo')); $this->assertTrue($input->hasParameterOption('-f'), '->hasParameterOption() returns true if the given short option is in the raw input'); + $input = new ArgvInput(array('cli.php', '-fh')); + $this->assertTrue($input->hasParameterOption('-fh'), '->hasParameterOption() returns true if the given short option is in the raw input'); + + $input = new ArgvInput(array('cli.php', '-e=test')); + $this->assertFalse($input->hasParameterOption('-s'), '->hasParameterOption() returns true if the given short option is in the raw input'); + $input = new ArgvInput(array('cli.php', '--foo', 'foo')); $this->assertTrue($input->hasParameterOption('--foo'), '->hasParameterOption() returns true if the given short option is in the raw input'); @@ -278,6 +330,21 @@ class ArgvInputTest extends \PHPUnit_Framework_TestCase $this->assertTrue($input->hasParameterOption('--foo'), '->hasParameterOption() returns true if the given option with provided value is in the raw input'); } + public function testHasParameterOptionOnlyOptions() + { + $input = new ArgvInput(array('cli.php', '-f', 'foo')); + $this->assertTrue($input->hasParameterOption('-f', true), '->hasParameterOption() returns true if the given short option is in the raw input'); + + $input = new ArgvInput(array('cli.php', '--foo', '--', 'foo')); + $this->assertTrue($input->hasParameterOption('--foo', true), '->hasParameterOption() returns true if the given long option is in the raw input'); + + $input = new ArgvInput(array('cli.php', '--foo=bar', 'foo')); + $this->assertTrue($input->hasParameterOption('--foo', true), '->hasParameterOption() returns true if the given long option with provided value is in the raw input'); + + $input = new ArgvInput(array('cli.php', '--', '--foo')); + $this->assertFalse($input->hasParameterOption('--foo', true), '->hasParameterOption() returns false if the given option is in the raw input but after an end of options signal'); + } + public function testToString() { $input = new ArgvInput(array('cli.php', '-f', 'foo')); @@ -290,21 +357,25 @@ class ArgvInputTest extends \PHPUnit_Framework_TestCase /** * @dataProvider provideGetParameterOptionValues */ - public function testGetParameterOptionEqualSign($argv, $key, $expected) + public function testGetParameterOptionEqualSign($argv, $key, $onlyParams, $expected) { $input = new ArgvInput($argv); - $this->assertEquals($expected, $input->getParameterOption($key), '->getParameterOption() returns the expected value'); + $this->assertEquals($expected, $input->getParameterOption($key, false, $onlyParams), '->getParameterOption() returns the expected value'); } public function provideGetParameterOptionValues() { return array( - array(array('app/console', 'foo:bar', '-e', 'dev'), '-e', 'dev'), - array(array('app/console', 'foo:bar', '--env=dev'), '--env', 'dev'), - array(array('app/console', 'foo:bar', '-e', 'dev'), array('-e', '--env'), 'dev'), - array(array('app/console', 'foo:bar', '--env=dev'), array('-e', '--env'), 'dev'), - array(array('app/console', 'foo:bar', '--env=dev', '--en=1'), array('--en'), '1'), - array(array('app/console', 'foo:bar', '--env=dev', '', '--en=1'), array('--en'), '1'), + array(array('app/console', 'foo:bar', '-e', 'dev'), '-e', false, 'dev'), + array(array('app/console', 'foo:bar', '--env=dev'), '--env', false, 'dev'), + array(array('app/console', 'foo:bar', '-e', 'dev'), array('-e', '--env'), false, 'dev'), + array(array('app/console', 'foo:bar', '--env=dev'), array('-e', '--env'), false, 'dev'), + array(array('app/console', 'foo:bar', '--env=dev', '--en=1'), array('--en'), false, '1'), + array(array('app/console', 'foo:bar', '--env=dev', '', '--en=1'), array('--en'), false, '1'), + array(array('app/console', 'foo:bar', '--env', 'val'), '--env', false, 'val'), + array(array('app/console', 'foo:bar', '--env', 'val', '--dummy'), '--env', false, 'val'), + array(array('app/console', 'foo:bar', '--', '--env=dev'), '--env', false, 'dev'), + array(array('app/console', 'foo:bar', '--', '--env=dev'), '--env', true, false), ); } @@ -314,4 +385,30 @@ class ArgvInputTest extends \PHPUnit_Framework_TestCase $input->bind(new InputDefinition(array(new InputArgument('file')))); $this->assertEquals(array('file' => '-'), $input->getArguments(), '->parse() parses single dash as an argument'); } + + public function testParseOptionWithValueOptionalGivenEmptyAndRequiredArgument() + { + $input = new ArgvInput(array('cli.php', '--foo=', 'bar')); + $input->bind(new InputDefinition(array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputArgument('name', InputArgument::REQUIRED)))); + $this->assertEquals(array('foo' => null), $input->getOptions(), '->parse() parses optional options with empty value as null'); + $this->assertEquals(array('name' => 'bar'), $input->getArguments(), '->parse() parses required arguments'); + + $input = new ArgvInput(array('cli.php', '--foo=0', 'bar')); + $input->bind(new InputDefinition(array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputArgument('name', InputArgument::REQUIRED)))); + $this->assertEquals(array('foo' => '0'), $input->getOptions(), '->parse() parses optional options with empty value as null'); + $this->assertEquals(array('name' => 'bar'), $input->getArguments(), '->parse() parses required arguments'); + } + + public function testParseOptionWithValueOptionalGivenEmptyAndOptionalArgument() + { + $input = new ArgvInput(array('cli.php', '--foo=', 'bar')); + $input->bind(new InputDefinition(array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputArgument('name', InputArgument::OPTIONAL)))); + $this->assertEquals(array('foo' => null), $input->getOptions(), '->parse() parses optional options with empty value as null'); + $this->assertEquals(array('name' => 'bar'), $input->getArguments(), '->parse() parses optional arguments'); + + $input = new ArgvInput(array('cli.php', '--foo=0', 'bar')); + $input->bind(new InputDefinition(array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputArgument('name', InputArgument::OPTIONAL)))); + $this->assertEquals(array('foo' => '0'), $input->getOptions(), '->parse() parses optional options with empty value as null'); + $this->assertEquals(array('name' => 'bar'), $input->getArguments(), '->parse() parses optional arguments'); + } } diff --git a/vendor/symfony/console/Tests/Input/ArrayInputTest.php b/vendor/symfony/console/Tests/Input/ArrayInputTest.php index cc89083c..3e858435 100644 --- a/vendor/symfony/console/Tests/Input/ArrayInputTest.php +++ b/vendor/symfony/console/Tests/Input/ArrayInputTest.php @@ -11,12 +11,13 @@ namespace Symfony\Component\Console\Tests\Input; +use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; -class ArrayInputTest extends \PHPUnit_Framework_TestCase +class ArrayInputTest extends TestCase { public function testGetFirstArgument() { @@ -36,15 +37,24 @@ class ArrayInputTest extends \PHPUnit_Framework_TestCase $input = new ArrayInput(array('--foo')); $this->assertTrue($input->hasParameterOption('--foo'), '->hasParameterOption() returns true if an option is present in the passed parameters'); + + $input = new ArrayInput(array('--foo', '--', '--bar')); + $this->assertTrue($input->hasParameterOption('--bar'), '->hasParameterOption() returns true if an option is present in the passed parameters'); + $this->assertFalse($input->hasParameterOption('--bar', true), '->hasParameterOption() returns false if an option is present in the passed parameters after an end of options signal'); } public function testGetParameterOption() { $input = new ArrayInput(array('name' => 'Fabien', '--foo' => 'bar')); $this->assertEquals('bar', $input->getParameterOption('--foo'), '->getParameterOption() returns the option of specified name'); + $this->assertFalse($input->getParameterOption('--bar'), '->getParameterOption() returns the default if an option is not present in the passed parameters'); $input = new ArrayInput(array('Fabien', '--foo' => 'bar')); $this->assertEquals('bar', $input->getParameterOption('--foo'), '->getParameterOption() returns the option of specified name'); + + $input = new ArrayInput(array('--foo', '--', '--bar' => 'woop')); + $this->assertEquals('woop', $input->getParameterOption('--bar'), '->getParameterOption() returns the correct value if an option is present in the passed parameters'); + $this->assertFalse($input->getParameterOption('--bar', false, true), '->getParameterOption() returns false if an option is present in the passed parameters after an end of options signal'); } public function testParseArguments() @@ -80,9 +90,15 @@ class ArrayInputTest extends \PHPUnit_Framework_TestCase '->parse() parses long options with a default value', ), array( - array('--foo' => null), + array(), array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL, '', 'default')), array('foo' => 'default'), + '->parse() uses the default value for long options with value optional which are not passed', + ), + array( + array('--foo' => null), + array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL, '', 'default')), + array('foo' => null), '->parse() parses long options with a default value', ), array( @@ -91,6 +107,18 @@ class ArrayInputTest extends \PHPUnit_Framework_TestCase array('foo' => 'bar'), '->parse() parses short options', ), + array( + array('--' => null, '-f' => 'bar'), + array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL, '', 'default')), + array('foo' => 'default'), + '->parse() does not parse opts after an end of options signal', + ), + array( + array('--' => null), + array(), + array(), + '->parse() does not choke on end of options signal', + ), ); } @@ -99,7 +127,12 @@ class ArrayInputTest extends \PHPUnit_Framework_TestCase */ public function testParseInvalidInput($parameters, $definition, $expectedExceptionMessage) { - $this->setExpectedException('InvalidArgumentException', $expectedExceptionMessage); + if (method_exists($this, 'expectException')) { + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessage($expectedExceptionMessage); + } else { + $this->setExpectedException('InvalidArgumentException', $expectedExceptionMessage); + } new ArrayInput($parameters, $definition); } @@ -134,5 +167,8 @@ class ArrayInputTest extends \PHPUnit_Framework_TestCase { $input = new ArrayInput(array('-f' => null, '-b' => 'bar', '--foo' => 'b a z', '--lala' => null, 'test' => 'Foo', 'test2' => "A\nB'C")); $this->assertEquals('-f -b=bar --foo='.escapeshellarg('b a z').' --lala Foo '.escapeshellarg("A\nB'C"), (string) $input); + + $input = new ArrayInput(array('-b' => array('bval_1', 'bval_2'), '--f' => array('fval_1', 'fval_2'))); + $this->assertSame('-b=bval_1 -b=bval_2 --f=fval_1 --f=fval_2', (string) $input); } } diff --git a/vendor/symfony/console/Tests/Input/InputArgumentTest.php b/vendor/symfony/console/Tests/Input/InputArgumentTest.php index cfb37cd4..66af98b3 100644 --- a/vendor/symfony/console/Tests/Input/InputArgumentTest.php +++ b/vendor/symfony/console/Tests/Input/InputArgumentTest.php @@ -11,9 +11,10 @@ namespace Symfony\Component\Console\Tests\Input; +use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Input\InputArgument; -class InputArgumentTest extends \PHPUnit_Framework_TestCase +class InputArgumentTest extends TestCase { public function testConstructor() { @@ -41,7 +42,12 @@ class InputArgumentTest extends \PHPUnit_Framework_TestCase */ public function testInvalidModes($mode) { - $this->setExpectedException('InvalidArgumentException', sprintf('Argument mode "%s" is not valid.', $mode)); + if (method_exists($this, 'expectException')) { + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessage(sprintf('Argument mode "%s" is not valid.', $mode)); + } else { + $this->setExpectedException('InvalidArgumentException', sprintf('Argument mode "%s" is not valid.', $mode)); + } new InputArgument('foo', $mode); } diff --git a/vendor/symfony/console/Tests/Input/InputDefinitionTest.php b/vendor/symfony/console/Tests/Input/InputDefinitionTest.php index 7e0a2425..1374ddfd 100644 --- a/vendor/symfony/console/Tests/Input/InputDefinitionTest.php +++ b/vendor/symfony/console/Tests/Input/InputDefinitionTest.php @@ -11,15 +11,19 @@ namespace Symfony\Component\Console\Tests\Input; +use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; -class InputDefinitionTest extends \PHPUnit_Framework_TestCase +class InputDefinitionTest extends TestCase { protected static $fixtures; - protected $foo, $bar, $foo1, $foo2; + protected $foo; + protected $bar; + protected $foo1; + protected $foo2; public static function setUpBeforeClass() { @@ -383,41 +387,6 @@ class InputDefinitionTest extends \PHPUnit_Framework_TestCase $this->assertEquals('[options] [--] [<cat>]', $definition->getSynopsis(true), '->getSynopsis(true) groups options in [options]'); } - /** - * @group legacy - */ - public function testLegacyAsText() - { - $definition = new InputDefinition(array( - new InputArgument('foo', InputArgument::OPTIONAL, 'The foo argument'), - new InputArgument('baz', InputArgument::OPTIONAL, 'The baz argument', true), - new InputArgument('bar', InputArgument::OPTIONAL | InputArgument::IS_ARRAY, 'The bar argument', array('http://foo.com/')), - new InputOption('foo', 'f', InputOption::VALUE_REQUIRED, 'The foo option'), - new InputOption('baz', null, InputOption::VALUE_OPTIONAL, 'The baz option', false), - new InputOption('bar', 'b', InputOption::VALUE_OPTIONAL, 'The bar option', 'bar'), - new InputOption('qux', '', InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'The qux option', array('http://foo.com/', 'bar')), - new InputOption('qux2', '', InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'The qux2 option', array('foo' => 'bar')), - )); - - $this->assertStringEqualsFile(self::$fixtures.'/definition_astext.txt', $definition->asText(), '->asText() returns a textual representation of the InputDefinition'); - } - - /** - * @group legacy - */ - public function testLegacyAsXml() - { - $definition = new InputDefinition(array( - new InputArgument('foo', InputArgument::OPTIONAL, 'The foo argument'), - new InputArgument('baz', InputArgument::OPTIONAL, 'The baz argument', true), - new InputArgument('bar', InputArgument::OPTIONAL | InputArgument::IS_ARRAY, 'The bar argument', array('bar')), - new InputOption('foo', 'f', InputOption::VALUE_REQUIRED, 'The foo option'), - new InputOption('baz', null, InputOption::VALUE_OPTIONAL, 'The baz option', false), - new InputOption('bar', 'b', InputOption::VALUE_OPTIONAL, 'The bar option', 'bar'), - )); - $this->assertXmlStringEqualsXmlFile(self::$fixtures.'/definition_asxml.txt', $definition->asXml(), '->asXml() returns an XML representation of the InputDefinition'); - } - protected function initializeArguments() { $this->foo = new InputArgument('foo'); diff --git a/vendor/symfony/console/Tests/Input/InputOptionTest.php b/vendor/symfony/console/Tests/Input/InputOptionTest.php index 53ce1df8..943bf607 100644 --- a/vendor/symfony/console/Tests/Input/InputOptionTest.php +++ b/vendor/symfony/console/Tests/Input/InputOptionTest.php @@ -11,9 +11,10 @@ namespace Symfony\Component\Console\Tests\Input; +use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Input\InputOption; -class InputOptionTest extends \PHPUnit_Framework_TestCase +class InputOptionTest extends TestCase { public function testConstructor() { @@ -77,7 +78,12 @@ class InputOptionTest extends \PHPUnit_Framework_TestCase */ public function testInvalidModes($mode) { - $this->setExpectedException('InvalidArgumentException', sprintf('Option mode "%s" is not valid.', $mode)); + if (method_exists($this, 'expectException')) { + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessage(sprintf('Option mode "%s" is not valid.', $mode)); + } else { + $this->setExpectedException('InvalidArgumentException', sprintf('Option mode "%s" is not valid.', $mode)); + } new InputOption('foo', 'f', $mode); } diff --git a/vendor/symfony/console/Tests/Input/InputTest.php b/vendor/symfony/console/Tests/Input/InputTest.php index eb1c6617..4410d2f5 100644 --- a/vendor/symfony/console/Tests/Input/InputTest.php +++ b/vendor/symfony/console/Tests/Input/InputTest.php @@ -11,12 +11,13 @@ namespace Symfony\Component\Console\Tests\Input; +use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; -class InputTest extends \PHPUnit_Framework_TestCase +class InputTest extends TestCase { public function testConstructor() { @@ -36,6 +37,14 @@ class InputTest extends \PHPUnit_Framework_TestCase $input = new ArrayInput(array('--name' => 'foo'), new InputDefinition(array(new InputOption('name'), new InputOption('bar', '', InputOption::VALUE_OPTIONAL, '', 'default')))); $this->assertEquals('default', $input->getOption('bar'), '->getOption() returns the default value for optional options'); $this->assertEquals(array('name' => 'foo', 'bar' => 'default'), $input->getOptions(), '->getOptions() returns all option values, even optional ones'); + + $input = new ArrayInput(array('--name' => 'foo', '--bar' => ''), new InputDefinition(array(new InputOption('name'), new InputOption('bar', '', InputOption::VALUE_OPTIONAL, '', 'default')))); + $this->assertEquals('', $input->getOption('bar'), '->getOption() returns null for options explicitly passed without value (or an empty value)'); + $this->assertEquals(array('name' => 'foo', 'bar' => ''), $input->getOptions(), '->getOptions() returns all option values.'); + + $input = new ArrayInput(array('--name' => 'foo', '--bar' => null), new InputDefinition(array(new InputOption('name'), new InputOption('bar', '', InputOption::VALUE_OPTIONAL, '', 'default')))); + $this->assertNull($input->getOption('bar'), '->getOption() returns null for options explicitly passed without value (or an empty value)'); + $this->assertEquals(array('name' => 'foo', 'bar' => null), $input->getOptions(), '->getOptions() returns all option values'); } /** @@ -129,4 +138,12 @@ class InputTest extends \PHPUnit_Framework_TestCase $input->setInteractive(false); $this->assertFalse($input->isInteractive(), '->setInteractive() changes the interactive flag'); } + + public function testSetGetStream() + { + $input = new ArrayInput(array()); + $stream = fopen('php://memory', 'r+', false); + $input->setStream($stream); + $this->assertSame($stream, $input->getStream()); + } } diff --git a/vendor/symfony/console/Tests/Input/StringInputTest.php b/vendor/symfony/console/Tests/Input/StringInputTest.php index c8a560f6..f2e3467e 100644 --- a/vendor/symfony/console/Tests/Input/StringInputTest.php +++ b/vendor/symfony/console/Tests/Input/StringInputTest.php @@ -11,11 +11,12 @@ namespace Symfony\Component\Console\Tests\Input; +use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\StringInput; -class StringInputTest extends \PHPUnit_Framework_TestCase +class StringInputTest extends TestCase { /** * @dataProvider getTokenizeData @@ -41,19 +42,6 @@ class StringInputTest extends \PHPUnit_Framework_TestCase $this->assertEquals('bar', $input->getOption('foo')); } - /** - * @group legacy - */ - public function testLegacyInputOptionDefinitionInConstructor() - { - $definition = new InputDefinition( - array(new InputOption('foo', null, InputOption::VALUE_REQUIRED)) - ); - - $input = new StringInput('--foo=bar', $definition); - $this->assertEquals('bar', $input->getOption('foo')); - } - public function getTokenizeData() { return array( diff --git a/vendor/symfony/console/Tests/Logger/ConsoleLoggerTest.php b/vendor/symfony/console/Tests/Logger/ConsoleLoggerTest.php index c5eca2ca..734a153e 100644 --- a/vendor/symfony/console/Tests/Logger/ConsoleLoggerTest.php +++ b/vendor/symfony/console/Tests/Logger/ConsoleLoggerTest.php @@ -11,9 +11,11 @@ namespace Symfony\Component\Console\Tests\Logger; -use Psr\Log\Test\LoggerInterfaceTest; +use PHPUnit\Framework\TestCase; +use Psr\Log\LoggerInterface; use Psr\Log\LogLevel; use Symfony\Component\Console\Logger\ConsoleLogger; +use Symfony\Component\Console\Output\BufferedOutput; use Symfony\Component\Console\Tests\Fixtures\DummyOutput; use Symfony\Component\Console\Output\OutputInterface; @@ -21,8 +23,9 @@ use Symfony\Component\Console\Output\OutputInterface; * Console logger test. * * @author Kévin Dunglas <dunglas@gmail.com> + * @author Jordi Boggiano <j.boggiano@seld.be> */ -class ConsoleLoggerTest extends LoggerInterfaceTest +class ConsoleLoggerTest extends TestCase { /** * @var DummyOutput @@ -30,7 +33,7 @@ class ConsoleLoggerTest extends LoggerInterfaceTest protected $output; /** - * {@inheritdoc} + * @return LoggerInterface */ public function getLogger() { @@ -49,10 +52,164 @@ class ConsoleLoggerTest extends LoggerInterfaceTest } /** - * {@inheritdoc} + * Return the log messages in order. + * + * @return string[] */ public function getLogs() { return $this->output->getLogs(); } + + /** + * @dataProvider provideOutputMappingParams + */ + public function testOutputMapping($logLevel, $outputVerbosity, $isOutput, $addVerbosityLevelMap = array()) + { + $out = new BufferedOutput($outputVerbosity); + $logger = new ConsoleLogger($out, $addVerbosityLevelMap); + $logger->log($logLevel, 'foo bar'); + $logs = $out->fetch(); + $this->assertEquals($isOutput ? "[$logLevel] foo bar".PHP_EOL : '', $logs); + } + + public function provideOutputMappingParams() + { + $quietMap = array(LogLevel::EMERGENCY => OutputInterface::VERBOSITY_QUIET); + + return array( + array(LogLevel::EMERGENCY, OutputInterface::VERBOSITY_NORMAL, true), + array(LogLevel::WARNING, OutputInterface::VERBOSITY_NORMAL, true), + array(LogLevel::INFO, OutputInterface::VERBOSITY_NORMAL, false), + array(LogLevel::DEBUG, OutputInterface::VERBOSITY_NORMAL, false), + array(LogLevel::INFO, OutputInterface::VERBOSITY_VERBOSE, false), + array(LogLevel::INFO, OutputInterface::VERBOSITY_VERY_VERBOSE, true), + array(LogLevel::DEBUG, OutputInterface::VERBOSITY_VERY_VERBOSE, false), + array(LogLevel::DEBUG, OutputInterface::VERBOSITY_DEBUG, true), + array(LogLevel::ALERT, OutputInterface::VERBOSITY_QUIET, false), + array(LogLevel::EMERGENCY, OutputInterface::VERBOSITY_QUIET, false), + array(LogLevel::ALERT, OutputInterface::VERBOSITY_QUIET, false, $quietMap), + array(LogLevel::EMERGENCY, OutputInterface::VERBOSITY_QUIET, true, $quietMap), + ); + } + + public function testHasErrored() + { + $logger = new ConsoleLogger(new BufferedOutput()); + + $this->assertFalse($logger->hasErrored()); + + $logger->warning('foo'); + $this->assertFalse($logger->hasErrored()); + + $logger->error('bar'); + $this->assertTrue($logger->hasErrored()); + } + + public function testImplements() + { + $this->assertInstanceOf('Psr\Log\LoggerInterface', $this->getLogger()); + } + + /** + * @dataProvider provideLevelsAndMessages + */ + public function testLogsAtAllLevels($level, $message) + { + $logger = $this->getLogger(); + $logger->{$level}($message, array('user' => 'Bob')); + $logger->log($level, $message, array('user' => 'Bob')); + + $expected = array( + $level.' message of level '.$level.' with context: Bob', + $level.' message of level '.$level.' with context: Bob', + ); + $this->assertEquals($expected, $this->getLogs()); + } + + public function provideLevelsAndMessages() + { + return array( + LogLevel::EMERGENCY => array(LogLevel::EMERGENCY, 'message of level emergency with context: {user}'), + LogLevel::ALERT => array(LogLevel::ALERT, 'message of level alert with context: {user}'), + LogLevel::CRITICAL => array(LogLevel::CRITICAL, 'message of level critical with context: {user}'), + LogLevel::ERROR => array(LogLevel::ERROR, 'message of level error with context: {user}'), + LogLevel::WARNING => array(LogLevel::WARNING, 'message of level warning with context: {user}'), + LogLevel::NOTICE => array(LogLevel::NOTICE, 'message of level notice with context: {user}'), + LogLevel::INFO => array(LogLevel::INFO, 'message of level info with context: {user}'), + LogLevel::DEBUG => array(LogLevel::DEBUG, 'message of level debug with context: {user}'), + ); + } + + /** + * @expectedException \Psr\Log\InvalidArgumentException + */ + public function testThrowsOnInvalidLevel() + { + $logger = $this->getLogger(); + $logger->log('invalid level', 'Foo'); + } + + public function testContextReplacement() + { + $logger = $this->getLogger(); + $logger->info('{Message {nothing} {user} {foo.bar} a}', array('user' => 'Bob', 'foo.bar' => 'Bar')); + + $expected = array('info {Message {nothing} Bob Bar a}'); + $this->assertEquals($expected, $this->getLogs()); + } + + public function testObjectCastToString() + { + if (method_exists($this, 'createPartialMock')) { + $dummy = $this->createPartialMock('Symfony\Component\Console\Tests\Logger\DummyTest', array('__toString')); + } else { + $dummy = $this->getMock('Symfony\Component\Console\Tests\Logger\DummyTest', array('__toString')); + } + $dummy->method('__toString')->will($this->returnValue('DUMMY')); + + $this->getLogger()->warning($dummy); + + $expected = array('warning DUMMY'); + $this->assertEquals($expected, $this->getLogs()); + } + + public function testContextCanContainAnything() + { + $context = array( + 'bool' => true, + 'null' => null, + 'string' => 'Foo', + 'int' => 0, + 'float' => 0.5, + 'nested' => array('with object' => new DummyTest()), + 'object' => new \DateTime(), + 'resource' => fopen('php://memory', 'r'), + ); + + $this->getLogger()->warning('Crazy context data', $context); + + $expected = array('warning Crazy context data'); + $this->assertEquals($expected, $this->getLogs()); + } + + public function testContextExceptionKeyCanBeExceptionOrOtherValues() + { + $logger = $this->getLogger(); + $logger->warning('Random message', array('exception' => 'oops')); + $logger->critical('Uncaught Exception!', array('exception' => new \LogicException('Fail'))); + + $expected = array( + 'warning Random message', + 'critical Uncaught Exception!', + ); + $this->assertEquals($expected, $this->getLogs()); + } +} + +class DummyTest +{ + public function __toString() + { + } } diff --git a/vendor/symfony/console/Tests/Output/ConsoleOutputTest.php b/vendor/symfony/console/Tests/Output/ConsoleOutputTest.php index 1afbbb6e..db39a02b 100644 --- a/vendor/symfony/console/Tests/Output/ConsoleOutputTest.php +++ b/vendor/symfony/console/Tests/Output/ConsoleOutputTest.php @@ -11,10 +11,12 @@ namespace Symfony\Component\Console\Tests\Output; +use PHPUnit\Framework\TestCase; +use Symfony\Component\Console\Formatter\OutputFormatter; use Symfony\Component\Console\Output\ConsoleOutput; use Symfony\Component\Console\Output\Output; -class ConsoleOutputTest extends \PHPUnit_Framework_TestCase +class ConsoleOutputTest extends TestCase { public function testConstructor() { @@ -22,4 +24,19 @@ class ConsoleOutputTest extends \PHPUnit_Framework_TestCase $this->assertEquals(Output::VERBOSITY_QUIET, $output->getVerbosity(), '__construct() takes the verbosity as its first argument'); $this->assertSame($output->getFormatter(), $output->getErrorOutput()->getFormatter(), '__construct() takes a formatter or null as the third argument'); } + + public function testSetFormatter() + { + $output = new ConsoleOutput(); + $outputFormatter = new OutputFormatter(); + $output->setFormatter($outputFormatter); + $this->assertSame($outputFormatter, $output->getFormatter()); + } + + public function testSetVerbosity() + { + $output = new ConsoleOutput(); + $output->setVerbosity(Output::VERBOSITY_VERBOSE); + $this->assertSame(Output::VERBOSITY_VERBOSE, $output->getVerbosity()); + } } diff --git a/vendor/symfony/console/Tests/Output/NullOutputTest.php b/vendor/symfony/console/Tests/Output/NullOutputTest.php index b20ae4e8..b7ff4be3 100644 --- a/vendor/symfony/console/Tests/Output/NullOutputTest.php +++ b/vendor/symfony/console/Tests/Output/NullOutputTest.php @@ -11,10 +11,13 @@ namespace Symfony\Component\Console\Tests\Output; +use PHPUnit\Framework\TestCase; +use Symfony\Component\Console\Formatter\OutputFormatter; use Symfony\Component\Console\Output\NullOutput; +use Symfony\Component\Console\Output\Output; use Symfony\Component\Console\Output\OutputInterface; -class NullOutputTest extends \PHPUnit_Framework_TestCase +class NullOutputTest extends TestCase { public function testConstructor() { @@ -36,4 +39,50 @@ class NullOutputTest extends \PHPUnit_Framework_TestCase $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE); $this->assertSame(OutputInterface::VERBOSITY_QUIET, $output->getVerbosity(), '->getVerbosity() always returns VERBOSITY_QUIET for NullOutput'); } + + public function testSetFormatter() + { + $output = new NullOutput(); + $outputFormatter = new OutputFormatter(); + $output->setFormatter($outputFormatter); + $this->assertNotSame($outputFormatter, $output->getFormatter()); + } + + public function testSetVerbosity() + { + $output = new NullOutput(); + $output->setVerbosity(Output::VERBOSITY_NORMAL); + $this->assertEquals(Output::VERBOSITY_QUIET, $output->getVerbosity()); + } + + public function testSetDecorated() + { + $output = new NullOutput(); + $output->setDecorated(true); + $this->assertFalse($output->isDecorated()); + } + + public function testIsQuiet() + { + $output = new NullOutput(); + $this->assertTrue($output->isQuiet()); + } + + public function testIsVerbose() + { + $output = new NullOutput(); + $this->assertFalse($output->isVerbose()); + } + + public function testIsVeryVerbose() + { + $output = new NullOutput(); + $this->assertFalse($output->isVeryVerbose()); + } + + public function testIsDebug() + { + $output = new NullOutput(); + $this->assertFalse($output->isDebug()); + } } diff --git a/vendor/symfony/console/Tests/Output/OutputTest.php b/vendor/symfony/console/Tests/Output/OutputTest.php index 45e6ddc7..d8330d0b 100644 --- a/vendor/symfony/console/Tests/Output/OutputTest.php +++ b/vendor/symfony/console/Tests/Output/OutputTest.php @@ -11,10 +11,11 @@ namespace Symfony\Component\Console\Tests\Output; +use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Output\Output; use Symfony\Component\Console\Formatter\OutputFormatterStyle; -class OutputTest extends \PHPUnit_Framework_TestCase +class OutputTest extends TestCase { public function testConstructor() { diff --git a/vendor/symfony/console/Tests/Output/StreamOutputTest.php b/vendor/symfony/console/Tests/Output/StreamOutputTest.php index 2fd4f612..780b5681 100644 --- a/vendor/symfony/console/Tests/Output/StreamOutputTest.php +++ b/vendor/symfony/console/Tests/Output/StreamOutputTest.php @@ -11,10 +11,11 @@ namespace Symfony\Component\Console\Tests\Output; +use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Output\Output; use Symfony\Component\Console\Output\StreamOutput; -class StreamOutputTest extends \PHPUnit_Framework_TestCase +class StreamOutputTest extends TestCase { protected $stream; diff --git a/vendor/symfony/console/Tests/Style/SymfonyStyleTest.php b/vendor/symfony/console/Tests/Style/SymfonyStyleTest.php index 889a9c82..865bb33f 100644 --- a/vendor/symfony/console/Tests/Style/SymfonyStyleTest.php +++ b/vendor/symfony/console/Tests/Style/SymfonyStyleTest.php @@ -11,14 +11,16 @@ namespace Symfony\Component\Console\Tests\Style; -use PHPUnit_Framework_TestCase; +use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Tester\CommandTester; +use Symfony\Component\Console\Formatter\OutputFormatter; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Output\ConsoleOutputInterface; +use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\Console\Tester\CommandTester; -class SymfonyStyleTest extends PHPUnit_Framework_TestCase +class SymfonyStyleTest extends TestCase { /** @var Command */ protected $command; @@ -27,12 +29,14 @@ class SymfonyStyleTest extends PHPUnit_Framework_TestCase protected function setUp() { + putenv('COLUMNS=121'); $this->command = new Command('sfstyle'); $this->tester = new CommandTester($this->command); } protected function tearDown() { + putenv('COLUMNS'); $this->command = null; $this->tester = null; } @@ -48,6 +52,24 @@ class SymfonyStyleTest extends PHPUnit_Framework_TestCase $this->assertStringEqualsFile($outputFilepath, $this->tester->getDisplay(true)); } + /** + * @dataProvider inputInteractiveCommandToOutputFilesProvider + */ + public function testInteractiveOutputs($inputCommandFilepath, $outputFilepath) + { + $code = require $inputCommandFilepath; + $this->command->setCode($code); + $this->tester->execute(array(), array('interactive' => true, 'decorated' => false)); + $this->assertStringEqualsFile($outputFilepath, $this->tester->getDisplay(true)); + } + + public function inputInteractiveCommandToOutputFilesProvider() + { + $baseDir = __DIR__.'/../Fixtures/Style/SymfonyStyle'; + + return array_map(null, glob($baseDir.'/command/interactive_command_*.php'), glob($baseDir.'/output/interactive_output_*.txt')); + } + public function inputCommandToOutputFilesProvider() { $baseDir = __DIR__.'/../Fixtures/Style/SymfonyStyle'; @@ -55,35 +77,40 @@ class SymfonyStyleTest extends PHPUnit_Framework_TestCase return array_map(null, glob($baseDir.'/command/command_*.php'), glob($baseDir.'/output/output_*.txt')); } - public function testLongWordsBlockWrapping() + public function testGetErrorStyle() { - $word = 'Lopadotemachoselachogaleokranioleipsanodrimhypotrimmatosilphioparaomelitokatakechymenokichlepikossyphophattoperisteralektryonoptekephalliokigklopeleiolagoiosiraiobaphetraganopterygovgollhjvhvljfezefeqifzeiqgiqzhrsdgihqzridghqridghqirshdghdghieridgheirhsdgehrsdvhqrsidhqshdgihrsidvqhneriqsdvjzergetsrfhgrstsfhsetsfhesrhdgtesfhbzrtfbrztvetbsdfbrsdfbrn'; - $wordLength = strlen($word); - $maxLineLength = SymfonyStyle::MAX_LINE_LENGTH - 3; + $input = $this->getMockBuilder(InputInterface::class)->getMock(); - $this->command->setCode(function (InputInterface $input, OutputInterface $output) use ($word) { - $sfStyle = new SymfonyStyleWithForcedLineLength($input, $output); - $sfStyle->block($word, 'CUSTOM', 'fg=white;bg=blue', ' § ', false); - }); + $errorOutput = $this->getMockBuilder(OutputInterface::class)->getMock(); + $errorOutput + ->method('getFormatter') + ->willReturn(new OutputFormatter()); + $errorOutput + ->expects($this->once()) + ->method('write'); - $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), ' § ')); + $output = $this->getMockBuilder(ConsoleOutputInterface::class)->getMock(); + $output + ->method('getFormatter') + ->willReturn(new OutputFormatter()); + $output + ->expects($this->once()) + ->method('getErrorOutput') + ->willReturn($errorOutput); + + $io = new SymfonyStyle($input, $output); + $io->getErrorStyle()->write(''); } -} -/** - * Use this class in tests to force the line length - * and ensure a consistent output for expectations. - */ -class SymfonyStyleWithForcedLineLength extends SymfonyStyle -{ - public function __construct(InputInterface $input, OutputInterface $output) + public function testGetErrorStyleUsesTheCurrentOutputIfNoErrorOutputIsAvailable() { - parent::__construct($input, $output); + $output = $this->getMockBuilder(OutputInterface::class)->getMock(); + $output + ->method('getFormatter') + ->willReturn(new OutputFormatter()); + + $style = new SymfonyStyle($this->getMockBuilder(InputInterface::class)->getMock(), $output); - $ref = new \ReflectionProperty(get_parent_class($this), 'lineLength'); - $ref->setAccessible(true); - $ref->setValue($this, 120); + $this->assertInstanceOf(SymfonyStyle::class, $style->getErrorStyle()); } } diff --git a/vendor/symfony/console/Tests/TerminalTest.php b/vendor/symfony/console/Tests/TerminalTest.php new file mode 100644 index 00000000..91af1d0a --- /dev/null +++ b/vendor/symfony/console/Tests/TerminalTest.php @@ -0,0 +1,44 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Tests; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Console\Terminal; + +class TerminalTest extends TestCase +{ + public function test() + { + putenv('COLUMNS=100'); + putenv('LINES=50'); + $terminal = new Terminal(); + $this->assertSame(100, $terminal->getWidth()); + $this->assertSame(50, $terminal->getHeight()); + + putenv('COLUMNS=120'); + putenv('LINES=60'); + $terminal = new Terminal(); + $this->assertSame(120, $terminal->getWidth()); + $this->assertSame(60, $terminal->getHeight()); + } + + public function test_zero_values() + { + putenv('COLUMNS=0'); + putenv('LINES=0'); + + $terminal = new Terminal(); + + $this->assertSame(0, $terminal->getWidth()); + $this->assertSame(0, $terminal->getHeight()); + } +} diff --git a/vendor/symfony/console/Tests/Tester/ApplicationTesterTest.php b/vendor/symfony/console/Tests/Tester/ApplicationTesterTest.php index a8389dd1..57e7136d 100644 --- a/vendor/symfony/console/Tests/Tester/ApplicationTesterTest.php +++ b/vendor/symfony/console/Tests/Tester/ApplicationTesterTest.php @@ -11,11 +11,12 @@ namespace Symfony\Component\Console\Tests\Tester; +use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Application; use Symfony\Component\Console\Output\Output; use Symfony\Component\Console\Tester\ApplicationTester; -class ApplicationTesterTest extends \PHPUnit_Framework_TestCase +class ApplicationTesterTest extends TestCase { protected $application; protected $tester; diff --git a/vendor/symfony/console/Tests/Tester/CommandTesterTest.php b/vendor/symfony/console/Tests/Tester/CommandTesterTest.php index b54c00e8..8d86da43 100644 --- a/vendor/symfony/console/Tests/Tester/CommandTesterTest.php +++ b/vendor/symfony/console/Tests/Tester/CommandTesterTest.php @@ -11,12 +11,17 @@ namespace Symfony\Component\Console\Tests\Tester; +use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Application; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Output\Output; use Symfony\Component\Console\Tester\CommandTester; +use Symfony\Component\Console\Question\Question; +use Symfony\Component\Console\Helper\HelperSet; +use Symfony\Component\Console\Helper\QuestionHelper; +use Symfony\Component\Console\Style\SymfonyStyle; -class CommandTesterTest extends \PHPUnit_Framework_TestCase +class CommandTesterTest extends TestCase { protected $command; protected $tester; @@ -81,4 +86,78 @@ class CommandTesterTest extends \PHPUnit_Framework_TestCase // check that there is no need to pass the command name here $this->assertEquals(0, $tester->execute(array())); } + + public function testCommandWithInputs() + { + $questions = array( + 'What\'s your name?', + 'How are you?', + 'Where do you come from?', + ); + + $command = new Command('foo'); + $command->setHelperSet(new HelperSet(array(new QuestionHelper()))); + $command->setCode(function ($input, $output) use ($questions, $command) { + $helper = $command->getHelper('question'); + $helper->ask($input, $output, new Question($questions[0])); + $helper->ask($input, $output, new Question($questions[1])); + $helper->ask($input, $output, new Question($questions[2])); + }); + + $tester = new CommandTester($command); + $tester->setInputs(array('Bobby', 'Fine', 'France')); + $tester->execute(array()); + + $this->assertEquals(0, $tester->getStatusCode()); + $this->assertEquals(implode('', $questions), $tester->getDisplay(true)); + } + + /** + * @expectedException \RuntimeException + * @expectedMessage Aborted + */ + public function testCommandWithWrongInputsNumber() + { + $questions = array( + 'What\'s your name?', + 'How are you?', + 'Where do you come from?', + ); + + $command = new Command('foo'); + $command->setHelperSet(new HelperSet(array(new QuestionHelper()))); + $command->setCode(function ($input, $output) use ($questions, $command) { + $helper = $command->getHelper('question'); + $helper->ask($input, $output, new Question($questions[0])); + $helper->ask($input, $output, new Question($questions[1])); + $helper->ask($input, $output, new Question($questions[2])); + }); + + $tester = new CommandTester($command); + $tester->setInputs(array('Bobby', 'Fine')); + $tester->execute(array()); + } + + public function testSymfonyStyleCommandWithInputs() + { + $questions = array( + 'What\'s your name?', + 'How are you?', + 'Where do you come from?', + ); + + $command = new Command('foo'); + $command->setCode(function ($input, $output) use ($questions, $command) { + $io = new SymfonyStyle($input, $output); + $io->ask($questions[0]); + $io->ask($questions[1]); + $io->ask($questions[2]); + }); + + $tester = new CommandTester($command); + $tester->setInputs(array('Bobby', 'Fine', 'France')); + $tester->execute(array()); + + $this->assertEquals(0, $tester->getStatusCode()); + } } diff --git a/vendor/symfony/console/composer.json b/vendor/symfony/console/composer.json index ab247045..e9d10e0c 100644 --- a/vendor/symfony/console/composer.json +++ b/vendor/symfony/console/composer.json @@ -16,19 +16,28 @@ } ], "require": { - "php": ">=5.3.9", - "symfony/polyfill-mbstring": "~1.0" + "php": "^5.5.9|>=7.0.8", + "symfony/polyfill-mbstring": "~1.0", + "symfony/debug": "~2.8|~3.0|~4.0" }, "require-dev": { - "symfony/event-dispatcher": "~2.1|~3.0.0", - "symfony/process": "~2.1|~3.0.0", + "symfony/config": "~3.3|~4.0", + "symfony/event-dispatcher": "~2.8|~3.0|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/lock": "~3.4|~4.0", + "symfony/process": "~3.3|~4.0", "psr/log": "~1.0" }, "suggest": { "symfony/event-dispatcher": "", + "symfony/lock": "", "symfony/process": "", "psr/log": "For using the console logger" }, + "conflict": { + "symfony/dependency-injection": "<3.4", + "symfony/process": "<3.3" + }, "autoload": { "psr-4": { "Symfony\\Component\\Console\\": "" }, "exclude-from-classmap": [ @@ -38,7 +47,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "2.8-dev" + "dev-master": "3.4-dev" } } } diff --git a/vendor/symfony/console/phpunit.xml.dist b/vendor/symfony/console/phpunit.xml.dist index 8c09554f..32569d63 100644 --- a/vendor/symfony/console/phpunit.xml.dist +++ b/vendor/symfony/console/phpunit.xml.dist @@ -5,6 +5,8 @@ backupGlobals="false" colors="true" bootstrap="vendor/autoload.php" + failOnRisky="true" + failOnWarning="true" > <php> <ini name="error_reporting" value="-1" /> diff --git a/vendor/symfony/debug/.gitignore b/vendor/symfony/debug/.gitignore new file mode 100644 index 00000000..c49a5d8d --- /dev/null +++ b/vendor/symfony/debug/.gitignore @@ -0,0 +1,3 @@ +vendor/ +composer.lock +phpunit.xml diff --git a/vendor/symfony/debug/BufferingLogger.php b/vendor/symfony/debug/BufferingLogger.php new file mode 100644 index 00000000..a2ed75b9 --- /dev/null +++ b/vendor/symfony/debug/BufferingLogger.php @@ -0,0 +1,37 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Debug; + +use Psr\Log\AbstractLogger; + +/** + * A buffering logger that stacks logs for later. + * + * @author Nicolas Grekas <p@tchwork.com> + */ +class BufferingLogger extends AbstractLogger +{ + private $logs = array(); + + public function log($level, $message, array $context = array()) + { + $this->logs[] = array($level, $message, $context); + } + + public function cleanLogs() + { + $logs = $this->logs; + $this->logs = array(); + + return $logs; + } +} diff --git a/vendor/symfony/debug/CHANGELOG.md b/vendor/symfony/debug/CHANGELOG.md new file mode 100644 index 00000000..31c67eb6 --- /dev/null +++ b/vendor/symfony/debug/CHANGELOG.md @@ -0,0 +1,64 @@ +CHANGELOG +========= + +3.4.0 +----- + +* deprecated `ErrorHandler::stackErrors()` and `ErrorHandler::unstackErrors()` + +3.3.0 +----- + +* deprecated the `ContextErrorException` class: use \ErrorException directly now + +3.2.0 +----- + +* `FlattenException::getTrace()` now returns additional type descriptions + `integer` and `float`. + + +3.0.0 +----- + +* removed classes, methods and interfaces deprecated in 2.x + +2.8.0 +----- + +* added BufferingLogger for errors that happen before a proper logger is configured +* allow throwing from `__toString()` with `return trigger_error($e, E_USER_ERROR);` +* deprecate ExceptionHandler::createResponse + +2.7.0 +----- + +* added deprecations checking for parent interfaces/classes to DebugClassLoader +* added ZTS support to symfony_debug extension +* added symfony_debug_backtrace() to symfony_debug extension + to track the backtrace of fatal errors + +2.6.0 +----- + +* generalized ErrorHandler and ExceptionHandler, + with some new methods and others deprecated +* enhanced error messages for uncaught exceptions + +2.5.0 +----- + +* added ExceptionHandler::setHandler() +* added UndefinedMethodFatalErrorHandler +* deprecated DummyException + +2.4.0 +----- + + * added a DebugClassLoader able to wrap any autoloader providing a findFile method + * improved error messages for not found classes and functions + +2.3.0 +----- + + * added the component diff --git a/vendor/symfony/debug/Debug.php b/vendor/symfony/debug/Debug.php new file mode 100644 index 00000000..e3665ae5 --- /dev/null +++ b/vendor/symfony/debug/Debug.php @@ -0,0 +1,63 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Debug; + +/** + * Registers all the debug tools. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Debug +{ + private static $enabled = false; + + /** + * Enables the debug tools. + * + * This method registers an error handler and an exception handler. + * + * If the Symfony ClassLoader component is available, a special + * class loader is also registered. + * + * @param int $errorReportingLevel The level of error reporting you want + * @param bool $displayErrors Whether to display errors (for development) or just log them (for production) + */ + public static function enable($errorReportingLevel = E_ALL, $displayErrors = true) + { + if (static::$enabled) { + return; + } + + static::$enabled = true; + + if (null !== $errorReportingLevel) { + error_reporting($errorReportingLevel); + } else { + error_reporting(E_ALL); + } + + if ('cli' !== PHP_SAPI) { + ini_set('display_errors', 0); + ExceptionHandler::register(); + } elseif ($displayErrors && (!ini_get('log_errors') || ini_get('error_log'))) { + // CLI - display errors only if they're not already logged to STDERR + ini_set('display_errors', 1); + } + if ($displayErrors) { + ErrorHandler::register(new ErrorHandler(new BufferingLogger())); + } else { + ErrorHandler::register()->throwAt(0, true); + } + + DebugClassLoader::enable(); + } +} diff --git a/vendor/symfony/debug/DebugClassLoader.php b/vendor/symfony/debug/DebugClassLoader.php new file mode 100644 index 00000000..9ff826ed --- /dev/null +++ b/vendor/symfony/debug/DebugClassLoader.php @@ -0,0 +1,384 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Debug; + +/** + * Autoloader checking if the class is really defined in the file found. + * + * The ClassLoader will wrap all registered autoloaders + * and will throw an exception if a file is found but does + * not declare the class. + * + * @author Fabien Potencier <fabien@symfony.com> + * @author Christophe Coevoet <stof@notk.org> + * @author Nicolas Grekas <p@tchwork.com> + */ +class DebugClassLoader +{ + private $classLoader; + private $isFinder; + private $loaded = array(); + private static $caseCheck; + private static $final = array(); + private static $finalMethods = array(); + private static $deprecated = array(); + private static $internal = array(); + private static $internalMethods = array(); + private static $php7Reserved = array('int', 'float', 'bool', 'string', 'true', 'false', 'null'); + private static $darwinCache = array('/' => array('/', array())); + + public function __construct(callable $classLoader) + { + $this->classLoader = $classLoader; + $this->isFinder = is_array($classLoader) && method_exists($classLoader[0], 'findFile'); + + if (!isset(self::$caseCheck)) { + $file = file_exists(__FILE__) ? __FILE__ : rtrim(realpath('.'), DIRECTORY_SEPARATOR); + $i = strrpos($file, DIRECTORY_SEPARATOR); + $dir = substr($file, 0, 1 + $i); + $file = substr($file, 1 + $i); + $test = strtoupper($file) === $file ? strtolower($file) : strtoupper($file); + $test = realpath($dir.$test); + + if (false === $test || false === $i) { + // filesystem is case sensitive + self::$caseCheck = 0; + } elseif (substr($test, -strlen($file)) === $file) { + // filesystem is case insensitive and realpath() normalizes the case of characters + self::$caseCheck = 1; + } elseif (false !== stripos(PHP_OS, 'darwin')) { + // on MacOSX, HFS+ is case insensitive but realpath() doesn't normalize the case of characters + self::$caseCheck = 2; + } else { + // filesystem case checks failed, fallback to disabling them + self::$caseCheck = 0; + } + } + } + + /** + * Gets the wrapped class loader. + * + * @return callable The wrapped class loader + */ + public function getClassLoader() + { + return $this->classLoader; + } + + /** + * Wraps all autoloaders. + */ + public static function enable() + { + // Ensures we don't hit https://bugs.php.net/42098 + class_exists('Symfony\Component\Debug\ErrorHandler'); + class_exists('Psr\Log\LogLevel'); + + if (!is_array($functions = spl_autoload_functions())) { + return; + } + + foreach ($functions as $function) { + spl_autoload_unregister($function); + } + + foreach ($functions as $function) { + if (!is_array($function) || !$function[0] instanceof self) { + $function = array(new static($function), 'loadClass'); + } + + spl_autoload_register($function); + } + } + + /** + * Disables the wrapping. + */ + public static function disable() + { + if (!is_array($functions = spl_autoload_functions())) { + return; + } + + foreach ($functions as $function) { + spl_autoload_unregister($function); + } + + foreach ($functions as $function) { + if (is_array($function) && $function[0] instanceof self) { + $function = $function[0]->getClassLoader(); + } + + spl_autoload_register($function); + } + } + + /** + * Loads the given class or interface. + * + * @param string $class The name of the class + * + * @return bool|null True, if loaded + * + * @throws \RuntimeException + */ + public function loadClass($class) + { + $e = error_reporting(error_reporting() | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR); + + try { + if ($this->isFinder && !isset($this->loaded[$class])) { + $this->loaded[$class] = true; + if ($file = $this->classLoader[0]->findFile($class)) { + require $file; + } + } else { + call_user_func($this->classLoader, $class); + $file = false; + } + } finally { + error_reporting($e); + } + + $exists = class_exists($class, false) || interface_exists($class, false) || trait_exists($class, false); + + if ($class && '\\' === $class[0]) { + $class = substr($class, 1); + } + + if ($exists) { + $refl = new \ReflectionClass($class); + $name = $refl->getName(); + + if ($name !== $class && 0 === strcasecmp($name, $class)) { + throw new \RuntimeException(sprintf('Case mismatch between loaded and declared class names: "%s" vs "%s".', $class, $name)); + } + + // Don't trigger deprecations for classes in the same vendor + if (2 > $len = 1 + (strpos($name, '\\') ?: strpos($name, '_'))) { + $len = 0; + $ns = ''; + } else { + $ns = substr($name, 0, $len); + } + + // Detect annotations on the class + if (false !== $doc = $refl->getDocComment()) { + foreach (array('final', 'deprecated', 'internal') as $annotation) { + if (false !== strpos($doc, '@'.$annotation) && preg_match('#\n \* @'.$annotation.'(?:( .+?)\.?)?\r?\n \*(?: @|/$)#s', $doc, $notice)) { + self::${$annotation}[$name] = isset($notice[1]) ? preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]) : ''; + } + } + } + + $parentAndTraits = class_uses($name, false); + if ($parent = get_parent_class($class)) { + $parentAndTraits[] = $parent; + + if (isset(self::$final[$parent])) { + @trigger_error(sprintf('The "%s" class is considered final%s. It may change without further notice as of its next major version. You should not extend it from "%s".', $parent, self::$final[$parent], $name), E_USER_DEPRECATED); + } + } + + // Detect if the parent is annotated + foreach ($parentAndTraits + $this->getOwnInterfaces($name, $parent) as $use) { + if (isset(self::$deprecated[$use]) && strncmp($ns, $use, $len)) { + $type = class_exists($name, false) ? 'class' : (interface_exists($name, false) ? 'interface' : 'trait'); + $verb = class_exists($use, false) || interface_exists($name, false) ? 'extends' : (interface_exists($use, false) ? 'implements' : 'uses'); + + @trigger_error(sprintf('The "%s" %s %s "%s" that is deprecated%s.', $name, $type, $verb, $use, self::$deprecated[$use]), E_USER_DEPRECATED); + } + if (isset(self::$internal[$use]) && strncmp($ns, $use, $len)) { + @trigger_error(sprintf('The "%s" %s is considered internal%s. It may change without further notice. You should not use it from "%s".', $use, class_exists($use, false) ? 'class' : (interface_exists($use, false) ? 'interface' : 'trait'), self::$internal[$use], $name), E_USER_DEPRECATED); + } + } + + // Inherit @final and @internal annotations for methods + self::$finalMethods[$name] = array(); + self::$internalMethods[$name] = array(); + foreach ($parentAndTraits as $use) { + foreach (array('finalMethods', 'internalMethods') as $property) { + if (isset(self::${$property}[$use])) { + self::${$property}[$name] = array_merge(self::${$property}[$name], self::${$property}[$use]); + } + } + } + + $isClass = class_exists($name, false); + foreach ($refl->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) as $method) { + if ($method->class !== $name) { + continue; + } + + // Method from a trait + if ($method->getFilename() !== $refl->getFileName()) { + continue; + } + + if ($isClass && $parent && isset(self::$finalMethods[$parent][$method->name])) { + list($declaringClass, $message) = self::$finalMethods[$parent][$method->name]; + @trigger_error(sprintf('The "%s::%s()" method is considered final%s. It may change without further notice as of its next major version. You should not extend it from "%s".', $declaringClass, $method->name, $message, $name), E_USER_DEPRECATED); + } + + foreach ($parentAndTraits as $use) { + if (isset(self::$internalMethods[$use][$method->name])) { + list($declaringClass, $message) = self::$internalMethods[$use][$method->name]; + if (strncmp($ns, $declaringClass, $len)) { + @trigger_error(sprintf('The "%s::%s()" method is considered internal%s. It may change without further notice. You should not extend it from "%s".', $declaringClass, $method->name, $message, $name), E_USER_DEPRECATED); + } + } + } + + // Detect method annotations + if (false === $doc = $method->getDocComment()) { + continue; + } + + foreach (array('final', 'internal') as $annotation) { + if (false !== strpos($doc, '@'.$annotation) && preg_match('#\n\s+\* @'.$annotation.'(?:( .+?)\.?)?\r?\n\s+\*(?: @|/$)#s', $doc, $notice)) { + $message = isset($notice[1]) ? preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]) : ''; + self::${$annotation.'Methods'}[$name][$method->name] = array($name, $message); + } + } + } + + if (in_array(strtolower($refl->getShortName()), self::$php7Reserved)) { + @trigger_error(sprintf('The "%s" class uses the reserved name "%s", it will break on PHP 7 and higher', $name, $refl->getShortName()), E_USER_DEPRECATED); + } + } + + if ($file) { + if (!$exists) { + if (false !== strpos($class, '/')) { + throw new \RuntimeException(sprintf('Trying to autoload a class with an invalid name "%s". Be careful that the namespace separator is "\" in PHP, not "/".', $class)); + } + + throw new \RuntimeException(sprintf('The autoloader expected class "%s" to be defined in file "%s". The file was found but the class was not in it, the class name or namespace probably has a typo.', $class, $file)); + } + if (self::$caseCheck) { + $real = explode('\\', $class.strrchr($file, '.')); + $tail = explode(DIRECTORY_SEPARATOR, str_replace('/', DIRECTORY_SEPARATOR, $file)); + + $i = count($tail) - 1; + $j = count($real) - 1; + + while (isset($tail[$i], $real[$j]) && $tail[$i] === $real[$j]) { + --$i; + --$j; + } + + array_splice($tail, 0, $i + 1); + } + if (self::$caseCheck && $tail) { + $tail = DIRECTORY_SEPARATOR.implode(DIRECTORY_SEPARATOR, $tail); + $tailLen = strlen($tail); + $real = $refl->getFileName(); + + if (2 === self::$caseCheck) { + // realpath() on MacOSX doesn't normalize the case of characters + + $i = 1 + strrpos($real, '/'); + $file = substr($real, $i); + $real = substr($real, 0, $i); + + if (isset(self::$darwinCache[$real])) { + $kDir = $real; + } else { + $kDir = strtolower($real); + + if (isset(self::$darwinCache[$kDir])) { + $real = self::$darwinCache[$kDir][0]; + } else { + $dir = getcwd(); + chdir($real); + $real = getcwd().'/'; + chdir($dir); + + $dir = $real; + $k = $kDir; + $i = strlen($dir) - 1; + while (!isset(self::$darwinCache[$k])) { + self::$darwinCache[$k] = array($dir, array()); + self::$darwinCache[$dir] = &self::$darwinCache[$k]; + + while ('/' !== $dir[--$i]) { + } + $k = substr($k, 0, ++$i); + $dir = substr($dir, 0, $i--); + } + } + } + + $dirFiles = self::$darwinCache[$kDir][1]; + + if (isset($dirFiles[$file])) { + $kFile = $file; + } else { + $kFile = strtolower($file); + + if (!isset($dirFiles[$kFile])) { + foreach (scandir($real, 2) as $f) { + if ('.' !== $f[0]) { + $dirFiles[$f] = $f; + if ($f === $file) { + $kFile = $k = $file; + } elseif ($f !== $k = strtolower($f)) { + $dirFiles[$k] = $f; + } + } + } + self::$darwinCache[$kDir][1] = $dirFiles; + } + } + + $real .= $dirFiles[$kFile]; + } + + if (0 === substr_compare($real, $tail, -$tailLen, $tailLen, true) + && 0 !== substr_compare($real, $tail, -$tailLen, $tailLen, false) + ) { + throw new \RuntimeException(sprintf('Case mismatch between class and real file names: "%s" vs "%s" in "%s".', substr($tail, -$tailLen + 1), substr($real, -$tailLen + 1), substr($real, 0, -$tailLen + 1))); + } + } + + return true; + } + } + + /** + * `class_implements` includes interfaces from the parents so we have to manually exclude them. + * + * @param string $class + * @param string|false $parent + * + * @return string[] + */ + private function getOwnInterfaces($class, $parent) + { + $ownInterfaces = class_implements($class, false); + + if ($parent) { + foreach (class_implements($parent, false) as $interface) { + unset($ownInterfaces[$interface]); + } + } + + foreach ($ownInterfaces as $interface) { + foreach (class_implements($interface) as $interface) { + unset($ownInterfaces[$interface]); + } + } + + return $ownInterfaces; + } +} diff --git a/vendor/symfony/debug/ErrorHandler.php b/vendor/symfony/debug/ErrorHandler.php new file mode 100644 index 00000000..aebb740a --- /dev/null +++ b/vendor/symfony/debug/ErrorHandler.php @@ -0,0 +1,746 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Debug; + +use Psr\Log\LogLevel; +use Psr\Log\LoggerInterface; +use Symfony\Component\Debug\Exception\ContextErrorException; +use Symfony\Component\Debug\Exception\FatalErrorException; +use Symfony\Component\Debug\Exception\FatalThrowableError; +use Symfony\Component\Debug\Exception\OutOfMemoryException; +use Symfony\Component\Debug\Exception\SilencedErrorContext; +use Symfony\Component\Debug\FatalErrorHandler\UndefinedFunctionFatalErrorHandler; +use Symfony\Component\Debug\FatalErrorHandler\UndefinedMethodFatalErrorHandler; +use Symfony\Component\Debug\FatalErrorHandler\ClassNotFoundFatalErrorHandler; +use Symfony\Component\Debug\FatalErrorHandler\FatalErrorHandlerInterface; + +/** + * A generic ErrorHandler for the PHP engine. + * + * Provides five bit fields that control how errors are handled: + * - thrownErrors: errors thrown as \ErrorException + * - loggedErrors: logged errors, when not @-silenced + * - scopedErrors: errors thrown or logged with their local context + * - tracedErrors: errors logged with their stack trace + * - screamedErrors: never @-silenced errors + * + * Each error level can be logged by a dedicated PSR-3 logger object. + * Screaming only applies to logging. + * Throwing takes precedence over logging. + * Uncaught exceptions are logged as E_ERROR. + * E_DEPRECATED and E_USER_DEPRECATED levels never throw. + * E_RECOVERABLE_ERROR and E_USER_ERROR levels always throw. + * Non catchable errors that can be detected at shutdown time are logged when the scream bit field allows so. + * As errors have a performance cost, repeated errors are all logged, so that the developer + * can see them and weight them as more important to fix than others of the same level. + * + * @author Nicolas Grekas <p@tchwork.com> + * @author Grégoire Pineau <lyrixx@lyrixx.info> + */ +class ErrorHandler +{ + private $levels = array( + E_DEPRECATED => 'Deprecated', + E_USER_DEPRECATED => 'User Deprecated', + E_NOTICE => 'Notice', + E_USER_NOTICE => 'User Notice', + E_STRICT => 'Runtime Notice', + E_WARNING => 'Warning', + E_USER_WARNING => 'User Warning', + E_COMPILE_WARNING => 'Compile Warning', + E_CORE_WARNING => 'Core Warning', + E_USER_ERROR => 'User Error', + E_RECOVERABLE_ERROR => 'Catchable Fatal Error', + E_COMPILE_ERROR => 'Compile Error', + E_PARSE => 'Parse Error', + E_ERROR => 'Error', + E_CORE_ERROR => 'Core Error', + ); + + private $loggers = array( + E_DEPRECATED => array(null, LogLevel::INFO), + E_USER_DEPRECATED => array(null, LogLevel::INFO), + E_NOTICE => array(null, LogLevel::WARNING), + E_USER_NOTICE => array(null, LogLevel::WARNING), + E_STRICT => array(null, LogLevel::WARNING), + E_WARNING => array(null, LogLevel::WARNING), + E_USER_WARNING => array(null, LogLevel::WARNING), + E_COMPILE_WARNING => array(null, LogLevel::WARNING), + E_CORE_WARNING => array(null, LogLevel::WARNING), + E_USER_ERROR => array(null, LogLevel::CRITICAL), + E_RECOVERABLE_ERROR => array(null, LogLevel::CRITICAL), + E_COMPILE_ERROR => array(null, LogLevel::CRITICAL), + E_PARSE => array(null, LogLevel::CRITICAL), + E_ERROR => array(null, LogLevel::CRITICAL), + E_CORE_ERROR => array(null, LogLevel::CRITICAL), + ); + + private $thrownErrors = 0x1FFF; // E_ALL - E_DEPRECATED - E_USER_DEPRECATED + private $scopedErrors = 0x1FFF; // E_ALL - E_DEPRECATED - E_USER_DEPRECATED + private $tracedErrors = 0x77FB; // E_ALL - E_STRICT - E_PARSE + private $screamedErrors = 0x55; // E_ERROR + E_CORE_ERROR + E_COMPILE_ERROR + E_PARSE + private $loggedErrors = 0; + private $traceReflector; + + private $isRecursive = 0; + private $isRoot = false; + private $exceptionHandler; + private $bootstrappingLogger; + + private static $reservedMemory; + private static $stackedErrors = array(); + private static $stackedErrorLevels = array(); + private static $toStringException = null; + private static $silencedErrorCache = array(); + private static $silencedErrorCount = 0; + private static $exitCode = 0; + + /** + * Registers the error handler. + * + * @param self|null $handler The handler to register + * @param bool $replace Whether to replace or not any existing handler + * + * @return self The registered error handler + */ + public static function register(self $handler = null, $replace = true) + { + if (null === self::$reservedMemory) { + self::$reservedMemory = str_repeat('x', 10240); + register_shutdown_function(__CLASS__.'::handleFatalError'); + } + + if ($handlerIsNew = null === $handler) { + $handler = new static(); + } + + if (null === $prev = set_error_handler(array($handler, 'handleError'))) { + restore_error_handler(); + // Specifying the error types earlier would expose us to https://bugs.php.net/63206 + set_error_handler(array($handler, 'handleError'), $handler->thrownErrors | $handler->loggedErrors); + $handler->isRoot = true; + } + + if ($handlerIsNew && is_array($prev) && $prev[0] instanceof self) { + $handler = $prev[0]; + $replace = false; + } + if ($replace || !$prev) { + $handler->setExceptionHandler(set_exception_handler(array($handler, 'handleException'))); + } else { + restore_error_handler(); + } + + $handler->throwAt(E_ALL & $handler->thrownErrors, true); + + return $handler; + } + + public function __construct(BufferingLogger $bootstrappingLogger = null) + { + if ($bootstrappingLogger) { + $this->bootstrappingLogger = $bootstrappingLogger; + $this->setDefaultLogger($bootstrappingLogger); + } + $this->traceReflector = new \ReflectionProperty('Exception', 'trace'); + $this->traceReflector->setAccessible(true); + } + + /** + * Sets a logger to non assigned errors levels. + * + * @param LoggerInterface $logger A PSR-3 logger to put as default for the given levels + * @param array|int $levels An array map of E_* to LogLevel::* or an integer bit field of E_* constants + * @param bool $replace Whether to replace or not any existing logger + */ + public function setDefaultLogger(LoggerInterface $logger, $levels = E_ALL, $replace = false) + { + $loggers = array(); + + if (is_array($levels)) { + foreach ($levels as $type => $logLevel) { + if (empty($this->loggers[$type][0]) || $replace || $this->loggers[$type][0] === $this->bootstrappingLogger) { + $loggers[$type] = array($logger, $logLevel); + } + } + } else { + if (null === $levels) { + $levels = E_ALL; + } + foreach ($this->loggers as $type => $log) { + if (($type & $levels) && (empty($log[0]) || $replace || $log[0] === $this->bootstrappingLogger)) { + $log[0] = $logger; + $loggers[$type] = $log; + } + } + } + + $this->setLoggers($loggers); + } + + /** + * Sets a logger for each error level. + * + * @param array $loggers Error levels to [LoggerInterface|null, LogLevel::*] map + * + * @return array The previous map + * + * @throws \InvalidArgumentException + */ + public function setLoggers(array $loggers) + { + $prevLogged = $this->loggedErrors; + $prev = $this->loggers; + $flush = array(); + + foreach ($loggers as $type => $log) { + if (!isset($prev[$type])) { + throw new \InvalidArgumentException('Unknown error type: '.$type); + } + if (!is_array($log)) { + $log = array($log); + } elseif (!array_key_exists(0, $log)) { + throw new \InvalidArgumentException('No logger provided'); + } + if (null === $log[0]) { + $this->loggedErrors &= ~$type; + } elseif ($log[0] instanceof LoggerInterface) { + $this->loggedErrors |= $type; + } else { + throw new \InvalidArgumentException('Invalid logger provided'); + } + $this->loggers[$type] = $log + $prev[$type]; + + if ($this->bootstrappingLogger && $prev[$type][0] === $this->bootstrappingLogger) { + $flush[$type] = $type; + } + } + $this->reRegister($prevLogged | $this->thrownErrors); + + if ($flush) { + foreach ($this->bootstrappingLogger->cleanLogs() as $log) { + $type = $log[2]['exception'] instanceof \ErrorException ? $log[2]['exception']->getSeverity() : E_ERROR; + if (!isset($flush[$type])) { + $this->bootstrappingLogger->log($log[0], $log[1], $log[2]); + } elseif ($this->loggers[$type][0]) { + $this->loggers[$type][0]->log($this->loggers[$type][1], $log[1], $log[2]); + } + } + } + + return $prev; + } + + /** + * Sets a user exception handler. + * + * @param callable $handler A handler that will be called on Exception + * + * @return callable|null The previous exception handler + */ + public function setExceptionHandler(callable $handler = null) + { + $prev = $this->exceptionHandler; + $this->exceptionHandler = $handler; + + return $prev; + } + + /** + * Sets the PHP error levels that throw an exception when a PHP error occurs. + * + * @param int $levels A bit field of E_* constants for thrown errors + * @param bool $replace Replace or amend the previous value + * + * @return int The previous value + */ + public function throwAt($levels, $replace = false) + { + $prev = $this->thrownErrors; + $this->thrownErrors = ($levels | E_RECOVERABLE_ERROR | E_USER_ERROR) & ~E_USER_DEPRECATED & ~E_DEPRECATED; + if (!$replace) { + $this->thrownErrors |= $prev; + } + $this->reRegister($prev | $this->loggedErrors); + + return $prev; + } + + /** + * Sets the PHP error levels for which local variables are preserved. + * + * @param int $levels A bit field of E_* constants for scoped errors + * @param bool $replace Replace or amend the previous value + * + * @return int The previous value + */ + public function scopeAt($levels, $replace = false) + { + $prev = $this->scopedErrors; + $this->scopedErrors = (int) $levels; + if (!$replace) { + $this->scopedErrors |= $prev; + } + + return $prev; + } + + /** + * Sets the PHP error levels for which the stack trace is preserved. + * + * @param int $levels A bit field of E_* constants for traced errors + * @param bool $replace Replace or amend the previous value + * + * @return int The previous value + */ + public function traceAt($levels, $replace = false) + { + $prev = $this->tracedErrors; + $this->tracedErrors = (int) $levels; + if (!$replace) { + $this->tracedErrors |= $prev; + } + + return $prev; + } + + /** + * Sets the error levels where the @-operator is ignored. + * + * @param int $levels A bit field of E_* constants for screamed errors + * @param bool $replace Replace or amend the previous value + * + * @return int The previous value + */ + public function screamAt($levels, $replace = false) + { + $prev = $this->screamedErrors; + $this->screamedErrors = (int) $levels; + if (!$replace) { + $this->screamedErrors |= $prev; + } + + return $prev; + } + + /** + * Re-registers as a PHP error handler if levels changed. + */ + private function reRegister($prev) + { + if ($prev !== $this->thrownErrors | $this->loggedErrors) { + $handler = set_error_handler('var_dump'); + $handler = is_array($handler) ? $handler[0] : null; + restore_error_handler(); + if ($handler === $this) { + restore_error_handler(); + if ($this->isRoot) { + set_error_handler(array($this, 'handleError'), $this->thrownErrors | $this->loggedErrors); + } else { + set_error_handler(array($this, 'handleError')); + } + } + } + } + + /** + * Handles errors by filtering then logging them according to the configured bit fields. + * + * @param int $type One of the E_* constants + * @param string $message + * @param string $file + * @param int $line + * + * @return bool Returns false when no handling happens so that the PHP engine can handle the error itself + * + * @throws \ErrorException When $this->thrownErrors requests so + * + * @internal + */ + public function handleError($type, $message, $file, $line) + { + // Level is the current error reporting level to manage silent error. + // Strong errors are not authorized to be silenced. + $level = error_reporting() | E_RECOVERABLE_ERROR | E_USER_ERROR | E_DEPRECATED | E_USER_DEPRECATED; + $log = $this->loggedErrors & $type; + $throw = $this->thrownErrors & $type & $level; + $type &= $level | $this->screamedErrors; + + if (!$type || (!$log && !$throw)) { + return $type && $log; + } + $scope = $this->scopedErrors & $type; + + if (4 < $numArgs = func_num_args()) { + $context = $scope ? (func_get_arg(4) ?: array()) : array(); + $backtrace = 5 < $numArgs ? func_get_arg(5) : null; // defined on HHVM + } else { + $context = array(); + $backtrace = null; + } + + if (isset($context['GLOBALS']) && $scope) { + $e = $context; // Whatever the signature of the method, + unset($e['GLOBALS'], $context); // $context is always a reference in 5.3 + $context = $e; + } + + if (null !== $backtrace && $type & E_ERROR) { + // E_ERROR fatal errors are triggered on HHVM when + // hhvm.error_handling.call_user_handler_on_fatals=1 + // which is the way to get their backtrace. + $this->handleFatalError(compact('type', 'message', 'file', 'line', 'backtrace')); + + return true; + } + + $logMessage = $this->levels[$type].': '.$message; + + if (null !== self::$toStringException) { + $errorAsException = self::$toStringException; + self::$toStringException = null; + } elseif (!$throw && !($type & $level)) { + if (!isset(self::$silencedErrorCache[$id = $file.':'.$line])) { + $lightTrace = $this->tracedErrors & $type ? $this->cleanTrace(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3), $type, $file, $line, false) : array(); + $errorAsException = new SilencedErrorContext($type, $file, $line, $lightTrace); + } elseif (isset(self::$silencedErrorCache[$id][$message])) { + $lightTrace = null; + $errorAsException = self::$silencedErrorCache[$id][$message]; + ++$errorAsException->count; + } else { + $lightTrace = array(); + $errorAsException = null; + } + + if (100 < ++self::$silencedErrorCount) { + self::$silencedErrorCache = $lightTrace = array(); + self::$silencedErrorCount = 1; + } + if ($errorAsException) { + self::$silencedErrorCache[$id][$message] = $errorAsException; + } + if (null === $lightTrace) { + return; + } + } else { + if ($scope) { + $errorAsException = new ContextErrorException($logMessage, 0, $type, $file, $line, $context); + } else { + $errorAsException = new \ErrorException($logMessage, 0, $type, $file, $line); + } + + // Clean the trace by removing function arguments and the first frames added by the error handler itself. + if ($throw || $this->tracedErrors & $type) { + $backtrace = $backtrace ?: $errorAsException->getTrace(); + $lightTrace = $this->cleanTrace($backtrace, $type, $file, $line, $throw); + $this->traceReflector->setValue($errorAsException, $lightTrace); + } else { + $this->traceReflector->setValue($errorAsException, array()); + } + } + + if ($throw) { + if (E_USER_ERROR & $type) { + for ($i = 1; isset($backtrace[$i]); ++$i) { + if (isset($backtrace[$i]['function'], $backtrace[$i]['type'], $backtrace[$i - 1]['function']) + && '__toString' === $backtrace[$i]['function'] + && '->' === $backtrace[$i]['type'] + && !isset($backtrace[$i - 1]['class']) + && ('trigger_error' === $backtrace[$i - 1]['function'] || 'user_error' === $backtrace[$i - 1]['function']) + ) { + // Here, we know trigger_error() has been called from __toString(). + // HHVM is fine with throwing from __toString() but PHP triggers a fatal error instead. + // A small convention allows working around the limitation: + // given a caught $e exception in __toString(), quitting the method with + // `return trigger_error($e, E_USER_ERROR);` allows this error handler + // to make $e get through the __toString() barrier. + + foreach ($context as $e) { + if (($e instanceof \Exception || $e instanceof \Throwable) && $e->__toString() === $message) { + if (1 === $i) { + // On HHVM + $errorAsException = $e; + break; + } + self::$toStringException = $e; + + return true; + } + } + + if (1 < $i) { + // On PHP (not on HHVM), display the original error message instead of the default one. + $this->handleException($errorAsException); + + // Stop the process by giving back the error to the native handler. + return false; + } + } + } + } + + throw $errorAsException; + } + + if ($this->isRecursive) { + $log = 0; + } elseif (self::$stackedErrorLevels) { + self::$stackedErrors[] = array( + $this->loggers[$type][0], + ($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG, + $logMessage, + $errorAsException ? array('exception' => $errorAsException) : array(), + ); + } else { + try { + $this->isRecursive = true; + $level = ($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG; + $this->loggers[$type][0]->log($level, $logMessage, $errorAsException ? array('exception' => $errorAsException) : array()); + } finally { + $this->isRecursive = false; + } + } + + return $type && $log; + } + + /** + * Handles an exception by logging then forwarding it to another handler. + * + * @param \Exception|\Throwable $exception An exception to handle + * @param array $error An array as returned by error_get_last() + * + * @internal + */ + public function handleException($exception, array $error = null) + { + if (null === $error) { + self::$exitCode = 255; + } + if (!$exception instanceof \Exception) { + $exception = new FatalThrowableError($exception); + } + $type = $exception instanceof FatalErrorException ? $exception->getSeverity() : E_ERROR; + $handlerException = null; + + if (($this->loggedErrors & $type) || $exception instanceof FatalThrowableError) { + if ($exception instanceof FatalErrorException) { + if ($exception instanceof FatalThrowableError) { + $error = array( + 'type' => $type, + 'message' => $message = $exception->getMessage(), + 'file' => $exception->getFile(), + 'line' => $exception->getLine(), + ); + } else { + $message = 'Fatal '.$exception->getMessage(); + } + } elseif ($exception instanceof \ErrorException) { + $message = 'Uncaught '.$exception->getMessage(); + } else { + $message = 'Uncaught Exception: '.$exception->getMessage(); + } + } + if ($this->loggedErrors & $type) { + try { + $this->loggers[$type][0]->log($this->loggers[$type][1], $message, array('exception' => $exception)); + } catch (\Exception $handlerException) { + } catch (\Throwable $handlerException) { + } + } + if ($exception instanceof FatalErrorException && !$exception instanceof OutOfMemoryException && $error) { + foreach ($this->getFatalErrorHandlers() as $handler) { + if ($e = $handler->handleError($error, $exception)) { + $exception = $e; + break; + } + } + } + try { + if (null !== $this->exceptionHandler) { + return \call_user_func($this->exceptionHandler, $exception); + } + $handlerException = $handlerException ?: $exception; + } catch (\Exception $handlerException) { + } catch (\Throwable $handlerException) { + } + $this->exceptionHandler = null; + if ($exception === $handlerException) { + self::$reservedMemory = null; // Disable the fatal error handler + throw $exception; // Give back $exception to the native handler + } + $this->handleException($handlerException); + } + + /** + * Shutdown registered function for handling PHP fatal errors. + * + * @param array $error An array as returned by error_get_last() + * + * @internal + */ + public static function handleFatalError(array $error = null) + { + if (null === self::$reservedMemory) { + return; + } + + $handler = self::$reservedMemory = null; + $handlers = array(); + + while (!is_array($handler) || !$handler[0] instanceof self) { + $handler = set_exception_handler('var_dump'); + restore_exception_handler(); + + if (!$handler) { + break; + } + restore_exception_handler(); + array_unshift($handlers, $handler); + } + foreach ($handlers as $h) { + set_exception_handler($h); + } + if (!$handler) { + return; + } + if ($handler !== $h) { + $handler[0]->setExceptionHandler($h); + } + $handler = $handler[0]; + $handlers = array(); + + if ($exit = null === $error) { + $error = error_get_last(); + } + + try { + while (self::$stackedErrorLevels) { + static::unstackErrors(); + } + } catch (\Exception $exception) { + // Handled below + } catch (\Throwable $exception) { + // Handled below + } + + if ($error && $error['type'] &= E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR) { + // Let's not throw anymore but keep logging + $handler->throwAt(0, true); + $trace = isset($error['backtrace']) ? $error['backtrace'] : null; + + if (0 === strpos($error['message'], 'Allowed memory') || 0 === strpos($error['message'], 'Out of memory')) { + $exception = new OutOfMemoryException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, false, $trace); + } else { + $exception = new FatalErrorException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, true, $trace); + } + } + + try { + if (isset($exception)) { + self::$exitCode = 255; + $handler->handleException($exception, $error); + } + } catch (FatalErrorException $e) { + // Ignore this re-throw + } + + if ($exit && self::$exitCode) { + $exitCode = self::$exitCode; + register_shutdown_function('register_shutdown_function', function () use ($exitCode) { exit($exitCode); }); + } + } + + /** + * Configures the error handler for delayed handling. + * Ensures also that non-catchable fatal errors are never silenced. + * + * As shown by http://bugs.php.net/42098 and http://bugs.php.net/60724 + * PHP has a compile stage where it behaves unusually. To workaround it, + * we plug an error handler that only stacks errors for later. + * + * The most important feature of this is to prevent + * autoloading until unstackErrors() is called. + * + * @deprecated since version 3.4, to be removed in 4.0. + */ + public static function stackErrors() + { + @trigger_error('Support for stacking errors is deprecated since Symfony 3.4 and will be removed in 4.0.', E_USER_DEPRECATED); + + self::$stackedErrorLevels[] = error_reporting(error_reporting() | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR); + } + + /** + * Unstacks stacked errors and forwards to the logger. + * + * @deprecated since version 3.4, to be removed in 4.0. + */ + public static function unstackErrors() + { + @trigger_error('Support for unstacking errors is deprecated since Symfony 3.4 and will be removed in 4.0.', E_USER_DEPRECATED); + + $level = array_pop(self::$stackedErrorLevels); + + if (null !== $level) { + $errorReportingLevel = error_reporting($level); + if ($errorReportingLevel !== ($level | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR)) { + // If the user changed the error level, do not overwrite it + error_reporting($errorReportingLevel); + } + } + + if (empty(self::$stackedErrorLevels)) { + $errors = self::$stackedErrors; + self::$stackedErrors = array(); + + foreach ($errors as $error) { + $error[0]->log($error[1], $error[2], $error[3]); + } + } + } + + /** + * Gets the fatal error handlers. + * + * Override this method if you want to define more fatal error handlers. + * + * @return FatalErrorHandlerInterface[] An array of FatalErrorHandlerInterface + */ + protected function getFatalErrorHandlers() + { + return array( + new UndefinedFunctionFatalErrorHandler(), + new UndefinedMethodFatalErrorHandler(), + new ClassNotFoundFatalErrorHandler(), + ); + } + + private function cleanTrace($backtrace, $type, $file, $line, $throw) + { + $lightTrace = $backtrace; + + for ($i = 0; isset($backtrace[$i]); ++$i) { + if (isset($backtrace[$i]['file'], $backtrace[$i]['line']) && $backtrace[$i]['line'] === $line && $backtrace[$i]['file'] === $file) { + $lightTrace = array_slice($lightTrace, 1 + $i); + break; + } + } + if (!($throw || $this->scopedErrors & $type)) { + for ($i = 0; isset($lightTrace[$i]); ++$i) { + unset($lightTrace[$i]['args'], $lightTrace[$i]['object']); + } + } + + return $lightTrace; + } +} diff --git a/vendor/symfony/debug/Exception/ClassNotFoundException.php b/vendor/symfony/debug/Exception/ClassNotFoundException.php new file mode 100644 index 00000000..b91bf466 --- /dev/null +++ b/vendor/symfony/debug/Exception/ClassNotFoundException.php @@ -0,0 +1,33 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Debug\Exception; + +/** + * Class (or Trait or Interface) Not Found Exception. + * + * @author Konstanton Myakshin <koc-dp@yandex.ru> + */ +class ClassNotFoundException extends FatalErrorException +{ + public function __construct($message, \ErrorException $previous) + { + parent::__construct( + $message, + $previous->getCode(), + $previous->getSeverity(), + $previous->getFile(), + $previous->getLine(), + $previous->getPrevious() + ); + $this->setTrace($previous->getTrace()); + } +} diff --git a/vendor/symfony/debug/Exception/ContextErrorException.php b/vendor/symfony/debug/Exception/ContextErrorException.php new file mode 100644 index 00000000..6561d4df --- /dev/null +++ b/vendor/symfony/debug/Exception/ContextErrorException.php @@ -0,0 +1,40 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Debug\Exception; + +/** + * Error Exception with Variable Context. + * + * @author Christian Sciberras <uuf6429@gmail.com> + * + * @deprecated since version 3.3. Instead, \ErrorException will be used directly in 4.0. + */ +class ContextErrorException extends \ErrorException +{ + private $context = array(); + + public function __construct($message, $code, $severity, $filename, $lineno, $context = array()) + { + parent::__construct($message, $code, $severity, $filename, $lineno); + $this->context = $context; + } + + /** + * @return array Array of variables that existed when the exception occurred + */ + public function getContext() + { + @trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0.', __CLASS__), E_USER_DEPRECATED); + + return $this->context; + } +} diff --git a/vendor/symfony/debug/Exception/FatalErrorException.php b/vendor/symfony/debug/Exception/FatalErrorException.php new file mode 100644 index 00000000..f24a54e7 --- /dev/null +++ b/vendor/symfony/debug/Exception/FatalErrorException.php @@ -0,0 +1,82 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Debug\Exception; + +/** + * Fatal Error Exception. + * + * @author Konstanton Myakshin <koc-dp@yandex.ru> + */ +class FatalErrorException extends \ErrorException +{ + public function __construct($message, $code, $severity, $filename, $lineno, $traceOffset = null, $traceArgs = true, array $trace = null) + { + parent::__construct($message, $code, $severity, $filename, $lineno); + + if (null !== $trace) { + if (!$traceArgs) { + foreach ($trace as &$frame) { + unset($frame['args'], $frame['this'], $frame); + } + } + + $this->setTrace($trace); + } elseif (null !== $traceOffset) { + if (function_exists('xdebug_get_function_stack')) { + $trace = xdebug_get_function_stack(); + if (0 < $traceOffset) { + array_splice($trace, -$traceOffset); + } + + foreach ($trace as &$frame) { + if (!isset($frame['type'])) { + // XDebug pre 2.1.1 doesn't currently set the call type key http://bugs.xdebug.org/view.php?id=695 + if (isset($frame['class'])) { + $frame['type'] = '::'; + } + } elseif ('dynamic' === $frame['type']) { + $frame['type'] = '->'; + } elseif ('static' === $frame['type']) { + $frame['type'] = '::'; + } + + // XDebug also has a different name for the parameters array + if (!$traceArgs) { + unset($frame['params'], $frame['args']); + } elseif (isset($frame['params']) && !isset($frame['args'])) { + $frame['args'] = $frame['params']; + unset($frame['params']); + } + } + + unset($frame); + $trace = array_reverse($trace); + } elseif (function_exists('symfony_debug_backtrace')) { + $trace = symfony_debug_backtrace(); + if (0 < $traceOffset) { + array_splice($trace, 0, $traceOffset); + } + } else { + $trace = array(); + } + + $this->setTrace($trace); + } + } + + protected function setTrace($trace) + { + $traceReflector = new \ReflectionProperty('Exception', 'trace'); + $traceReflector->setAccessible(true); + $traceReflector->setValue($this, $trace); + } +} diff --git a/vendor/symfony/debug/Exception/FatalThrowableError.php b/vendor/symfony/debug/Exception/FatalThrowableError.php new file mode 100644 index 00000000..34f43b17 --- /dev/null +++ b/vendor/symfony/debug/Exception/FatalThrowableError.php @@ -0,0 +1,44 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Debug\Exception; + +/** + * Fatal Throwable Error. + * + * @author Nicolas Grekas <p@tchwork.com> + */ +class FatalThrowableError extends FatalErrorException +{ + public function __construct(\Throwable $e) + { + if ($e instanceof \ParseError) { + $message = 'Parse error: '.$e->getMessage(); + $severity = E_PARSE; + } elseif ($e instanceof \TypeError) { + $message = 'Type error: '.$e->getMessage(); + $severity = E_RECOVERABLE_ERROR; + } else { + $message = $e->getMessage(); + $severity = E_ERROR; + } + + \ErrorException::__construct( + $message, + $e->getCode(), + $severity, + $e->getFile(), + $e->getLine() + ); + + $this->setTrace($e->getTrace()); + } +} diff --git a/vendor/symfony/debug/Exception/FlattenException.php b/vendor/symfony/debug/Exception/FlattenException.php new file mode 100644 index 00000000..24679dca --- /dev/null +++ b/vendor/symfony/debug/Exception/FlattenException.php @@ -0,0 +1,263 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Debug\Exception; + +use Symfony\Component\HttpFoundation\Exception\RequestExceptionInterface; +use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; + +/** + * FlattenException wraps a PHP Exception to be able to serialize it. + * + * Basically, this class removes all objects from the trace. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class FlattenException +{ + private $message; + private $code; + private $previous; + private $trace; + private $class; + private $statusCode; + private $headers; + private $file; + private $line; + + public static function create(\Exception $exception, $statusCode = null, array $headers = array()) + { + $e = new static(); + $e->setMessage($exception->getMessage()); + $e->setCode($exception->getCode()); + + if ($exception instanceof HttpExceptionInterface) { + $statusCode = $exception->getStatusCode(); + $headers = array_merge($headers, $exception->getHeaders()); + } elseif ($exception instanceof RequestExceptionInterface) { + $statusCode = 400; + } + + if (null === $statusCode) { + $statusCode = 500; + } + + $e->setStatusCode($statusCode); + $e->setHeaders($headers); + $e->setTraceFromException($exception); + $e->setClass(get_class($exception)); + $e->setFile($exception->getFile()); + $e->setLine($exception->getLine()); + + $previous = $exception->getPrevious(); + + if ($previous instanceof \Exception) { + $e->setPrevious(static::create($previous)); + } elseif ($previous instanceof \Throwable) { + $e->setPrevious(static::create(new FatalThrowableError($previous))); + } + + return $e; + } + + public function toArray() + { + $exceptions = array(); + foreach (array_merge(array($this), $this->getAllPrevious()) as $exception) { + $exceptions[] = array( + 'message' => $exception->getMessage(), + 'class' => $exception->getClass(), + 'trace' => $exception->getTrace(), + ); + } + + return $exceptions; + } + + public function getStatusCode() + { + return $this->statusCode; + } + + public function setStatusCode($code) + { + $this->statusCode = $code; + } + + public function getHeaders() + { + return $this->headers; + } + + public function setHeaders(array $headers) + { + $this->headers = $headers; + } + + public function getClass() + { + return $this->class; + } + + public function setClass($class) + { + $this->class = $class; + } + + public function getFile() + { + return $this->file; + } + + public function setFile($file) + { + $this->file = $file; + } + + public function getLine() + { + return $this->line; + } + + public function setLine($line) + { + $this->line = $line; + } + + public function getMessage() + { + return $this->message; + } + + public function setMessage($message) + { + $this->message = $message; + } + + public function getCode() + { + return $this->code; + } + + public function setCode($code) + { + $this->code = $code; + } + + public function getPrevious() + { + return $this->previous; + } + + public function setPrevious(FlattenException $previous) + { + $this->previous = $previous; + } + + public function getAllPrevious() + { + $exceptions = array(); + $e = $this; + while ($e = $e->getPrevious()) { + $exceptions[] = $e; + } + + return $exceptions; + } + + public function getTrace() + { + return $this->trace; + } + + public function setTraceFromException(\Exception $exception) + { + $this->setTrace($exception->getTrace(), $exception->getFile(), $exception->getLine()); + } + + public function setTrace($trace, $file, $line) + { + $this->trace = array(); + $this->trace[] = array( + 'namespace' => '', + 'short_class' => '', + 'class' => '', + 'type' => '', + 'function' => '', + 'file' => $file, + 'line' => $line, + 'args' => array(), + ); + foreach ($trace as $entry) { + $class = ''; + $namespace = ''; + if (isset($entry['class'])) { + $parts = explode('\\', $entry['class']); + $class = array_pop($parts); + $namespace = implode('\\', $parts); + } + + $this->trace[] = array( + 'namespace' => $namespace, + 'short_class' => $class, + 'class' => isset($entry['class']) ? $entry['class'] : '', + 'type' => isset($entry['type']) ? $entry['type'] : '', + 'function' => isset($entry['function']) ? $entry['function'] : null, + 'file' => isset($entry['file']) ? $entry['file'] : null, + 'line' => isset($entry['line']) ? $entry['line'] : null, + 'args' => isset($entry['args']) ? $this->flattenArgs($entry['args']) : array(), + ); + } + } + + private function flattenArgs($args, $level = 0, &$count = 0) + { + $result = array(); + foreach ($args as $key => $value) { + if (++$count > 1e4) { + return array('array', '*SKIPPED over 10000 entries*'); + } + if ($value instanceof \__PHP_Incomplete_Class) { + // is_object() returns false on PHP<=7.1 + $result[$key] = array('incomplete-object', $this->getClassNameFromIncomplete($value)); + } elseif (is_object($value)) { + $result[$key] = array('object', get_class($value)); + } elseif (is_array($value)) { + if ($level > 10) { + $result[$key] = array('array', '*DEEP NESTED ARRAY*'); + } else { + $result[$key] = array('array', $this->flattenArgs($value, $level + 1, $count)); + } + } elseif (null === $value) { + $result[$key] = array('null', null); + } elseif (is_bool($value)) { + $result[$key] = array('boolean', $value); + } elseif (is_int($value)) { + $result[$key] = array('integer', $value); + } elseif (is_float($value)) { + $result[$key] = array('float', $value); + } elseif (is_resource($value)) { + $result[$key] = array('resource', get_resource_type($value)); + } else { + $result[$key] = array('string', (string) $value); + } + } + + return $result; + } + + private function getClassNameFromIncomplete(\__PHP_Incomplete_Class $value) + { + $array = new \ArrayObject($value); + + return $array['__PHP_Incomplete_Class_Name']; + } +} diff --git a/vendor/symfony/debug/Exception/OutOfMemoryException.php b/vendor/symfony/debug/Exception/OutOfMemoryException.php new file mode 100644 index 00000000..fec19798 --- /dev/null +++ b/vendor/symfony/debug/Exception/OutOfMemoryException.php @@ -0,0 +1,21 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Debug\Exception; + +/** + * Out of memory exception. + * + * @author Nicolas Grekas <p@tchwork.com> + */ +class OutOfMemoryException extends FatalErrorException +{ +} diff --git a/vendor/symfony/debug/Exception/SilencedErrorContext.php b/vendor/symfony/debug/Exception/SilencedErrorContext.php new file mode 100644 index 00000000..4be83491 --- /dev/null +++ b/vendor/symfony/debug/Exception/SilencedErrorContext.php @@ -0,0 +1,67 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Debug\Exception; + +/** + * Data Object that represents a Silenced Error. + * + * @author Grégoire Pineau <lyrixx@lyrixx.info> + */ +class SilencedErrorContext implements \JsonSerializable +{ + public $count = 1; + + private $severity; + private $file; + private $line; + private $trace; + + public function __construct($severity, $file, $line, array $trace = array(), $count = 1) + { + $this->severity = $severity; + $this->file = $file; + $this->line = $line; + $this->trace = $trace; + $this->count = $count; + } + + public function getSeverity() + { + return $this->severity; + } + + public function getFile() + { + return $this->file; + } + + public function getLine() + { + return $this->line; + } + + public function getTrace() + { + return $this->trace; + } + + public function JsonSerialize() + { + return array( + 'severity' => $this->severity, + 'file' => $this->file, + 'line' => $this->line, + 'trace' => $this->trace, + 'count' => $this->count, + ); + } +} diff --git a/vendor/symfony/debug/Exception/UndefinedFunctionException.php b/vendor/symfony/debug/Exception/UndefinedFunctionException.php new file mode 100644 index 00000000..a66ae2a3 --- /dev/null +++ b/vendor/symfony/debug/Exception/UndefinedFunctionException.php @@ -0,0 +1,33 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Debug\Exception; + +/** + * Undefined Function Exception. + * + * @author Konstanton Myakshin <koc-dp@yandex.ru> + */ +class UndefinedFunctionException extends FatalErrorException +{ + public function __construct($message, \ErrorException $previous) + { + parent::__construct( + $message, + $previous->getCode(), + $previous->getSeverity(), + $previous->getFile(), + $previous->getLine(), + $previous->getPrevious() + ); + $this->setTrace($previous->getTrace()); + } +} diff --git a/vendor/symfony/debug/Exception/UndefinedMethodException.php b/vendor/symfony/debug/Exception/UndefinedMethodException.php new file mode 100644 index 00000000..350dc318 --- /dev/null +++ b/vendor/symfony/debug/Exception/UndefinedMethodException.php @@ -0,0 +1,33 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Debug\Exception; + +/** + * Undefined Method Exception. + * + * @author Grégoire Pineau <lyrixx@lyrixx.info> + */ +class UndefinedMethodException extends FatalErrorException +{ + public function __construct($message, \ErrorException $previous) + { + parent::__construct( + $message, + $previous->getCode(), + $previous->getSeverity(), + $previous->getFile(), + $previous->getLine(), + $previous->getPrevious() + ); + $this->setTrace($previous->getTrace()); + } +} diff --git a/vendor/symfony/debug/ExceptionHandler.php b/vendor/symfony/debug/ExceptionHandler.php new file mode 100644 index 00000000..97470cb6 --- /dev/null +++ b/vendor/symfony/debug/ExceptionHandler.php @@ -0,0 +1,410 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Debug; + +use Symfony\Component\Debug\Exception\FlattenException; +use Symfony\Component\Debug\Exception\OutOfMemoryException; +use Symfony\Component\HttpKernel\Debug\FileLinkFormatter; + +/** + * ExceptionHandler converts an exception to a Response object. + * + * It is mostly useful in debug mode to replace the default PHP/XDebug + * output with something prettier and more useful. + * + * As this class is mainly used during Kernel boot, where nothing is yet + * available, the Response content is always HTML. + * + * @author Fabien Potencier <fabien@symfony.com> + * @author Nicolas Grekas <p@tchwork.com> + */ +class ExceptionHandler +{ + private $debug; + private $charset; + private $handler; + private $caughtBuffer; + private $caughtLength; + private $fileLinkFormat; + + public function __construct($debug = true, $charset = null, $fileLinkFormat = null) + { + $this->debug = $debug; + $this->charset = $charset ?: ini_get('default_charset') ?: 'UTF-8'; + $this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format'); + } + + /** + * Registers the exception handler. + * + * @param bool $debug Enable/disable debug mode, where the stack trace is displayed + * @param string|null $charset The charset used by exception messages + * @param string|null $fileLinkFormat The IDE link template + * + * @return static + */ + public static function register($debug = true, $charset = null, $fileLinkFormat = null) + { + $handler = new static($debug, $charset, $fileLinkFormat); + + $prev = set_exception_handler(array($handler, 'handle')); + if (is_array($prev) && $prev[0] instanceof ErrorHandler) { + restore_exception_handler(); + $prev[0]->setExceptionHandler(array($handler, 'handle')); + } + + return $handler; + } + + /** + * Sets a user exception handler. + * + * @param callable $handler An handler that will be called on Exception + * + * @return callable|null The previous exception handler if any + */ + public function setHandler(callable $handler = null) + { + $old = $this->handler; + $this->handler = $handler; + + return $old; + } + + /** + * Sets the format for links to source files. + * + * @param string|FileLinkFormatter $fileLinkFormat The format for links to source files + * + * @return string The previous file link format + */ + public function setFileLinkFormat($fileLinkFormat) + { + $old = $this->fileLinkFormat; + $this->fileLinkFormat = $fileLinkFormat; + + return $old; + } + + /** + * Sends a response for the given Exception. + * + * To be as fail-safe as possible, the exception is first handled + * by our simple exception handler, then by the user exception handler. + * The latter takes precedence and any output from the former is cancelled, + * if and only if nothing bad happens in this handling path. + */ + public function handle(\Exception $exception) + { + if (null === $this->handler || $exception instanceof OutOfMemoryException) { + $this->sendPhpResponse($exception); + + return; + } + + $caughtLength = $this->caughtLength = 0; + + ob_start(function ($buffer) { + $this->caughtBuffer = $buffer; + + return ''; + }); + + $this->sendPhpResponse($exception); + while (null === $this->caughtBuffer && ob_end_flush()) { + // Empty loop, everything is in the condition + } + if (isset($this->caughtBuffer[0])) { + ob_start(function ($buffer) { + if ($this->caughtLength) { + // use substr_replace() instead of substr() for mbstring overloading resistance + $cleanBuffer = substr_replace($buffer, '', 0, $this->caughtLength); + if (isset($cleanBuffer[0])) { + $buffer = $cleanBuffer; + } + } + + return $buffer; + }); + + echo $this->caughtBuffer; + $caughtLength = ob_get_length(); + } + $this->caughtBuffer = null; + + try { + call_user_func($this->handler, $exception); + $this->caughtLength = $caughtLength; + } catch (\Exception $e) { + if (!$caughtLength) { + // All handlers failed. Let PHP handle that now. + throw $exception; + } + } + } + + /** + * Sends the error associated with the given Exception as a plain PHP response. + * + * This method uses plain PHP functions like header() and echo to output + * the response. + * + * @param \Exception|FlattenException $exception An \Exception or FlattenException instance + */ + public function sendPhpResponse($exception) + { + if (!$exception instanceof FlattenException) { + $exception = FlattenException::create($exception); + } + + if (!headers_sent()) { + header(sprintf('HTTP/1.0 %s', $exception->getStatusCode())); + foreach ($exception->getHeaders() as $name => $value) { + header($name.': '.$value, false); + } + header('Content-Type: text/html; charset='.$this->charset); + } + + echo $this->decorate($this->getContent($exception), $this->getStylesheet($exception)); + } + + /** + * Gets the full HTML content associated with the given exception. + * + * @param \Exception|FlattenException $exception An \Exception or FlattenException instance + * + * @return string The HTML content as a string + */ + public function getHtml($exception) + { + if (!$exception instanceof FlattenException) { + $exception = FlattenException::create($exception); + } + + return $this->decorate($this->getContent($exception), $this->getStylesheet($exception)); + } + + /** + * Gets the HTML content associated with the given exception. + * + * @return string The content as a string + */ + public function getContent(FlattenException $exception) + { + switch ($exception->getStatusCode()) { + case 404: + $title = 'Sorry, the page you are looking for could not be found.'; + break; + default: + $title = 'Whoops, looks like something went wrong.'; + } + + $content = ''; + if ($this->debug) { + try { + $count = count($exception->getAllPrevious()); + $total = $count + 1; + foreach ($exception->toArray() as $position => $e) { + $ind = $count - $position + 1; + $class = $this->formatClass($e['class']); + $message = nl2br($this->escapeHtml($e['message'])); + $content .= sprintf(<<<'EOF' + <div class="trace trace-as-html"> + <table class="trace-details"> + <thead class="trace-head"><tr><th> + <h3 class="trace-class"> + <span class="text-muted">(%d/%d)</span> + <span class="exception_title">%s</span> + </h3> + <p class="break-long-words trace-message">%s</p> + </th></tr></thead> + <tbody> +EOF + , $ind, $total, $class, $message); + foreach ($e['trace'] as $trace) { + $content .= '<tr><td>'; + if ($trace['function']) { + $content .= sprintf('at <span class="trace-class">%s</span><span class="trace-type">%s</span><span class="trace-method">%s</span>(<span class="trace-arguments">%s</span>)', $this->formatClass($trace['class']), $trace['type'], $trace['function'], $this->formatArgs($trace['args'])); + } + if (isset($trace['file']) && isset($trace['line'])) { + $content .= $this->formatPath($trace['file'], $trace['line']); + } + $content .= "</td></tr>\n"; + } + + $content .= "</tbody>\n</table>\n</div>\n"; + } + } catch (\Exception $e) { + // something nasty happened and we cannot throw an exception anymore + if ($this->debug) { + $title = sprintf('Exception thrown when handling an exception (%s: %s)', get_class($e), $this->escapeHtml($e->getMessage())); + } else { + $title = 'Whoops, looks like something went wrong.'; + } + } + } + + $symfonyGhostImageContents = $this->getSymfonyGhostAsSvg(); + + return <<<EOF + <div class="exception-summary"> + <div class="container"> + <div class="exception-message-wrapper"> + <h1 class="break-long-words exception-message">$title</h1> + <div class="exception-illustration hidden-xs-down">$symfonyGhostImageContents</div> + </div> + </div> + </div> + + <div class="container"> + $content + </div> +EOF; + } + + /** + * Gets the stylesheet associated with the given exception. + * + * @return string The stylesheet as a string + */ + public function getStylesheet(FlattenException $exception) + { + return <<<'EOF' + body { background-color: #F9F9F9; color: #222; font: 14px/1.4 Helvetica, Arial, sans-serif; margin: 0; padding-bottom: 45px; } + + a { cursor: pointer; text-decoration: none; } + a:hover { text-decoration: underline; } + abbr[title] { border-bottom: none; cursor: help; text-decoration: none; } + + code, pre { font: 13px/1.5 Consolas, Monaco, Menlo, "Ubuntu Mono", "Liberation Mono", monospace; } + + table, tr, th, td { background: #FFF; border-collapse: collapse; vertical-align: top; } + table { background: #FFF; border: 1px solid #E0E0E0; box-shadow: 0px 0px 1px rgba(128, 128, 128, .2); margin: 1em 0; width: 100%; } + table th, table td { border: solid #E0E0E0; border-width: 1px 0; padding: 8px 10px; } + table th { background-color: #E0E0E0; font-weight: bold; text-align: left; } + + .hidden-xs-down { display: none; } + .block { display: block; } + .break-long-words { -ms-word-break: break-all; word-break: break-all; word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; } + .text-muted { color: #999; } + + .container { max-width: 1024px; margin: 0 auto; padding: 0 15px; } + .container::after { content: ""; display: table; clear: both; } + + .exception-summary { background: #B0413E; border-bottom: 2px solid rgba(0, 0, 0, 0.1); border-top: 1px solid rgba(0, 0, 0, .3); flex: 0 0 auto; margin-bottom: 30px; } + + .exception-message-wrapper { display: flex; align-items: center; min-height: 70px; } + .exception-message { flex-grow: 1; padding: 30px 0; } + .exception-message, .exception-message a { color: #FFF; font-size: 21px; font-weight: 400; margin: 0; } + .exception-message.long { font-size: 18px; } + .exception-message a { border-bottom: 1px solid rgba(255, 255, 255, 0.5); font-size: inherit; text-decoration: none; } + .exception-message a:hover { border-bottom-color: #ffffff; } + + .exception-illustration { flex-basis: 111px; flex-shrink: 0; height: 66px; margin-left: 15px; opacity: .7; } + + .trace + .trace { margin-top: 30px; } + .trace-head .trace-class { color: #222; font-size: 18px; font-weight: bold; line-height: 1.3; margin: 0; position: relative; } + + .trace-message { font-size: 14px; font-weight: normal; margin: .5em 0 0; } + + .trace-file-path, .trace-file-path a { color: #222; margin-top: 3px; font-size: 13px; } + .trace-class { color: #B0413E; } + .trace-type { padding: 0 2px; } + .trace-method { color: #B0413E; font-weight: bold; } + .trace-arguments { color: #777; font-weight: normal; padding-left: 2px; } + + @media (min-width: 575px) { + .hidden-xs-down { display: initial; } + } +EOF; + } + + private function decorate($content, $css) + { + return <<<EOF +<!DOCTYPE html> +<html> + <head> + <meta charset="{$this->charset}" /> + <meta name="robots" content="noindex,nofollow" /> + <style>$css</style> + </head> + <body> + $content + </body> +</html> +EOF; + } + + private function formatClass($class) + { + $parts = explode('\\', $class); + + return sprintf('<abbr title="%s">%s</abbr>', $class, array_pop($parts)); + } + + private function formatPath($path, $line) + { + $file = $this->escapeHtml(preg_match('#[^/\\\\]*+$#', $path, $file) ? $file[0] : $path); + $fmt = $this->fileLinkFormat; + + if ($fmt && $link = is_string($fmt) ? strtr($fmt, array('%f' => $path, '%l' => $line)) : $fmt->format($path, $line)) { + return sprintf('<span class="block trace-file-path">in <a href="%s" title="Go to source">%s (line %d)</a></span>', $this->escapeHtml($link), $file, $line); + } + + return sprintf('<span class="block trace-file-path">in <a title="%s line %3$d"><strong>%s</strong> (line %d)</a></span>', $this->escapeHtml($path), $file, $line); + } + + /** + * Formats an array as a string. + * + * @param array $args The argument array + * + * @return string + */ + private function formatArgs(array $args) + { + $result = array(); + foreach ($args as $key => $item) { + if ('object' === $item[0]) { + $formattedValue = sprintf('<em>object</em>(%s)', $this->formatClass($item[1])); + } elseif ('array' === $item[0]) { + $formattedValue = sprintf('<em>array</em>(%s)', is_array($item[1]) ? $this->formatArgs($item[1]) : $item[1]); + } elseif ('null' === $item[0]) { + $formattedValue = '<em>null</em>'; + } elseif ('boolean' === $item[0]) { + $formattedValue = '<em>'.strtolower(var_export($item[1], true)).'</em>'; + } elseif ('resource' === $item[0]) { + $formattedValue = '<em>resource</em>'; + } else { + $formattedValue = str_replace("\n", '', $this->escapeHtml(var_export($item[1], true))); + } + + $result[] = is_int($key) ? $formattedValue : sprintf("'%s' => %s", $this->escapeHtml($key), $formattedValue); + } + + return implode(', ', $result); + } + + /** + * HTML-encodes a string. + */ + private function escapeHtml($str) + { + return htmlspecialchars($str, ENT_COMPAT | ENT_SUBSTITUTE, $this->charset); + } + + private function getSymfonyGhostAsSvg() + { + return '<svg viewBox="0 0 136 81" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414"><path d="M92.358 20.403a23.168 23.168 0 0 1 9.003 1.881 23.67 23.67 0 0 1 5.197 3.079 24.257 24.257 0 0 1 3.457 3.296 24.771 24.771 0 0 1 5.042 9.396c.486 1.72.78 3.492.895 5.28l.008.142.028.158.015.246v13.875c.116.034.232.065.348.098.193.054.383.116.577.168.487.125.989.191 1.49.215.338.016.689.023 1.021-.059.021-.005.032-.029.048-.044l.095-.1c.243-.265.461-.552.663-.851.277-.408.523-.837.746-1.279l.042-.087c-.066-.012-.131-.026-.197-.04l-.099-.023a5.536 5.536 0 0 1-.694-.242 5.649 5.649 0 0 1-2.374-1.845 5.694 5.694 0 0 1-.824-1.594 6.514 6.514 0 0 1-.267-2.781c.045-.394.126-.779.233-1.159.079-.278.162-.562.307-.812.094-.163.129-.196.247-.341l.79-.882c.143-.143.174-.186.34-.303.249-.174.536-.289.834-.333.074-.011.15-.014.224-.02l1.188-.037c.173.004.217-.002.388.028s.211.05.375.105l.018.007c.059.026.119.05.176.079.151.076.179.104.313.2l.006-.021c.073-.187.084-.238.187-.41.077-.129.167-.249.27-.357.051-.054.108-.103.162-.154l1.124-.95c.14-.107.172-.14.327-.224.155-.085.199-.094.363-.154l.019-.006c.169-.043.211-.06.385-.077.174-.016.218-.007.392.003l1.446.158c.193.033.244.033.43.098.278.097.534.259.744.47.053.053.1.112.149.167l.923 1.158.149.213.028.054.017-.014.184-.125c.196-.104.196-.104.402-.184l1.386-.451c.064-.018.126-.038.19-.052.129-.028.259-.042.39-.043.16-.002.321.017.478.047.364.069.711.21 1.032.396.162.094.316.199.469.308.088.063.176.132.27.188l.021.011c.19.123.245.146.409.305.185.178.336.393.443.63.035.079.061.162.091.243l.439 1.428c.045.175.062.219.081.4.02.193.006.381-.015.573a7.79 7.79 0 0 1-.101.645c-.09.455-.212.901-.365 1.339-.128.366-.273.73-.445 1.077-.658 1.335-1.652 2.512-2.917 3.265a6.399 6.399 0 0 1-1.019.489 6.097 6.097 0 0 1-.631.203c-.226.058-.455.1-.686.134l-.096.012-.061.007c-.01.176-.022.352-.036.528-.034.39-.082.778-.153 1.163a14.258 14.258 0 0 1-.574 2.114c-.229.654-.484 1.306-.806 1.918a9.16 9.16 0 0 1-.386.656c-.219.348-.451.686-.697 1.013-.448.594-.946 1.148-1.521 1.614-.255.207-.52.397-.808.553-.9.489-1.919.648-2.921.735-.493.038-.986.059-1.478.099-.162.015-.324.033-.486.049-.145.011-.289.022-.434.03a15.768 15.768 0 0 1-2.778-.118c0 1.416.007 2.832-.001 4.248a9.737 9.737 0 0 1-.684 3.479 9.615 9.615 0 0 1-1.72 2.804 9.326 9.326 0 0 1-3.04 2.279 9.046 9.046 0 0 1-5.33.715 9.064 9.064 0 0 1-2.988-1.079 9.363 9.363 0 0 1-2.761-2.429 10.078 10.078 0 0 1-1.05 1.16 9.281 9.281 0 0 1-1.871 1.358 9.033 9.033 0 0 1-2.495.926 9.04 9.04 0 0 1-6.462-1.072 9.395 9.395 0 0 1-2.602-2.292l-.062-.08a10.896 10.896 0 0 1-.53.635 9.266 9.266 0 0 1-2.671 2.032 9.028 9.028 0 0 1-6.044.751 9.048 9.048 0 0 1-2.436-.934 9.343 9.343 0 0 1-2.286-1.803 9.572 9.572 0 0 1-1.783-2.757 9.705 9.705 0 0 1-.773-3.693V67.244c-.157.024-.314.047-.472.067-.487.06-.977.103-1.469.109-.313.004-.627-.009-.94-.028-.426-.025-.85-.065-1.273-.125-1.833-.264-3.65-.92-5.109-2.117a8.172 8.172 0 0 1-1.064-1.049 10.155 10.155 0 0 1-.878-1.236 15.277 15.277 0 0 1-.7-1.274 20.835 20.835 0 0 1-1.889-6.194l-.018-.142-.008-.061a6.47 6.47 0 0 1-.99-.297 6.135 6.135 0 0 1-.61-.285 6.587 6.587 0 0 1-.889-.562c-1.228-.924-2.124-2.259-2.668-3.711a9.947 9.947 0 0 1-.307-.99 10.288 10.288 0 0 1-.318-1.923c-.009-.147-.011-.293-.015-.44v-.037c.008-.175.004-.22.037-.393.033-.173.053-.213.11-.378l.561-1.417c.031-.068.06-.139.095-.206a2.028 2.028 0 0 1 .771-.803c.093-.054.194-.095.289-.145l.311-.179c.352-.194.714-.358 1.107-.44.213-.044.426-.061.643-.061l.034.001c.177.014.223.01.396.052.174.041.214.065.379.132l1.347.635c.073.04.15.076.221.121.142.091.272.2.388.325.154.166.176.222.297.414l.022.047.722-.762.168-.158c.165-.122.202-.161.385-.253.206-.102.429-.168.656-.193.076-.008.152-.008.228-.011l1.46.013c.177.011.223.007.397.046.175.038.215.061.381.126l.018.008c.154.08.196.094.338.196.142.102.169.137.294.259l.853.912.152-.067.191-.063.019-.005.196-.042c.177-.019.222-.031.401-.022.066.003.133.013.199.02l1.185.182c.073.016.147.027.219.047.288.08.558.227.784.428.151.135.177.181.303.339l.714 1.004c.097.152.127.187.201.352.077.172.123.352.164.536.029.134.056.269.08.404.063.361.102.725.112 1.091.021.78-.08 1.566-.321 2.307a5.906 5.906 0 0 1-.532 1.183 5.463 5.463 0 0 1-3.257 2.489l-.03.008c.195.584.433 1.155.712 1.701.215.422.453.833.735 1.211.026.035.026.034.053.068l.058.072c.056.024.113.042.171.06.319.09.653.121.982.14.488.027.978.013 1.461-.06.167-.028.333-.062.499-.089.134-.022.267-.042.401-.066l.28-.056c.154-.023.308-.049.462-.076l.115-.021V43.881c.011-.203.006-.203.042-.404a26.66 26.66 0 0 1 .226-2.241 24.737 24.737 0 0 1 5.72-12.577 24.204 24.204 0 0 1 3.457-3.296 23.653 23.653 0 0 1 4.937-2.966 23.215 23.215 0 0 1 5.604-1.681 23.703 23.703 0 0 1 3.958-.313zm-.287 2.042a21.169 21.169 0 0 0-8.012 1.622 21.636 21.636 0 0 0-4.799 2.766 22.233 22.233 0 0 0-3.205 2.985 22.705 22.705 0 0 0-4.897 9.196 23.383 23.383 0 0 0-.737 4.867h-.025v15.744c-.258.053-.258.052-.517.101-.28.051-.56.1-.841.144-.211.04-.421.079-.632.115l-.232.037-.411.078c-.116.02-.233.035-.348.057-.305.056-.609.11-.917.14a9.929 9.929 0 0 1-1.883-.017c-.514-.056-1.044-.155-1.51-.397a1.762 1.762 0 0 1-.33-.218 1.925 1.925 0 0 1-.234-.252 5.248 5.248 0 0 1-.174-.22 8.97 8.97 0 0 1-.582-.883 13.806 13.806 0 0 1-.941-1.971 14.348 14.348 0 0 1-.608-1.954 14.04 14.04 0 0 1-.169-.86l-.015-.11-.015-.109c.161-.007.16-.007.321-.016a12.793 12.793 0 0 0 1.413-.182 4.43 4.43 0 0 0 .28-.074 3.56 3.56 0 0 0 1.199-.616c.309-.244.576-.543.786-.88.163-.261.292-.544.387-.838.123-.378.192-.774.214-1.172a5.102 5.102 0 0 0-.024-.865 7.192 7.192 0 0 0-.145-.799l-.714-1.005-1.184-.182-.019.005-.946.758-.12 1.229a4.953 4.953 0 0 1 .111.455c.032.181.052.36.043.544a1.04 1.04 0 0 1-.056.303c-.11.301-.419.451-.696.548-.402.142-.813.25-1.229.339l.07-.648c.022-.191.047-.381.08-.57.036-.207.079-.413.152-.61.077-.211.182-.412.296-.605.044-.074.092-.146.135-.222.029-.048.031-.047.055-.098.016-.033.031-.064.045-.098l-.026-1.551-1.042-1.116-.018-.008-1.459-.014-1.022 1.079c-.049.128-.08.258-.111.393a5.274 5.274 0 0 0-.1.651 5.55 5.55 0 0 0-.031.466c-.009.687.104 1.37.294 2.028.11.382.262.753.402 1.123-.115-.029-.228-.06-.342-.092a9.526 9.526 0 0 1-1.176-.446c-.108-.05-.111-.048-.191-.097a1.921 1.921 0 0 1-.327-.249c-.416-.4-.589-.986-.671-1.55a5.643 5.643 0 0 1-.057-.549c-.007-.143-.006-.286-.007-.429-.001-.186.005-.372.011-.558l.001-.039-.567-1.446-1.347-.634c-.316-.008-.599.144-.867.299-.109.063-.218.126-.33.185a2.058 2.058 0 0 1-.125.061l-.042.019-.561 1.416c0 .209.014.416.036.624.04.377.106.75.196 1.118.076.309.164.616.275.913.415 1.109 1.093 2.146 2.043 2.838.234.171.485.317.746.442.183.088.371.161.565.22.263.079.532.13.803.17.296.045.594.075.892.095l.108.007c.004.151.01.302.017.453.011.177.023.353.038.529a18.13 18.13 0 0 0 .762 3.752c.239.76.522 1.505.857 2.225.23.494.483.977.767 1.44.288.469.608.915.989 1.308 1.001 1.028 2.324 1.648 3.687 1.976.643.155 1.298.243 1.955.287.311.021.622.036.933.033.418-.006.835-.041 1.25-.094.238-.03.477-.064.713-.11.117-.023.232-.053.348-.081.196-.048.392-.097.586-.151.147-.041.291-.094.436-.144.204-.069.408-.139.608-.217l.006-.003c0 2.207-.013 4.414.001 6.62a7.942 7.942 0 0 0 .13 1.32 7.545 7.545 0 0 0 2.383 4.243 7.23 7.23 0 0 0 2.258 1.372 7.094 7.094 0 0 0 7.012-1.164 7.504 7.504 0 0 0 2.035-2.613 7.727 7.727 0 0 0 .676-2.401l.009-.088.038-.765a8.16 8.16 0 0 0 .113 1.324c.121.694.338 1.37.643 2.001a7.49 7.49 0 0 0 1.692 2.275 7.266 7.266 0 0 0 2.24 1.399 7.11 7.11 0 0 0 4.615.19 7.212 7.212 0 0 0 2.351-1.218 7.501 7.501 0 0 0 2.128-2.64 7.763 7.763 0 0 0 .702-2.39l.01-.088.009-.088.038-.765a9.339 9.339 0 0 0 .021.575 7.626 7.626 0 0 0 .621 2.504 7.507 7.507 0 0 0 2.35 2.972 7.1 7.1 0 0 0 7.026.881 7.275 7.275 0 0 0 2.268-1.515 7.525 7.525 0 0 0 1.612-2.338 7.58 7.58 0 0 0 .572-2.033c.048-.347.069-.696.071-1.046v-6.721c.136.051.271.101.408.148a12.153 12.153 0 0 0 1.976.443c.264.035.529.055.794.071.33.02.66.031.991.027.245-.002.49-.012.735-.031.245-.018.49-.048.735-.068.407-.03.814-.051 1.221-.079a9.493 9.493 0 0 0 1.384-.188c.315-.073.626-.174.912-.329a3.53 3.53 0 0 0 .586-.418c.46-.386.85-.85 1.205-1.337a12.178 12.178 0 0 0 .801-1.246c.122-.232.229-.471.33-.712a15.873 15.873 0 0 0 .681-1.988c.136-.525.23-1.058.282-1.598.035-.41.052-.822.088-1.232.03-.317.078-.632.121-.947l.018-.145.016-.145c.144.009.287.016.431.021.459.009.924.007 1.378-.07a4.456 4.456 0 0 0 1.353-.482c.989-.55 1.752-1.466 2.258-2.488.116-.235.214-.48.304-.727a7.58 7.58 0 0 0 .377-1.43c.016-.109.027-.218.039-.328l.001-.009-.438-1.428a5.206 5.206 0 0 1-.16-.096c-.158-.105-.311-.219-.467-.326a3.829 3.829 0 0 0-.159-.1 1.356 1.356 0 0 0-.509-.18l-.01-.001-1.386.452-.681 1.323c-.016.212-.023.424-.043.636a5.66 5.66 0 0 1-.139.873c-.118.494-.316.999-.702 1.338a1.865 1.865 0 0 1-.496.301l-.272.087a9.57 9.57 0 0 1-.83.205 8.797 8.797 0 0 1-.582.091l.229-.462c.079-.163.158-.325.229-.492.051-.118.096-.239.139-.36.036-.103.076-.209.103-.315.019-.075.031-.153.041-.229.017-.132.031-.263.043-.395.035-.368.06-.737.094-1.104.02-.187.048-.372.067-.559.015-.167.015-.336.012-.505a4.76 4.76 0 0 0-.074-.826c-.012-.065-.03-.13-.045-.194l-.003-.009-.923-1.157-1.446-.159-.019.006-1.124.95-.154 1.489c.011.034.024.066.037.099.044.115.107.221.161.331.046.096.088.193.13.29l.031.076c.013.033.017.07.023.105.012.096.022.191.031.287.031.364.047.73.081 1.093.013.102.028.202.04.303.014.145.027.29.033.435.014.28.016.561.023.841a9.588 9.588 0 0 1-.862-.323c-.063-.027-.128-.062-.193-.084a1.325 1.325 0 0 0-.067-.013c-.081-.01-.162-.017-.243-.025-.245-.02-.49-.037-.734-.061-.066-.007-.132-.014-.198-.028l-.017-.005c-.03-.013-.029-.014-.067-.038a1.614 1.614 0 0 1-.161-.108.863.863 0 0 1-.22-.242c-.089-.155-.102-.34-.09-.517.02-.299.117-.591.228-.866l.004-.009-.018-1.197-.874-.84-.018-.007-1.188.036-.79.882c-.037.112-.074.224-.106.338a4.756 4.756 0 0 0-.171 1.906c.039.329.115.654.233.963a3.542 3.542 0 0 0 1.263 1.636c.313.222.659.393 1.019.517.237.082.487.111.734.145.479.06.959.106 1.438.166.121.017.241.037.362.058l.158.026a12.12 12.12 0 0 1-.923 2.565 13.221 13.221 0 0 1-.829 1.474 9.474 9.474 0 0 1-.984 1.286c-.08.087-.163.17-.248.252a1.655 1.655 0 0 1-.329.262 2.376 2.376 0 0 1-.722.247c-.457.089-.927.093-1.39.071-.391-.018-.781-.06-1.168-.123a7.817 7.817 0 0 1-.609-.124c-.226-.056-.448-.124-.671-.191-.065-.019-.131-.035-.197-.054a14.75 14.75 0 0 1-.543-.165 23.384 23.384 0 0 1-.453-.128c-.196-.059-.195-.059-.39-.12l-.276-.077V43.881h-.025a34.633 34.633 0 0 0-.031-.557 23.606 23.606 0 0 0-.4-2.994 22.743 22.743 0 0 0-1.492-4.708 22.567 22.567 0 0 0-4.593-6.748 21.865 21.865 0 0 0-6.882-4.706 21.175 21.175 0 0 0-8.115-1.722l-.411-.001zm9.15 33.69c.109.015.214.038.315.085a1.012 1.012 0 0 1 .574.771c.021.132.013.268.009.4a8.38 8.38 0 0 1-.026.476 8.767 8.767 0 0 1-1.564 4.282c-.306.437-.65.846-1.024 1.222a10.09 10.09 0 0 1-4.612 2.627c-1.32.343-2.704.427-4.055.254a10.422 10.422 0 0 1-2.67-.709 9.917 9.917 0 0 1-3.57-2.503 9.312 9.312 0 0 1-.775-.984 8.933 8.933 0 0 1-.731-1.288 8.648 8.648 0 0 1-.795-3.377c-.003-.104-.008-.211 0-.316a1.042 1.042 0 0 1 .254-.609.98.98 0 0 1 1.337-.125 1.023 1.023 0 0 1 .385.719c.007.151.006.303.014.454a6.547 6.547 0 0 0 .524 2.217c.257.595.599 1.15 1.006 1.648.325.398.691.759 1.087 1.081.312.253.642.482.987.684 2.592 1.522 5.945 1.538 8.553.047a7.982 7.982 0 0 0 1.069-.731 7.619 7.619 0 0 0 1.142-1.15 6.949 6.949 0 0 0 1.018-1.741 6.538 6.538 0 0 0 .467-2.425l.004-.084a1.012 1.012 0 0 1 .672-.876c.08-.028.158-.04.241-.05.082-.003.082-.003.164.001zm-70.51-12.426c-15.5.93-28.544-5.922-30.126-16.443C-1.156 15.689 11.64 4.024 29.14 1.235c17.501-2.79 33.123 4.345 34.864 15.922 1.575 10.475-8.749 21.021-23.691 25.001l.001.099a31.185 31.185 0 0 0 .042.833c.007.094.019.188.021.282.006.178.013.356.024.534.011.16.024.32.039.48.017.154.038.306.058.459.036.273.077.544.144.811a4.723 4.723 0 0 0 .449 1.128c.192.332.434.628.702.898l.047.05c.151.139.302.275.461.403.24.192.492.367.748.537.474.314.962.6 1.457.877l.041.023.588.735-.729.586c-.376.112-.755.216-1.135.309a11.193 11.193 0 0 1-2.562.355 8.575 8.575 0 0 1-2.995-.486 8.461 8.461 0 0 1-.96-.413 11.194 11.194 0 0 1-1.836-1.152 13.345 13.345 0 0 1-1.07-.934c-.23-.221-.454-.448-.672-.681-.121-.129-.246-.258-.36-.395a23.448 23.448 0 0 1-1.328-1.773c-.051-.076-.049-.077-.095-.155l-.277-.477-.072-.13c-.081-.177-.159-.357-.238-.535l-.003-.01-.092-.707zm52.409-7.804c3.557 0 6.444 3.201 6.444 7.145 0 3.944-2.887 7.146-6.444 7.146s-6.444-3.202-6.444-7.146 2.887-7.145 6.444-7.145zm18.062 0c3.557 0 6.444 3.201 6.444 7.145 0 3.944-2.887 7.146-6.444 7.146s-6.444-3.202-6.444-7.146 2.887-7.145 6.444-7.145zM83.12 42.029c1.915 0 3.47 1.601 3.47 3.573s-1.555 3.573-3.47 3.573c-1.915 0-3.47-1.601-3.47-3.573s1.555-3.573 3.47-3.573zm17.846 0c1.915 0 3.47 1.601 3.47 3.573s-1.555 3.573-3.47 3.573c-1.915 0-3.47-1.601-3.47-3.573s1.555-3.573 3.47-3.573zM17.019 28c-.368 1.65-1.848 5.008-5.178 5.799-2.572.611-4.153-.815-4.544-2.559-.424-1.891.722-3.532 2.121-4.575a3.473 3.473 0 0 1-1.446-2.099c-.421-1.875.867-3.637 3.184-4.187 1.917-.455 3.185.248 3.462 1.482.265 1.184-.534 2.275-1.828 2.582-.878.209-1.574-.042-1.718-.683a1.4 1.4 0 0 1 .044-.704s.287.227.894.083c.751-.179 1.086-.709.972-1.219-.14-.625-.892-.827-1.739-.626-1.054.25-2.06 1.096-1.713 2.642.232 1.036.871 1.56 1.483 1.813.245-.11.481-.183.688-.233.943-.224 1.48-.005 1.587.472.092.411-.144.935-1.166 1.178a3.255 3.255 0 0 1-1.548.004c-.837.771-1.58 1.883-1.27 3.264.276 1.234 1.267 2.125 2.944 1.726 2.598-.617 3.861-3.638 4.277-4.883-.353-.574-.615-1.153-.732-1.676-.107-.477.145-1.005.863-1.175.48-.114.702.127.846.769a2.77 2.77 0 0 1-.03.995c.209.331.443.622.735.951.616-1.983 1.369-3.877 1.737-3.964.591-.141 1.492.65 1.492.65-.815.644-1.689 2.376-2.333 4.158.804.658 1.627 1.103 2.139.982.43-.102.735-.577.95-1.151-.323-2.226.975-4.331 2.31-4.648.703-.167 1.257.204 1.39.796.114.51-.044 1.379-.854 1.745-.236-1.053-.672-1.348-.944-1.283-.495.117-.844 1.413-.538 2.778.232 1.037.712 1.529 1.351 1.377.756-.179 1.333-1.176 1.699-2.128-.265-2.095.877-4.166 2.221-4.486.671-.159 1.214.162 1.391.952.332 1.48-.986 2.885-2.173 3.444.265.734.673 1.053 1.281.909.96-.229 1.578-1.465 1.923-2.506-.125-1.267-.26-2.385-.406-3.035l-.055-.247s1.568-.286 1.778.652l.019.082c.238-.663.67-1.216 1.309-1.368.83-.197 1.526.504 1.755 1.524.497 2.22-.556 4.428-1.834 4.732-.368.087-.642.066-.883-.033.121 1.288.292 2.651.542 3.77.126.559.272 1.061.448 1.47-.464.11-1.797.392-1.978-.414-.16-.716-.342-3.206-.554-5.612-.504 1.107-1.311 2.192-2.441 2.46-1.008.24-1.685-.303-2.055-1.182-.491 1.082-1.281 2.148-2.381 2.409-.817.194-1.554-.117-1.988-1.013-.36.843-.875 1.555-1.54 1.713-.639.152-1.53-.295-2.4-1.024-.239.888-.384 1.668-.39 2.241 0 0-.701.028-.804-.433-.096-.427.065-1.436.341-2.61a10.315 10.315 0 0 1-.713-.848zm38.163-17.803c.068.157.185.527.266.889.424 1.892.37 4.451.739 6.42-.065.61-.387 3.077-1.352 3.307-.192.045-.333-.06-.422-.454-.14-.626-.091-1.607-.293-2.512-.258-1.152-.782-1.686-1.517-1.511-.767.182-1.287 1.016-1.643 2.054-.022-.099-.053-.386-.093-.567-.211-.938-1.779-.652-1.779-.652a6.2 6.2 0 0 1 .457 1.364c.07.31.119.618.155.921-.246.495-.637.996-1.225 1.135-.064.015-.128.031-.195.029a6.977 6.977 0 0 0-.126-.784c-.258-1.152-.871-2.011-1.526-1.855a.712.712 0 0 0-.423.291c-1.337.317-2.358 2.107-2.118 3.919-.214.889-.551 1.757-1.059 1.877-.415.099-.724-.452-1.03-1.817-.059-.263-.09-.706-.122-1.149.142-.64.177-1.237.081-1.665-.107-.477-.417-.733-.816-.638-.715.17-.909 1.75-.52 3.801-.238.92-.639 1.915-1.278 2.067-.464.11-.835-.27-1.012-1.059-.158-.708-.196-1.929-.236-3.08 1.201-.424 1.911-1.009 1.775-1.617-.114-.51-.739-.743-.739-.743s-.124.722-1.064 1.258c-.029-.582-.064-1.111-.137-1.44-.137-.609-.458-.914-1.688-.622.158.327.274.698.359 1.076.103.46.162.949.189 1.445-.611.128-.947.052-.947.052s-.1.457-.041.72c.078.345.432.348 1.026.224.02 1.364-.067 2.701.143 3.639.306 1.365 1.231 1.89 2.046 1.697.907-.216 1.539-1.275 1.914-2.36.407 1.245 1.031 1.955 1.951 1.736.731-.174 1.261-1.142 1.587-2.195.431.765 1.15 1.129 1.983.931 1.214-.289 1.742-1.54 1.835-2.775 0 0 .147-.018.243-.04.526-.125.949-.488 1.26-.915.04.788.053 1.518.194 2.146.111.493.339.612.595.552.495-.118 1.081-.881 1.081-.881a3.93 3.93 0 0 1-.383-1.035c-.284-1.267.317-3.541.988-3.7.208-.049.377.257.492.767.057.255.092.504.115.751l.098 1.469c.024.246.059.496.116.751.158.707.63 1.236 1.381 1.058 1.317-.313 2.07-2.634 2.178-3.956.228.157.536.175.909.086-.505-2.253.089-6.136-.298-7.864-.1-.444-1.001-.58-1.607-.583l-.467.037zM33.729 22.293c.415-.099.711.246.885 1.02.287 1.283-.222 2.616-.797 2.753-.191.045-.695-.025-.961-1.21-.025-.115-.051-.23-.061-.349.05-1.277.439-2.097.934-2.214zm-5.187.955c.271-.065.511.104.588.449.137.609-.338 1.345-1.275 1.966-.255-1.36.159-2.29.687-2.415zm18.032-.403c-.607.144-1.062-.458-1.239-1.248-.217-.97.001-2.097.644-2.457.001.155.038.32.075.484.147.658.554 1.497 1.268 1.83-.017.749-.253 1.273-.748 1.391zm9.877-1.654c.103.461.496.714 1.039.585.799-.19.973-.993.847-1.553-.125-.559-.461-.93-.988-.805-.543.13-1.108.836-.898 1.773zm-14.21-5.442c-.104-.461-.497-.714-1.056-.581-.783.186-.972.993-.847 1.552.126.56.461.93.908.824.56-.133 1.172-1.006.995-1.795z" fill="#fff" fill-opacity=".6"></path></svg>'; + } +} diff --git a/vendor/symfony/debug/FatalErrorHandler/ClassNotFoundFatalErrorHandler.php b/vendor/symfony/debug/FatalErrorHandler/ClassNotFoundFatalErrorHandler.php new file mode 100644 index 00000000..32ba9a09 --- /dev/null +++ b/vendor/symfony/debug/FatalErrorHandler/ClassNotFoundFatalErrorHandler.php @@ -0,0 +1,206 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Debug\FatalErrorHandler; + +use Symfony\Component\Debug\Exception\ClassNotFoundException; +use Symfony\Component\Debug\Exception\FatalErrorException; +use Symfony\Component\Debug\DebugClassLoader; +use Composer\Autoload\ClassLoader as ComposerClassLoader; +use Symfony\Component\ClassLoader\ClassLoader as SymfonyClassLoader; + +/** + * ErrorHandler for classes that do not exist. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class ClassNotFoundFatalErrorHandler implements FatalErrorHandlerInterface +{ + /** + * {@inheritdoc} + */ + public function handleError(array $error, FatalErrorException $exception) + { + $messageLen = strlen($error['message']); + $notFoundSuffix = '\' not found'; + $notFoundSuffixLen = strlen($notFoundSuffix); + if ($notFoundSuffixLen > $messageLen) { + return; + } + + if (0 !== substr_compare($error['message'], $notFoundSuffix, -$notFoundSuffixLen)) { + return; + } + + foreach (array('class', 'interface', 'trait') as $typeName) { + $prefix = ucfirst($typeName).' \''; + $prefixLen = strlen($prefix); + if (0 !== strpos($error['message'], $prefix)) { + continue; + } + + $fullyQualifiedClassName = substr($error['message'], $prefixLen, -$notFoundSuffixLen); + if (false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedClassName, '\\')) { + $className = substr($fullyQualifiedClassName, $namespaceSeparatorIndex + 1); + $namespacePrefix = substr($fullyQualifiedClassName, 0, $namespaceSeparatorIndex); + $message = sprintf('Attempted to load %s "%s" from namespace "%s".', $typeName, $className, $namespacePrefix); + $tail = ' for another namespace?'; + } else { + $className = $fullyQualifiedClassName; + $message = sprintf('Attempted to load %s "%s" from the global namespace.', $typeName, $className); + $tail = '?'; + } + + if ($candidates = $this->getClassCandidates($className)) { + $tail = array_pop($candidates).'"?'; + if ($candidates) { + $tail = ' for e.g. "'.implode('", "', $candidates).'" or "'.$tail; + } else { + $tail = ' for "'.$tail; + } + } + $message .= "\nDid you forget a \"use\" statement".$tail; + + return new ClassNotFoundException($message, $exception); + } + } + + /** + * Tries to guess the full namespace for a given class name. + * + * By default, it looks for PSR-0 and PSR-4 classes registered via a Symfony or a Composer + * autoloader (that should cover all common cases). + * + * @param string $class A class name (without its namespace) + * + * @return array An array of possible fully qualified class names + */ + private function getClassCandidates($class) + { + if (!is_array($functions = spl_autoload_functions())) { + return array(); + } + + // find Symfony and Composer autoloaders + $classes = array(); + + foreach ($functions as $function) { + if (!is_array($function)) { + continue; + } + // get class loaders wrapped by DebugClassLoader + if ($function[0] instanceof DebugClassLoader) { + $function = $function[0]->getClassLoader(); + + if (!is_array($function)) { + continue; + } + } + + if ($function[0] instanceof ComposerClassLoader || $function[0] instanceof SymfonyClassLoader) { + foreach ($function[0]->getPrefixes() as $prefix => $paths) { + foreach ($paths as $path) { + $classes = array_merge($classes, $this->findClassInPath($path, $class, $prefix)); + } + } + } + if ($function[0] instanceof ComposerClassLoader) { + foreach ($function[0]->getPrefixesPsr4() as $prefix => $paths) { + foreach ($paths as $path) { + $classes = array_merge($classes, $this->findClassInPath($path, $class, $prefix)); + } + } + } + } + + return array_unique($classes); + } + + /** + * @param string $path + * @param string $class + * @param string $prefix + * + * @return array + */ + private function findClassInPath($path, $class, $prefix) + { + if (!$path = realpath($path.'/'.strtr($prefix, '\\_', '//')) ?: realpath($path.'/'.dirname(strtr($prefix, '\\_', '//'))) ?: realpath($path)) { + return array(); + } + + $classes = array(); + $filename = $class.'.php'; + foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) { + if ($filename == $file->getFileName() && $class = $this->convertFileToClass($path, $file->getPathName(), $prefix)) { + $classes[] = $class; + } + } + + return $classes; + } + + /** + * @param string $path + * @param string $file + * @param string $prefix + * + * @return string|null + */ + private function convertFileToClass($path, $file, $prefix) + { + $candidates = array( + // namespaced class + $namespacedClass = str_replace(array($path.DIRECTORY_SEPARATOR, '.php', '/'), array('', '', '\\'), $file), + // namespaced class (with target dir) + $prefix.$namespacedClass, + // namespaced class (with target dir and separator) + $prefix.'\\'.$namespacedClass, + // PEAR class + str_replace('\\', '_', $namespacedClass), + // PEAR class (with target dir) + str_replace('\\', '_', $prefix.$namespacedClass), + // PEAR class (with target dir and separator) + str_replace('\\', '_', $prefix.'\\'.$namespacedClass), + ); + + if ($prefix) { + $candidates = array_filter($candidates, function ($candidate) use ($prefix) { return 0 === strpos($candidate, $prefix); }); + } + + // We cannot use the autoloader here as most of them use require; but if the class + // is not found, the new autoloader call will require the file again leading to a + // "cannot redeclare class" error. + foreach ($candidates as $candidate) { + if ($this->classExists($candidate)) { + return $candidate; + } + } + + require_once $file; + + foreach ($candidates as $candidate) { + if ($this->classExists($candidate)) { + return $candidate; + } + } + } + + /** + * @param string $class + * + * @return bool + */ + private function classExists($class) + { + return class_exists($class, false) || interface_exists($class, false) || trait_exists($class, false); + } +} diff --git a/vendor/symfony/debug/FatalErrorHandler/FatalErrorHandlerInterface.php b/vendor/symfony/debug/FatalErrorHandler/FatalErrorHandlerInterface.php new file mode 100644 index 00000000..6b87eb30 --- /dev/null +++ b/vendor/symfony/debug/FatalErrorHandler/FatalErrorHandlerInterface.php @@ -0,0 +1,32 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Debug\FatalErrorHandler; + +use Symfony\Component\Debug\Exception\FatalErrorException; + +/** + * Attempts to convert fatal errors to exceptions. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +interface FatalErrorHandlerInterface +{ + /** + * Attempts to convert an error into an exception. + * + * @param array $error An array as returned by error_get_last() + * @param FatalErrorException $exception A FatalErrorException instance + * + * @return FatalErrorException|null A FatalErrorException instance if the class is able to convert the error, null otherwise + */ + public function handleError(array $error, FatalErrorException $exception); +} diff --git a/vendor/symfony/debug/FatalErrorHandler/UndefinedFunctionFatalErrorHandler.php b/vendor/symfony/debug/FatalErrorHandler/UndefinedFunctionFatalErrorHandler.php new file mode 100644 index 00000000..c6f391a7 --- /dev/null +++ b/vendor/symfony/debug/FatalErrorHandler/UndefinedFunctionFatalErrorHandler.php @@ -0,0 +1,84 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Debug\FatalErrorHandler; + +use Symfony\Component\Debug\Exception\UndefinedFunctionException; +use Symfony\Component\Debug\Exception\FatalErrorException; + +/** + * ErrorHandler for undefined functions. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class UndefinedFunctionFatalErrorHandler implements FatalErrorHandlerInterface +{ + /** + * {@inheritdoc} + */ + public function handleError(array $error, FatalErrorException $exception) + { + $messageLen = strlen($error['message']); + $notFoundSuffix = '()'; + $notFoundSuffixLen = strlen($notFoundSuffix); + if ($notFoundSuffixLen > $messageLen) { + return; + } + + if (0 !== substr_compare($error['message'], $notFoundSuffix, -$notFoundSuffixLen)) { + return; + } + + $prefix = 'Call to undefined function '; + $prefixLen = strlen($prefix); + if (0 !== strpos($error['message'], $prefix)) { + return; + } + + $fullyQualifiedFunctionName = substr($error['message'], $prefixLen, -$notFoundSuffixLen); + if (false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedFunctionName, '\\')) { + $functionName = substr($fullyQualifiedFunctionName, $namespaceSeparatorIndex + 1); + $namespacePrefix = substr($fullyQualifiedFunctionName, 0, $namespaceSeparatorIndex); + $message = sprintf('Attempted to call function "%s" from namespace "%s".', $functionName, $namespacePrefix); + } else { + $functionName = $fullyQualifiedFunctionName; + $message = sprintf('Attempted to call function "%s" from the global namespace.', $functionName); + } + + $candidates = array(); + foreach (get_defined_functions() as $type => $definedFunctionNames) { + foreach ($definedFunctionNames as $definedFunctionName) { + if (false !== $namespaceSeparatorIndex = strrpos($definedFunctionName, '\\')) { + $definedFunctionNameBasename = substr($definedFunctionName, $namespaceSeparatorIndex + 1); + } else { + $definedFunctionNameBasename = $definedFunctionName; + } + + if ($definedFunctionNameBasename === $functionName) { + $candidates[] = '\\'.$definedFunctionName; + } + } + } + + if ($candidates) { + sort($candidates); + $last = array_pop($candidates).'"?'; + if ($candidates) { + $candidates = 'e.g. "'.implode('", "', $candidates).'" or "'.$last; + } else { + $candidates = '"'.$last; + } + $message .= "\nDid you mean to call ".$candidates; + } + + return new UndefinedFunctionException($message, $exception); + } +} diff --git a/vendor/symfony/debug/FatalErrorHandler/UndefinedMethodFatalErrorHandler.php b/vendor/symfony/debug/FatalErrorHandler/UndefinedMethodFatalErrorHandler.php new file mode 100644 index 00000000..6fa62b6f --- /dev/null +++ b/vendor/symfony/debug/FatalErrorHandler/UndefinedMethodFatalErrorHandler.php @@ -0,0 +1,66 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Debug\FatalErrorHandler; + +use Symfony\Component\Debug\Exception\FatalErrorException; +use Symfony\Component\Debug\Exception\UndefinedMethodException; + +/** + * ErrorHandler for undefined methods. + * + * @author Grégoire Pineau <lyrixx@lyrixx.info> + */ +class UndefinedMethodFatalErrorHandler implements FatalErrorHandlerInterface +{ + /** + * {@inheritdoc} + */ + public function handleError(array $error, FatalErrorException $exception) + { + preg_match('/^Call to undefined method (.*)::(.*)\(\)$/', $error['message'], $matches); + if (!$matches) { + return; + } + + $className = $matches[1]; + $methodName = $matches[2]; + + $message = sprintf('Attempted to call an undefined method named "%s" of class "%s".', $methodName, $className); + + if (!class_exists($className) || null === $methods = get_class_methods($className)) { + // failed to get the class or its methods on which an unknown method was called (for example on an anonymous class) + return new UndefinedMethodException($message, $exception); + } + + $candidates = array(); + foreach ($methods as $definedMethodName) { + $lev = levenshtein($methodName, $definedMethodName); + if ($lev <= strlen($methodName) / 3 || false !== strpos($definedMethodName, $methodName)) { + $candidates[] = $definedMethodName; + } + } + + if ($candidates) { + sort($candidates); + $last = array_pop($candidates).'"?'; + if ($candidates) { + $candidates = 'e.g. "'.implode('", "', $candidates).'" or "'.$last; + } else { + $candidates = '"'.$last; + } + + $message .= "\nDid you mean to call ".$candidates; + } + + return new UndefinedMethodException($message, $exception); + } +} diff --git a/vendor/ramsey/array_column/LICENSE b/vendor/symfony/debug/LICENSE index d099612d..17d16a13 100644 --- a/vendor/ramsey/array_column/LICENSE +++ b/vendor/symfony/debug/LICENSE @@ -1,14 +1,14 @@ -Copyright (c) 2013-2015 Ben Ramsey (http://benramsey.com) +Copyright (c) 2004-2017 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, diff --git a/vendor/symfony/debug/README.md b/vendor/symfony/debug/README.md new file mode 100644 index 00000000..a1d16175 --- /dev/null +++ b/vendor/symfony/debug/README.md @@ -0,0 +1,13 @@ +Debug Component +=============== + +The Debug component provides tools to ease debugging PHP code. + +Resources +--------- + + * [Documentation](https://symfony.com/doc/current/components/debug/index.html) + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/vendor/symfony/debug/Resources/ext/README.md b/vendor/symfony/debug/Resources/ext/README.md new file mode 100644 index 00000000..25dccf07 --- /dev/null +++ b/vendor/symfony/debug/Resources/ext/README.md @@ -0,0 +1,134 @@ +Symfony Debug Extension for PHP 5 +================================= + +This extension publishes several functions to help building powerful debugging tools. +It is compatible with PHP 5.3, 5.4, 5.5 and 5.6; with ZTS and non-ZTS modes. +It is not required thus not provided for PHP 7. + +symfony_zval_info() +------------------- + +- exposes zval_hash/refcounts, allowing e.g. efficient exploration of arbitrary structures in PHP, +- does work with references, preventing memory copying. + +Its behavior is about the same as: + +```php +<?php + +function symfony_zval_info($key, $array, $options = 0) +{ + + // $options is currently not used, but could be in future version. + + if (!array_key_exists($key, $array)) { + return null; + } + + $info = array( + 'type' => gettype($array[$key]), + 'zval_hash' => /* hashed memory address of $array[$key] */, + 'zval_refcount' => /* internal zval refcount of $array[$key] */, + 'zval_isref' => /* is_ref status of $array[$key] */, + ); + + switch ($info['type']) { + case 'object': + $info += array( + 'object_class' => get_class($array[$key]), + 'object_refcount' => /* internal object refcount of $array[$key] */, + 'object_hash' => spl_object_hash($array[$key]), + 'object_handle' => /* internal object handle $array[$key] */, + ); + break; + + case 'resource': + $info += array( + 'resource_handle' => (int) $array[$key], + 'resource_type' => get_resource_type($array[$key]), + 'resource_refcount' => /* internal resource refcount of $array[$key] */, + ); + break; + + case 'array': + $info += array( + 'array_count' => count($array[$key]), + ); + break; + + case 'string': + $info += array( + 'strlen' => strlen($array[$key]), + ); + break; + } + + return $info; +} +``` + +symfony_debug_backtrace() +------------------------- + +This function works like debug_backtrace(), except that it can fetch the full backtrace in case of fatal errors: + +```php +function foo() { fatal(); } +function bar() { foo(); } + +function sd() { var_dump(symfony_debug_backtrace()); } + +register_shutdown_function('sd'); + +bar(); + +/* Will output +Fatal error: Call to undefined function fatal() in foo.php on line 42 +array(3) { + [0]=> + array(2) { + ["function"]=> + string(2) "sd" + ["args"]=> + array(0) { + } + } + [1]=> + array(4) { + ["file"]=> + string(7) "foo.php" + ["line"]=> + int(1) + ["function"]=> + string(3) "foo" + ["args"]=> + array(0) { + } + } + [2]=> + array(4) { + ["file"]=> + string(102) "foo.php" + ["line"]=> + int(2) + ["function"]=> + string(3) "bar" + ["args"]=> + array(0) { + } + } +} +*/ +``` + +Usage +----- + +To enable the extension from source, run: + +``` + phpize + ./configure + make + sudo make install +``` diff --git a/vendor/symfony/debug/Resources/ext/config.m4 b/vendor/symfony/debug/Resources/ext/config.m4 new file mode 100644 index 00000000..3c560471 --- /dev/null +++ b/vendor/symfony/debug/Resources/ext/config.m4 @@ -0,0 +1,63 @@ +dnl $Id$ +dnl config.m4 for extension symfony_debug + +dnl Comments in this file start with the string 'dnl'. +dnl Remove where necessary. This file will not work +dnl without editing. + +dnl If your extension references something external, use with: + +dnl PHP_ARG_WITH(symfony_debug, for symfony_debug support, +dnl Make sure that the comment is aligned: +dnl [ --with-symfony_debug Include symfony_debug support]) + +dnl Otherwise use enable: + +PHP_ARG_ENABLE(symfony_debug, whether to enable symfony_debug support, +dnl Make sure that the comment is aligned: +[ --enable-symfony_debug Enable symfony_debug support]) + +if test "$PHP_SYMFONY_DEBUG" != "no"; then + dnl Write more examples of tests here... + + dnl # --with-symfony_debug -> check with-path + dnl SEARCH_PATH="/usr/local /usr" # you might want to change this + dnl SEARCH_FOR="/include/symfony_debug.h" # you most likely want to change this + dnl if test -r $PHP_SYMFONY_DEBUG/$SEARCH_FOR; then # path given as parameter + dnl SYMFONY_DEBUG_DIR=$PHP_SYMFONY_DEBUG + dnl else # search default path list + dnl AC_MSG_CHECKING([for symfony_debug files in default path]) + dnl for i in $SEARCH_PATH ; do + dnl if test -r $i/$SEARCH_FOR; then + dnl SYMFONY_DEBUG_DIR=$i + dnl AC_MSG_RESULT(found in $i) + dnl fi + dnl done + dnl fi + dnl + dnl if test -z "$SYMFONY_DEBUG_DIR"; then + dnl AC_MSG_RESULT([not found]) + dnl AC_MSG_ERROR([Please reinstall the symfony_debug distribution]) + dnl fi + + dnl # --with-symfony_debug -> add include path + dnl PHP_ADD_INCLUDE($SYMFONY_DEBUG_DIR/include) + + dnl # --with-symfony_debug -> check for lib and symbol presence + dnl LIBNAME=symfony_debug # you may want to change this + dnl LIBSYMBOL=symfony_debug # you most likely want to change this + + dnl PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL, + dnl [ + dnl PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $SYMFONY_DEBUG_DIR/lib, SYMFONY_DEBUG_SHARED_LIBADD) + dnl AC_DEFINE(HAVE_SYMFONY_DEBUGLIB,1,[ ]) + dnl ],[ + dnl AC_MSG_ERROR([wrong symfony_debug lib version or lib not found]) + dnl ],[ + dnl -L$SYMFONY_DEBUG_DIR/lib -lm + dnl ]) + dnl + dnl PHP_SUBST(SYMFONY_DEBUG_SHARED_LIBADD) + + PHP_NEW_EXTENSION(symfony_debug, symfony_debug.c, $ext_shared) +fi diff --git a/vendor/symfony/debug/Resources/ext/config.w32 b/vendor/symfony/debug/Resources/ext/config.w32 new file mode 100644 index 00000000..487e6913 --- /dev/null +++ b/vendor/symfony/debug/Resources/ext/config.w32 @@ -0,0 +1,13 @@ +// $Id$ +// vim:ft=javascript + +// If your extension references something external, use ARG_WITH +// ARG_WITH("symfony_debug", "for symfony_debug support", "no"); + +// Otherwise, use ARG_ENABLE +// ARG_ENABLE("symfony_debug", "enable symfony_debug support", "no"); + +if (PHP_SYMFONY_DEBUG != "no") { + EXTENSION("symfony_debug", "symfony_debug.c"); +} + diff --git a/vendor/symfony/debug/Resources/ext/php_symfony_debug.h b/vendor/symfony/debug/Resources/ext/php_symfony_debug.h new file mode 100644 index 00000000..26d0e8c0 --- /dev/null +++ b/vendor/symfony/debug/Resources/ext/php_symfony_debug.h @@ -0,0 +1,60 @@ +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +#ifndef PHP_SYMFONY_DEBUG_H +#define PHP_SYMFONY_DEBUG_H + +extern zend_module_entry symfony_debug_module_entry; +#define phpext_symfony_debug_ptr &symfony_debug_module_entry + +#define PHP_SYMFONY_DEBUG_VERSION "2.7" + +#ifdef PHP_WIN32 +# define PHP_SYMFONY_DEBUG_API __declspec(dllexport) +#elif defined(__GNUC__) && __GNUC__ >= 4 +# define PHP_SYMFONY_DEBUG_API __attribute__ ((visibility("default"))) +#else +# define PHP_SYMFONY_DEBUG_API +#endif + +#ifdef ZTS +#include "TSRM.h" +#endif + +ZEND_BEGIN_MODULE_GLOBALS(symfony_debug) + intptr_t req_rand_init; + void (*old_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args); + zval *debug_bt; +ZEND_END_MODULE_GLOBALS(symfony_debug) + +PHP_MINIT_FUNCTION(symfony_debug); +PHP_MSHUTDOWN_FUNCTION(symfony_debug); +PHP_RINIT_FUNCTION(symfony_debug); +PHP_RSHUTDOWN_FUNCTION(symfony_debug); +PHP_MINFO_FUNCTION(symfony_debug); +PHP_GINIT_FUNCTION(symfony_debug); +PHP_GSHUTDOWN_FUNCTION(symfony_debug); + +PHP_FUNCTION(symfony_zval_info); +PHP_FUNCTION(symfony_debug_backtrace); + +static char *_symfony_debug_memory_address_hash(void * TSRMLS_DC); +static const char *_symfony_debug_zval_type(zval *); +static const char* _symfony_debug_get_resource_type(long TSRMLS_DC); +static int _symfony_debug_get_resource_refcount(long TSRMLS_DC); + +void symfony_debug_error_cb(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args); + +#ifdef ZTS +#define SYMFONY_DEBUG_G(v) TSRMG(symfony_debug_globals_id, zend_symfony_debug_globals *, v) +#else +#define SYMFONY_DEBUG_G(v) (symfony_debug_globals.v) +#endif + +#endif /* PHP_SYMFONY_DEBUG_H */ diff --git a/vendor/symfony/debug/Resources/ext/symfony_debug.c b/vendor/symfony/debug/Resources/ext/symfony_debug.c new file mode 100644 index 00000000..0d7cb602 --- /dev/null +++ b/vendor/symfony/debug/Resources/ext/symfony_debug.c @@ -0,0 +1,283 @@ +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php.h" +#ifdef ZTS +#include "TSRM.h" +#endif +#include "php_ini.h" +#include "ext/standard/info.h" +#include "php_symfony_debug.h" +#include "ext/standard/php_rand.h" +#include "ext/standard/php_lcg.h" +#include "ext/spl/php_spl.h" +#include "Zend/zend_gc.h" +#include "Zend/zend_builtin_functions.h" +#include "Zend/zend_extensions.h" /* for ZEND_EXTENSION_API_NO */ +#include "ext/standard/php_array.h" +#include "Zend/zend_interfaces.h" +#include "SAPI.h" + +#define IS_PHP_53 ZEND_EXTENSION_API_NO == 220090626 + +ZEND_DECLARE_MODULE_GLOBALS(symfony_debug) + +ZEND_BEGIN_ARG_INFO_EX(symfony_zval_arginfo, 0, 0, 2) + ZEND_ARG_INFO(0, key) + ZEND_ARG_ARRAY_INFO(0, array, 0) + ZEND_ARG_INFO(0, options) +ZEND_END_ARG_INFO() + +const zend_function_entry symfony_debug_functions[] = { + PHP_FE(symfony_zval_info, symfony_zval_arginfo) + PHP_FE(symfony_debug_backtrace, NULL) + PHP_FE_END +}; + +PHP_FUNCTION(symfony_debug_backtrace) +{ + if (zend_parse_parameters_none() == FAILURE) { + return; + } +#if IS_PHP_53 + zend_fetch_debug_backtrace(return_value, 1, 0 TSRMLS_CC); +#else + zend_fetch_debug_backtrace(return_value, 1, 0, 0 TSRMLS_CC); +#endif + + if (!SYMFONY_DEBUG_G(debug_bt)) { + return; + } + + php_array_merge(Z_ARRVAL_P(return_value), Z_ARRVAL_P(SYMFONY_DEBUG_G(debug_bt)), 0 TSRMLS_CC); +} + +PHP_FUNCTION(symfony_zval_info) +{ + zval *key = NULL, *arg = NULL; + zval **data = NULL; + HashTable *array = NULL; + long options = 0; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zh|l", &key, &array, &options) == FAILURE) { + return; + } + + switch (Z_TYPE_P(key)) { + case IS_STRING: + if (zend_symtable_find(array, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, (void **)&data) == FAILURE) { + return; + } + break; + case IS_LONG: + if (zend_hash_index_find(array, Z_LVAL_P(key), (void **)&data)) { + return; + } + break; + } + + arg = *data; + + array_init(return_value); + + add_assoc_string(return_value, "type", (char *)_symfony_debug_zval_type(arg), 1); + add_assoc_stringl(return_value, "zval_hash", _symfony_debug_memory_address_hash((void *)arg TSRMLS_CC), 16, 0); + add_assoc_long(return_value, "zval_refcount", Z_REFCOUNT_P(arg)); + add_assoc_bool(return_value, "zval_isref", (zend_bool)Z_ISREF_P(arg)); + + if (Z_TYPE_P(arg) == IS_OBJECT) { + char hash[33] = {0}; + + php_spl_object_hash(arg, (char *)hash TSRMLS_CC); + add_assoc_stringl(return_value, "object_class", (char *)Z_OBJCE_P(arg)->name, Z_OBJCE_P(arg)->name_length, 1); + add_assoc_long(return_value, "object_refcount", EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(arg)].bucket.obj.refcount); + add_assoc_string(return_value, "object_hash", hash, 1); + add_assoc_long(return_value, "object_handle", Z_OBJ_HANDLE_P(arg)); + } else if (Z_TYPE_P(arg) == IS_ARRAY) { + add_assoc_long(return_value, "array_count", zend_hash_num_elements(Z_ARRVAL_P(arg))); + } else if(Z_TYPE_P(arg) == IS_RESOURCE) { + add_assoc_long(return_value, "resource_handle", Z_LVAL_P(arg)); + add_assoc_string(return_value, "resource_type", (char *)_symfony_debug_get_resource_type(Z_LVAL_P(arg) TSRMLS_CC), 1); + add_assoc_long(return_value, "resource_refcount", _symfony_debug_get_resource_refcount(Z_LVAL_P(arg) TSRMLS_CC)); + } else if (Z_TYPE_P(arg) == IS_STRING) { + add_assoc_long(return_value, "strlen", Z_STRLEN_P(arg)); + } +} + +void symfony_debug_error_cb(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args) +{ + TSRMLS_FETCH(); + zval *retval; + + switch (type) { + case E_ERROR: + case E_PARSE: + case E_CORE_ERROR: + case E_CORE_WARNING: + case E_COMPILE_ERROR: + case E_COMPILE_WARNING: + ALLOC_INIT_ZVAL(retval); +#if IS_PHP_53 + zend_fetch_debug_backtrace(retval, 1, 0 TSRMLS_CC); +#else + zend_fetch_debug_backtrace(retval, 1, 0, 0 TSRMLS_CC); +#endif + SYMFONY_DEBUG_G(debug_bt) = retval; + } + + SYMFONY_DEBUG_G(old_error_cb)(type, error_filename, error_lineno, format, args); +} + +static const char* _symfony_debug_get_resource_type(long rsid TSRMLS_DC) +{ + const char *res_type; + res_type = zend_rsrc_list_get_rsrc_type(rsid TSRMLS_CC); + + if (!res_type) { + return "Unknown"; + } + + return res_type; +} + +static int _symfony_debug_get_resource_refcount(long rsid TSRMLS_DC) +{ + zend_rsrc_list_entry *le; + + if (zend_hash_index_find(&EG(regular_list), rsid, (void **) &le)==SUCCESS) { + return le->refcount; + } + + return 0; +} + +static char *_symfony_debug_memory_address_hash(void *address TSRMLS_DC) +{ + char *result = NULL; + intptr_t address_rand; + + if (!SYMFONY_DEBUG_G(req_rand_init)) { + if (!BG(mt_rand_is_seeded)) { + php_mt_srand(GENERATE_SEED() TSRMLS_CC); + } + SYMFONY_DEBUG_G(req_rand_init) = (intptr_t)php_mt_rand(TSRMLS_C); + } + + address_rand = (intptr_t)address ^ SYMFONY_DEBUG_G(req_rand_init); + + spprintf(&result, 17, "%016zx", address_rand); + + return result; +} + +static const char *_symfony_debug_zval_type(zval *zv) +{ + switch (Z_TYPE_P(zv)) { + case IS_NULL: + return "NULL"; + break; + + case IS_BOOL: + return "boolean"; + break; + + case IS_LONG: + return "integer"; + break; + + case IS_DOUBLE: + return "double"; + break; + + case IS_STRING: + return "string"; + break; + + case IS_ARRAY: + return "array"; + break; + + case IS_OBJECT: + return "object"; + + case IS_RESOURCE: + return "resource"; + + default: + return "unknown type"; + } +} + +zend_module_entry symfony_debug_module_entry = { + STANDARD_MODULE_HEADER, + "symfony_debug", + symfony_debug_functions, + PHP_MINIT(symfony_debug), + PHP_MSHUTDOWN(symfony_debug), + PHP_RINIT(symfony_debug), + PHP_RSHUTDOWN(symfony_debug), + PHP_MINFO(symfony_debug), + PHP_SYMFONY_DEBUG_VERSION, + PHP_MODULE_GLOBALS(symfony_debug), + PHP_GINIT(symfony_debug), + PHP_GSHUTDOWN(symfony_debug), + NULL, + STANDARD_MODULE_PROPERTIES_EX +}; + +#ifdef COMPILE_DL_SYMFONY_DEBUG +ZEND_GET_MODULE(symfony_debug) +#endif + +PHP_GINIT_FUNCTION(symfony_debug) +{ + memset(symfony_debug_globals, 0 , sizeof(*symfony_debug_globals)); +} + +PHP_GSHUTDOWN_FUNCTION(symfony_debug) +{ + +} + +PHP_MINIT_FUNCTION(symfony_debug) +{ + SYMFONY_DEBUG_G(old_error_cb) = zend_error_cb; + zend_error_cb = symfony_debug_error_cb; + + return SUCCESS; +} + +PHP_MSHUTDOWN_FUNCTION(symfony_debug) +{ + zend_error_cb = SYMFONY_DEBUG_G(old_error_cb); + + return SUCCESS; +} + +PHP_RINIT_FUNCTION(symfony_debug) +{ + return SUCCESS; +} + +PHP_RSHUTDOWN_FUNCTION(symfony_debug) +{ + return SUCCESS; +} + +PHP_MINFO_FUNCTION(symfony_debug) +{ + php_info_print_table_start(); + php_info_print_table_header(2, "Symfony Debug support", "enabled"); + php_info_print_table_header(2, "Symfony Debug version", PHP_SYMFONY_DEBUG_VERSION); + php_info_print_table_end(); +} diff --git a/vendor/symfony/debug/Resources/ext/tests/001.phpt b/vendor/symfony/debug/Resources/ext/tests/001.phpt new file mode 100644 index 00000000..15e183a7 --- /dev/null +++ b/vendor/symfony/debug/Resources/ext/tests/001.phpt @@ -0,0 +1,153 @@ +--TEST-- +Test symfony_zval_info API +--SKIPIF-- +<?php if (!extension_loaded('symfony_debug')) print 'skip'; ?> +--FILE-- +<?php + +$int = 42; +$float = 42.42; +$str = 'foobar'; +$object = new StdClass(); +$array = array('foo', 'bar'); +$resource = tmpfile(); +$null = null; +$bool = true; + +$anotherint = 42; +$refcount2 = &$anotherint; + +$var = array( + 'int' => $int, + 'float' => $float, + 'str' => $str, + 'object' => $object, + 'array' => $array, + 'resource' => $resource, + 'null' => $null, + 'bool' => $bool, + 'refcount' => &$refcount2, +); + +var_dump(symfony_zval_info('int', $var)); +var_dump(symfony_zval_info('float', $var)); +var_dump(symfony_zval_info('str', $var)); +var_dump(symfony_zval_info('object', $var)); +var_dump(symfony_zval_info('array', $var)); +var_dump(symfony_zval_info('resource', $var)); +var_dump(symfony_zval_info('null', $var)); +var_dump(symfony_zval_info('bool', $var)); + +var_dump(symfony_zval_info('refcount', $var)); +var_dump(symfony_zval_info('not-exist', $var)); +?> +--EXPECTF-- +array(4) { + ["type"]=> + string(7) "integer" + ["zval_hash"]=> + string(16) "%s" + ["zval_refcount"]=> + int(2) + ["zval_isref"]=> + bool(false) +} +array(4) { + ["type"]=> + string(6) "double" + ["zval_hash"]=> + string(16) "%s" + ["zval_refcount"]=> + int(2) + ["zval_isref"]=> + bool(false) +} +array(5) { + ["type"]=> + string(6) "string" + ["zval_hash"]=> + string(16) "%s" + ["zval_refcount"]=> + int(2) + ["zval_isref"]=> + bool(false) + ["strlen"]=> + int(6) +} +array(8) { + ["type"]=> + string(6) "object" + ["zval_hash"]=> + string(16) "%s" + ["zval_refcount"]=> + int(2) + ["zval_isref"]=> + bool(false) + ["object_class"]=> + string(8) "stdClass" + ["object_refcount"]=> + int(1) + ["object_hash"]=> + string(32) "%s" + ["object_handle"]=> + int(%d) +} +array(5) { + ["type"]=> + string(5) "array" + ["zval_hash"]=> + string(16) "%s" + ["zval_refcount"]=> + int(2) + ["zval_isref"]=> + bool(false) + ["array_count"]=> + int(2) +} +array(7) { + ["type"]=> + string(8) "resource" + ["zval_hash"]=> + string(16) "%s" + ["zval_refcount"]=> + int(2) + ["zval_isref"]=> + bool(false) + ["resource_handle"]=> + int(%d) + ["resource_type"]=> + string(6) "stream" + ["resource_refcount"]=> + int(1) +} +array(4) { + ["type"]=> + string(4) "NULL" + ["zval_hash"]=> + string(16) "%s" + ["zval_refcount"]=> + int(2) + ["zval_isref"]=> + bool(false) +} +array(4) { + ["type"]=> + string(7) "boolean" + ["zval_hash"]=> + string(16) "%s" + ["zval_refcount"]=> + int(2) + ["zval_isref"]=> + bool(false) +} +array(4) { + ["type"]=> + string(7) "integer" + ["zval_hash"]=> + string(16) "%s" + ["zval_refcount"]=> + int(3) + ["zval_isref"]=> + bool(true) +} +NULL diff --git a/vendor/symfony/debug/Resources/ext/tests/002.phpt b/vendor/symfony/debug/Resources/ext/tests/002.phpt new file mode 100644 index 00000000..2bc6d712 --- /dev/null +++ b/vendor/symfony/debug/Resources/ext/tests/002.phpt @@ -0,0 +1,63 @@ +--TEST-- +Test symfony_debug_backtrace in case of fatal error +--SKIPIF-- +<?php if (!extension_loaded('symfony_debug')) print 'skip'; ?> +--FILE-- +<?php + +function bar() +{ + foo(); +} + +function foo() +{ + notexist(); +} + +function bt() +{ + print_r(symfony_debug_backtrace()); +} + +register_shutdown_function('bt'); + +bar(); + +?> +--EXPECTF-- +Fatal error: Call to undefined function notexist() in %s on line %d +Array +( + [0] => Array + ( + [function] => bt + [args] => Array + ( + ) + + ) + + [1] => Array + ( + [file] => %s + [line] => %d + [function] => foo + [args] => Array + ( + ) + + ) + + [2] => Array + ( + [file] => %s + [line] => %d + [function] => bar + [args] => Array + ( + ) + + ) + +) diff --git a/vendor/symfony/debug/Resources/ext/tests/002_1.phpt b/vendor/symfony/debug/Resources/ext/tests/002_1.phpt new file mode 100644 index 00000000..4e9e34f1 --- /dev/null +++ b/vendor/symfony/debug/Resources/ext/tests/002_1.phpt @@ -0,0 +1,46 @@ +--TEST-- +Test symfony_debug_backtrace in case of non fatal error +--SKIPIF-- +<?php if (!extension_loaded('symfony_debug')) print 'skip'; ?> +--FILE-- +<?php + +function bar() +{ + bt(); +} + +function bt() +{ + print_r(symfony_debug_backtrace()); +} + +bar(); + +?> +--EXPECTF-- +Array +( + [0] => Array + ( + [file] => %s + [line] => %d + [function] => bt + [args] => Array + ( + ) + + ) + + [1] => Array + ( + [file] => %s + [line] => %d + [function] => bar + [args] => Array + ( + ) + + ) + +) diff --git a/vendor/symfony/debug/Resources/ext/tests/003.phpt b/vendor/symfony/debug/Resources/ext/tests/003.phpt new file mode 100644 index 00000000..2a494e27 --- /dev/null +++ b/vendor/symfony/debug/Resources/ext/tests/003.phpt @@ -0,0 +1,85 @@ +--TEST-- +Test ErrorHandler in case of fatal error +--SKIPIF-- +<?php if (!extension_loaded('symfony_debug')) print 'skip'; ?> +--FILE-- +<?php + +namespace Psr\Log; + +class LogLevel +{ + const EMERGENCY = 'emergency'; + const ALERT = 'alert'; + const CRITICAL = 'critical'; + const ERROR = 'error'; + const WARNING = 'warning'; + const NOTICE = 'notice'; + const INFO = 'info'; + const DEBUG = 'debug'; +} + +namespace Symfony\Component\Debug; + +$dir = __DIR__.'/../../../'; +require $dir.'ErrorHandler.php'; +require $dir.'Exception/FatalErrorException.php'; +require $dir.'Exception/UndefinedFunctionException.php'; +require $dir.'FatalErrorHandler/FatalErrorHandlerInterface.php'; +require $dir.'FatalErrorHandler/ClassNotFoundFatalErrorHandler.php'; +require $dir.'FatalErrorHandler/UndefinedFunctionFatalErrorHandler.php'; +require $dir.'FatalErrorHandler/UndefinedMethodFatalErrorHandler.php'; + +function bar() +{ + foo(); +} + +function foo() +{ + notexist(); +} + +$handler = ErrorHandler::register(); +$handler->setExceptionHandler('print_r'); + +if (function_exists('xdebug_disable')) { + xdebug_disable(); +} + +bar(); +?> +--EXPECTF-- +Fatal error: Call to undefined function Symfony\Component\Debug\notexist() in %s on line %d +Symfony\Component\Debug\Exception\UndefinedFunctionException Object +( + [message:protected] => Attempted to call function "notexist" from namespace "Symfony\Component\Debug". + [string:Exception:private] => + [code:protected] => 0 + [file:protected] => %s + [line:protected] => %d + [trace:Exception:private] => Array + ( + [0] => Array + ( +%A [function] => Symfony\Component\Debug\foo +%A [args] => Array + ( + ) + + ) + + [1] => Array + ( +%A [function] => Symfony\Component\Debug\bar +%A [args] => Array + ( + ) + + ) +%A + ) + + [previous:Exception:private] => + [severity:protected] => 1 +) diff --git a/vendor/symfony/debug/Tests/DebugClassLoaderTest.php b/vendor/symfony/debug/Tests/DebugClassLoaderTest.php new file mode 100644 index 00000000..0219f533 --- /dev/null +++ b/vendor/symfony/debug/Tests/DebugClassLoaderTest.php @@ -0,0 +1,425 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Debug\Tests; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Debug\DebugClassLoader; +use Symfony\Component\Debug\ErrorHandler; + +class DebugClassLoaderTest extends TestCase +{ + /** + * @var int Error reporting level before running tests + */ + private $errorReporting; + + private $loader; + + protected function setUp() + { + $this->errorReporting = error_reporting(E_ALL); + $this->loader = new ClassLoader(); + spl_autoload_register(array($this->loader, 'loadClass'), true, true); + DebugClassLoader::enable(); + } + + protected function tearDown() + { + DebugClassLoader::disable(); + spl_autoload_unregister(array($this->loader, 'loadClass')); + error_reporting($this->errorReporting); + } + + public function testIdempotence() + { + DebugClassLoader::enable(); + + $functions = spl_autoload_functions(); + foreach ($functions as $function) { + if (is_array($function) && $function[0] instanceof DebugClassLoader) { + $reflClass = new \ReflectionClass($function[0]); + $reflProp = $reflClass->getProperty('classLoader'); + $reflProp->setAccessible(true); + + $this->assertNotInstanceOf('Symfony\Component\Debug\DebugClassLoader', $reflProp->getValue($function[0])); + + return; + } + } + + $this->fail('DebugClassLoader did not register'); + } + + /** + * @expectedException \Exception + * @expectedExceptionMessage boo + */ + public function testThrowingClass() + { + try { + class_exists(__NAMESPACE__.'\Fixtures\Throwing'); + $this->fail('Exception expected'); + } catch (\Exception $e) { + $this->assertSame('boo', $e->getMessage()); + } + + // the second call also should throw + class_exists(__NAMESPACE__.'\Fixtures\Throwing'); + } + + public function testUnsilencing() + { + if (\PHP_VERSION_ID >= 70000) { + $this->markTestSkipped('PHP7 throws exceptions, unsilencing is not required anymore.'); + } + if (defined('HHVM_VERSION')) { + $this->markTestSkipped('HHVM is not handled in this test case.'); + } + + ob_start(); + + $this->iniSet('log_errors', 0); + $this->iniSet('display_errors', 1); + + // See below: this will fail with parse error + // but this should not be @-silenced. + @class_exists(__NAMESPACE__.'\TestingUnsilencing', true); + + $output = ob_get_clean(); + + $this->assertStringMatchesFormat('%aParse error%a', $output); + } + + public function testStacking() + { + // the ContextErrorException must not be loaded to test the workaround + // for https://bugs.php.net/65322. + if (class_exists('Symfony\Component\Debug\Exception\ContextErrorException', false)) { + $this->markTestSkipped('The ContextErrorException class is already loaded.'); + } + if (defined('HHVM_VERSION')) { + $this->markTestSkipped('HHVM is not handled in this test case.'); + } + + ErrorHandler::register(); + + try { + // Trigger autoloading + E_STRICT at compile time + // which in turn triggers $errorHandler->handle() + // that again triggers autoloading for ContextErrorException. + // Error stacking works around the bug above and everything is fine. + + eval(' + namespace '.__NAMESPACE__.'; + class ChildTestingStacking extends TestingStacking { function foo($bar) {} } + '); + $this->fail('ContextErrorException expected'); + } catch (\ErrorException $exception) { + // if an exception is thrown, the test passed + $this->assertStringStartsWith(__FILE__, $exception->getFile()); + if (\PHP_VERSION_ID < 70000) { + $this->assertRegExp('/^Runtime Notice: Declaration/', $exception->getMessage()); + $this->assertEquals(E_STRICT, $exception->getSeverity()); + } else { + $this->assertRegExp('/^Warning: Declaration/', $exception->getMessage()); + $this->assertEquals(E_WARNING, $exception->getSeverity()); + } + } finally { + restore_error_handler(); + restore_exception_handler(); + } + } + + /** + * @expectedException \RuntimeException + * @expectedExceptionMessage Case mismatch between loaded and declared class names + */ + public function testNameCaseMismatch() + { + class_exists(__NAMESPACE__.'\TestingCaseMismatch', true); + } + + /** + * @expectedException \RuntimeException + * @expectedExceptionMessage Case mismatch between class and real file names + */ + public function testFileCaseMismatch() + { + if (!file_exists(__DIR__.'/Fixtures/CaseMismatch.php')) { + $this->markTestSkipped('Can only be run on case insensitive filesystems'); + } + + class_exists(__NAMESPACE__.'\Fixtures\CaseMismatch', true); + } + + /** + * @expectedException \RuntimeException + * @expectedExceptionMessage Case mismatch between loaded and declared class names + */ + public function testPsr4CaseMismatch() + { + class_exists(__NAMESPACE__.'\Fixtures\Psr4CaseMismatch', true); + } + + public function testNotPsr0() + { + $this->assertTrue(class_exists(__NAMESPACE__.'\Fixtures\NotPSR0', true)); + } + + public function testNotPsr0Bis() + { + $this->assertTrue(class_exists(__NAMESPACE__.'\Fixtures\NotPSR0bis', true)); + } + + public function testClassAlias() + { + $this->assertTrue(class_exists(__NAMESPACE__.'\Fixtures\ClassAlias', true)); + } + + /** + * @dataProvider provideDeprecatedSuper + */ + public function testDeprecatedSuper($class, $super, $type) + { + set_error_handler(function () { return false; }); + $e = error_reporting(0); + trigger_error('', E_USER_DEPRECATED); + + class_exists('Test\\'.__NAMESPACE__.'\\'.$class, true); + + error_reporting($e); + restore_error_handler(); + + $lastError = error_get_last(); + unset($lastError['file'], $lastError['line']); + + $xError = array( + 'type' => E_USER_DEPRECATED, + 'message' => 'The "Test\Symfony\Component\Debug\Tests\\'.$class.'" class '.$type.' "Symfony\Component\Debug\Tests\Fixtures\\'.$super.'" that is deprecated but this is a test deprecation notice.', + ); + + $this->assertSame($xError, $lastError); + } + + public function provideDeprecatedSuper() + { + return array( + array('DeprecatedInterfaceClass', 'DeprecatedInterface', 'implements'), + array('DeprecatedParentClass', 'DeprecatedClass', 'extends'), + ); + } + + public function testInterfaceExtendsDeprecatedInterface() + { + set_error_handler(function () { return false; }); + $e = error_reporting(0); + trigger_error('', E_USER_NOTICE); + + class_exists('Test\\'.__NAMESPACE__.'\\NonDeprecatedInterfaceClass', true); + + error_reporting($e); + restore_error_handler(); + + $lastError = error_get_last(); + unset($lastError['file'], $lastError['line']); + + $xError = array( + 'type' => E_USER_NOTICE, + 'message' => '', + ); + + $this->assertSame($xError, $lastError); + } + + public function testDeprecatedSuperInSameNamespace() + { + set_error_handler(function () { return false; }); + $e = error_reporting(0); + trigger_error('', E_USER_NOTICE); + + class_exists('Symfony\Bridge\Debug\Tests\Fixtures\ExtendsDeprecatedParent', true); + + error_reporting($e); + restore_error_handler(); + + $lastError = error_get_last(); + unset($lastError['file'], $lastError['line']); + + $xError = array( + 'type' => E_USER_NOTICE, + 'message' => '', + ); + + $this->assertSame($xError, $lastError); + } + + public function testReservedForPhp7() + { + if (\PHP_VERSION_ID >= 70000) { + $this->markTestSkipped('PHP7 already prevents using reserved names.'); + } + + set_error_handler(function () { return false; }); + $e = error_reporting(0); + trigger_error('', E_USER_NOTICE); + + class_exists('Test\\'.__NAMESPACE__.'\\Float', true); + + error_reporting($e); + restore_error_handler(); + + $lastError = error_get_last(); + unset($lastError['file'], $lastError['line']); + + $xError = array( + 'type' => E_USER_DEPRECATED, + 'message' => 'The "Test\Symfony\Component\Debug\Tests\Float" class uses the reserved name "Float", it will break on PHP 7 and higher', + ); + + $this->assertSame($xError, $lastError); + } + + public function testExtendedFinalClass() + { + set_error_handler(function () { return false; }); + $e = error_reporting(0); + trigger_error('', E_USER_NOTICE); + + class_exists('Test\\'.__NAMESPACE__.'\\ExtendsFinalClass', true); + + error_reporting($e); + restore_error_handler(); + + $lastError = error_get_last(); + unset($lastError['file'], $lastError['line']); + + $xError = array( + 'type' => E_USER_DEPRECATED, + 'message' => 'The "Symfony\Component\Debug\Tests\Fixtures\FinalClass" class is considered final since version 3.3. It may change without further notice as of its next major version. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsFinalClass".', + ); + + $this->assertSame($xError, $lastError); + } + + public function testExtendedFinalMethod() + { + set_error_handler(function () { return false; }); + $e = error_reporting(0); + trigger_error('', E_USER_NOTICE); + + class_exists(__NAMESPACE__.'\\Fixtures\\ExtendedFinalMethod', true); + + error_reporting($e); + restore_error_handler(); + + $lastError = error_get_last(); + unset($lastError['file'], $lastError['line']); + + $xError = array( + 'type' => E_USER_DEPRECATED, + 'message' => 'The "Symfony\Component\Debug\Tests\Fixtures\FinalMethod::finalMethod()" method is considered final since version 3.3. It may change without further notice as of its next major version. You should not extend it from "Symfony\Component\Debug\Tests\Fixtures\ExtendedFinalMethod".', + ); + + $this->assertSame($xError, $lastError); + } + + public function testExtendedDeprecatedMethodDoesntTriggerAnyNotice() + { + set_error_handler(function () { return false; }); + $e = error_reporting(0); + trigger_error('', E_USER_NOTICE); + + class_exists('Test\\'.__NAMESPACE__.'\\ExtendsAnnotatedClass', true); + + error_reporting($e); + restore_error_handler(); + + $lastError = error_get_last(); + unset($lastError['file'], $lastError['line']); + + $this->assertSame(array('type' => E_USER_NOTICE, 'message' => ''), $lastError); + } + + public function testInternalsUse() + { + $deprecations = array(); + set_error_handler(function ($type, $msg) use (&$deprecations) { $deprecations[] = $msg; }); + $e = error_reporting(E_USER_DEPRECATED); + + class_exists('Test\\'.__NAMESPACE__.'\\ExtendsInternals', true); + + error_reporting($e); + restore_error_handler(); + + $this->assertSame($deprecations, array( + 'The "Symfony\Component\Debug\Tests\Fixtures\InternalClass" class is considered internal since version 3.4. It may change without further notice. You should not use it from "Test\Symfony\Component\Debug\Tests\ExtendsInternalsParent".', + 'The "Symfony\Component\Debug\Tests\Fixtures\InternalInterface" interface is considered internal. It may change without further notice. You should not use it from "Test\Symfony\Component\Debug\Tests\ExtendsInternalsParent".', + 'The "Symfony\Component\Debug\Tests\Fixtures\InternalTrait" trait is considered internal. It may change without further notice. You should not use it from "Test\Symfony\Component\Debug\Tests\ExtendsInternals".', + 'The "Symfony\Component\Debug\Tests\Fixtures\InternalTrait2::internalMethod()" method is considered internal since version 3.4. It may change without further notice. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsInternals".', + )); + } +} + +class ClassLoader +{ + public function loadClass($class) + { + } + + public function getClassMap() + { + return array(__NAMESPACE__.'\Fixtures\NotPSR0bis' => __DIR__.'/Fixtures/notPsr0Bis.php'); + } + + public function findFile($class) + { + $fixtureDir = __DIR__.DIRECTORY_SEPARATOR.'Fixtures'.DIRECTORY_SEPARATOR; + + if (__NAMESPACE__.'\TestingUnsilencing' === $class) { + eval('-- parse error --'); + } elseif (__NAMESPACE__.'\TestingStacking' === $class) { + eval('namespace '.__NAMESPACE__.'; class TestingStacking { function foo() {} }'); + } elseif (__NAMESPACE__.'\TestingCaseMismatch' === $class) { + eval('namespace '.__NAMESPACE__.'; class TestingCaseMisMatch {}'); + } elseif (__NAMESPACE__.'\Fixtures\Psr4CaseMismatch' === $class) { + return $fixtureDir.'psr4'.DIRECTORY_SEPARATOR.'Psr4CaseMismatch.php'; + } elseif (__NAMESPACE__.'\Fixtures\NotPSR0' === $class) { + return $fixtureDir.'reallyNotPsr0.php'; + } elseif (__NAMESPACE__.'\Fixtures\NotPSR0bis' === $class) { + return $fixtureDir.'notPsr0Bis.php'; + } elseif ('Symfony\Bridge\Debug\Tests\Fixtures\ExtendsDeprecatedParent' === $class) { + eval('namespace Symfony\Bridge\Debug\Tests\Fixtures; class ExtendsDeprecatedParent extends \\'.__NAMESPACE__.'\Fixtures\DeprecatedClass {}'); + } elseif ('Test\\'.__NAMESPACE__.'\DeprecatedParentClass' === $class) { + eval('namespace Test\\'.__NAMESPACE__.'; class DeprecatedParentClass extends \\'.__NAMESPACE__.'\Fixtures\DeprecatedClass {}'); + } elseif ('Test\\'.__NAMESPACE__.'\DeprecatedInterfaceClass' === $class) { + eval('namespace Test\\'.__NAMESPACE__.'; class DeprecatedInterfaceClass implements \\'.__NAMESPACE__.'\Fixtures\DeprecatedInterface {}'); + } elseif ('Test\\'.__NAMESPACE__.'\NonDeprecatedInterfaceClass' === $class) { + eval('namespace Test\\'.__NAMESPACE__.'; class NonDeprecatedInterfaceClass implements \\'.__NAMESPACE__.'\Fixtures\NonDeprecatedInterface {}'); + } elseif ('Test\\'.__NAMESPACE__.'\Float' === $class) { + eval('namespace Test\\'.__NAMESPACE__.'; class Float {}'); + } elseif ('Test\\'.__NAMESPACE__.'\ExtendsFinalClass' === $class) { + eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsFinalClass extends \\'.__NAMESPACE__.'\Fixtures\FinalClass {}'); + } elseif ('Test\\'.__NAMESPACE__.'\ExtendsAnnotatedClass' === $class) { + eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsAnnotatedClass extends \\'.__NAMESPACE__.'\Fixtures\AnnotatedClass { + public function deprecatedMethod() { } + }'); + } elseif ('Test\\'.__NAMESPACE__.'\ExtendsInternals' === $class) { + eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsInternals extends ExtendsInternalsParent { + use \\'.__NAMESPACE__.'\Fixtures\InternalTrait; + + public function internalMethod() { } + }'); + } elseif ('Test\\'.__NAMESPACE__.'\ExtendsInternalsParent' === $class) { + eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsInternalsParent extends \\'.__NAMESPACE__.'\Fixtures\InternalClass implements \\'.__NAMESPACE__.'\Fixtures\InternalInterface { }'); + } + } +} diff --git a/vendor/symfony/debug/Tests/ErrorHandlerTest.php b/vendor/symfony/debug/Tests/ErrorHandlerTest.php new file mode 100644 index 00000000..4cbe47f3 --- /dev/null +++ b/vendor/symfony/debug/Tests/ErrorHandlerTest.php @@ -0,0 +1,536 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Debug\Tests; + +use PHPUnit\Framework\TestCase; +use Psr\Log\LogLevel; +use Symfony\Component\Debug\BufferingLogger; +use Symfony\Component\Debug\ErrorHandler; +use Symfony\Component\Debug\Exception\SilencedErrorContext; + +/** + * ErrorHandlerTest. + * + * @author Robert Schönthal <seroscho@googlemail.com> + * @author Nicolas Grekas <p@tchwork.com> + */ +class ErrorHandlerTest extends TestCase +{ + public function testRegister() + { + $handler = ErrorHandler::register(); + + try { + $this->assertInstanceOf('Symfony\Component\Debug\ErrorHandler', $handler); + $this->assertSame($handler, ErrorHandler::register()); + + $newHandler = new ErrorHandler(); + + $this->assertSame($newHandler, ErrorHandler::register($newHandler, false)); + $h = set_error_handler('var_dump'); + restore_error_handler(); + $this->assertSame(array($handler, 'handleError'), $h); + + try { + $this->assertSame($newHandler, ErrorHandler::register($newHandler, true)); + $h = set_error_handler('var_dump'); + restore_error_handler(); + $this->assertSame(array($newHandler, 'handleError'), $h); + } catch (\Exception $e) { + } + + restore_error_handler(); + restore_exception_handler(); + + if (isset($e)) { + throw $e; + } + } catch (\Exception $e) { + } + + restore_error_handler(); + restore_exception_handler(); + + if (isset($e)) { + throw $e; + } + } + + public function testNotice() + { + ErrorHandler::register(); + + try { + self::triggerNotice($this); + $this->fail('ErrorException expected'); + } catch (\ErrorException $exception) { + // if an exception is thrown, the test passed + $this->assertEquals(E_NOTICE, $exception->getSeverity()); + $this->assertEquals(__FILE__, $exception->getFile()); + $this->assertRegExp('/^Notice: Undefined variable: (foo|bar)/', $exception->getMessage()); + + $trace = $exception->getTrace(); + + $this->assertEquals(__FILE__, $trace[0]['file']); + $this->assertEquals(__CLASS__, $trace[0]['class']); + $this->assertEquals('triggerNotice', $trace[0]['function']); + $this->assertEquals('::', $trace[0]['type']); + + $this->assertEquals(__FILE__, $trace[0]['file']); + $this->assertEquals(__CLASS__, $trace[1]['class']); + $this->assertEquals(__FUNCTION__, $trace[1]['function']); + $this->assertEquals('->', $trace[1]['type']); + } finally { + restore_error_handler(); + restore_exception_handler(); + } + } + + // dummy function to test trace in error handler. + private static function triggerNotice($that) + { + $that->assertSame('', $foo.$foo.$bar); + } + + public function testConstruct() + { + try { + $handler = ErrorHandler::register(); + $handler->throwAt(3, true); + $this->assertEquals(3 | E_RECOVERABLE_ERROR | E_USER_ERROR, $handler->throwAt(0)); + } finally { + restore_error_handler(); + restore_exception_handler(); + } + } + + public function testDefaultLogger() + { + try { + $handler = ErrorHandler::register(); + + $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); + + $handler->setDefaultLogger($logger, E_NOTICE); + $handler->setDefaultLogger($logger, array(E_USER_NOTICE => LogLevel::CRITICAL)); + + $loggers = array( + E_DEPRECATED => array(null, LogLevel::INFO), + E_USER_DEPRECATED => array(null, LogLevel::INFO), + E_NOTICE => array($logger, LogLevel::WARNING), + E_USER_NOTICE => array($logger, LogLevel::CRITICAL), + E_STRICT => array(null, LogLevel::WARNING), + E_WARNING => array(null, LogLevel::WARNING), + E_USER_WARNING => array(null, LogLevel::WARNING), + E_COMPILE_WARNING => array(null, LogLevel::WARNING), + E_CORE_WARNING => array(null, LogLevel::WARNING), + E_USER_ERROR => array(null, LogLevel::CRITICAL), + E_RECOVERABLE_ERROR => array(null, LogLevel::CRITICAL), + E_COMPILE_ERROR => array(null, LogLevel::CRITICAL), + E_PARSE => array(null, LogLevel::CRITICAL), + E_ERROR => array(null, LogLevel::CRITICAL), + E_CORE_ERROR => array(null, LogLevel::CRITICAL), + ); + $this->assertSame($loggers, $handler->setLoggers(array())); + } finally { + restore_error_handler(); + restore_exception_handler(); + } + } + + public function testHandleError() + { + try { + $handler = ErrorHandler::register(); + $handler->throwAt(0, true); + $this->assertFalse($handler->handleError(0, 'foo', 'foo.php', 12, array())); + + restore_error_handler(); + restore_exception_handler(); + + $handler = ErrorHandler::register(); + $handler->throwAt(3, true); + $this->assertFalse($handler->handleError(4, 'foo', 'foo.php', 12, array())); + + restore_error_handler(); + restore_exception_handler(); + + $handler = ErrorHandler::register(); + $handler->throwAt(3, true); + try { + $handler->handleError(4, 'foo', 'foo.php', 12, array()); + } catch (\ErrorException $e) { + $this->assertSame('Parse Error: foo', $e->getMessage()); + $this->assertSame(4, $e->getSeverity()); + $this->assertSame('foo.php', $e->getFile()); + $this->assertSame(12, $e->getLine()); + } + + restore_error_handler(); + restore_exception_handler(); + + $handler = ErrorHandler::register(); + $handler->throwAt(E_USER_DEPRECATED, true); + $this->assertFalse($handler->handleError(E_USER_DEPRECATED, 'foo', 'foo.php', 12, array())); + + restore_error_handler(); + restore_exception_handler(); + + $handler = ErrorHandler::register(); + $handler->throwAt(E_DEPRECATED, true); + $this->assertFalse($handler->handleError(E_DEPRECATED, 'foo', 'foo.php', 12, array())); + + restore_error_handler(); + restore_exception_handler(); + + $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); + + $warnArgCheck = function ($logLevel, $message, $context) { + $this->assertEquals('info', $logLevel); + $this->assertEquals('User Deprecated: foo', $message); + $this->assertArrayHasKey('exception', $context); + $exception = $context['exception']; + $this->assertInstanceOf(\ErrorException::class, $exception); + $this->assertSame('User Deprecated: foo', $exception->getMessage()); + $this->assertSame(E_USER_DEPRECATED, $exception->getSeverity()); + }; + + $logger + ->expects($this->once()) + ->method('log') + ->will($this->returnCallback($warnArgCheck)) + ; + + $handler = ErrorHandler::register(); + $handler->setDefaultLogger($logger, E_USER_DEPRECATED); + $this->assertTrue($handler->handleError(E_USER_DEPRECATED, 'foo', 'foo.php', 12, array())); + + restore_error_handler(); + restore_exception_handler(); + + $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); + + $line = null; + $logArgCheck = function ($level, $message, $context) use (&$line) { + $this->assertEquals('Notice: Undefined variable: undefVar', $message); + $this->assertArrayHasKey('exception', $context); + $exception = $context['exception']; + $this->assertInstanceOf(SilencedErrorContext::class, $exception); + $this->assertSame(E_NOTICE, $exception->getSeverity()); + $this->assertSame(__FILE__, $exception->getFile()); + $this->assertSame($line, $exception->getLine()); + $this->assertNotEmpty($exception->getTrace()); + $this->assertSame(1, $exception->count); + }; + + $logger + ->expects($this->once()) + ->method('log') + ->will($this->returnCallback($logArgCheck)) + ; + + $handler = ErrorHandler::register(); + $handler->setDefaultLogger($logger, E_NOTICE); + $handler->screamAt(E_NOTICE); + unset($undefVar); + $line = __LINE__ + 1; + @$undefVar++; + + restore_error_handler(); + restore_exception_handler(); + } catch (\Exception $e) { + restore_error_handler(); + restore_exception_handler(); + + throw $e; + } + } + + public function testHandleUserError() + { + try { + $handler = ErrorHandler::register(); + $handler->throwAt(0, true); + + $e = null; + $x = new \Exception('Foo'); + + try { + $f = new Fixtures\ToStringThrower($x); + $f .= ''; // Trigger $f->__toString() + } catch (\Exception $e) { + } + + $this->assertSame($x, $e); + } finally { + restore_error_handler(); + restore_exception_handler(); + } + } + + public function testHandleDeprecation() + { + $logArgCheck = function ($level, $message, $context) { + $this->assertEquals(LogLevel::INFO, $level); + $this->assertArrayHasKey('exception', $context); + $exception = $context['exception']; + $this->assertInstanceOf(\ErrorException::class, $exception); + $this->assertSame('User Deprecated: Foo deprecation', $exception->getMessage()); + }; + + $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); + $logger + ->expects($this->once()) + ->method('log') + ->will($this->returnCallback($logArgCheck)) + ; + + $handler = new ErrorHandler(); + $handler->setDefaultLogger($logger); + @$handler->handleError(E_USER_DEPRECATED, 'Foo deprecation', __FILE__, __LINE__, array()); + } + + public function testHandleException() + { + try { + $handler = ErrorHandler::register(); + + $exception = new \Exception('foo'); + + $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); + + $logArgCheck = function ($level, $message, $context) { + $this->assertSame('Uncaught Exception: foo', $message); + $this->assertArrayHasKey('exception', $context); + $this->assertInstanceOf(\Exception::class, $context['exception']); + }; + + $logger + ->expects($this->exactly(2)) + ->method('log') + ->will($this->returnCallback($logArgCheck)) + ; + + $handler->setDefaultLogger($logger, E_ERROR); + + try { + $handler->handleException($exception); + $this->fail('Exception expected'); + } catch (\Exception $e) { + $this->assertSame($exception, $e); + } + + $handler->setExceptionHandler(function ($e) use ($exception) { + $this->assertSame($exception, $e); + }); + + $handler->handleException($exception); + } finally { + restore_error_handler(); + restore_exception_handler(); + } + } + + /** + * @group legacy + */ + public function testErrorStacking() + { + try { + $handler = ErrorHandler::register(); + $handler->screamAt(E_USER_WARNING); + + $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); + + $logger + ->expects($this->exactly(2)) + ->method('log') + ->withConsecutive( + array($this->equalTo(LogLevel::WARNING), $this->equalTo('Dummy log')), + array($this->equalTo(LogLevel::DEBUG), $this->equalTo('User Warning: Silenced warning')) + ) + ; + + $handler->setDefaultLogger($logger, array(E_USER_WARNING => LogLevel::WARNING)); + + ErrorHandler::stackErrors(); + @trigger_error('Silenced warning', E_USER_WARNING); + $logger->log(LogLevel::WARNING, 'Dummy log'); + ErrorHandler::unstackErrors(); + } finally { + restore_error_handler(); + restore_exception_handler(); + } + } + + public function testBootstrappingLogger() + { + $bootLogger = new BufferingLogger(); + $handler = new ErrorHandler($bootLogger); + + $loggers = array( + E_DEPRECATED => array($bootLogger, LogLevel::INFO), + E_USER_DEPRECATED => array($bootLogger, LogLevel::INFO), + E_NOTICE => array($bootLogger, LogLevel::WARNING), + E_USER_NOTICE => array($bootLogger, LogLevel::WARNING), + E_STRICT => array($bootLogger, LogLevel::WARNING), + E_WARNING => array($bootLogger, LogLevel::WARNING), + E_USER_WARNING => array($bootLogger, LogLevel::WARNING), + E_COMPILE_WARNING => array($bootLogger, LogLevel::WARNING), + E_CORE_WARNING => array($bootLogger, LogLevel::WARNING), + E_USER_ERROR => array($bootLogger, LogLevel::CRITICAL), + E_RECOVERABLE_ERROR => array($bootLogger, LogLevel::CRITICAL), + E_COMPILE_ERROR => array($bootLogger, LogLevel::CRITICAL), + E_PARSE => array($bootLogger, LogLevel::CRITICAL), + E_ERROR => array($bootLogger, LogLevel::CRITICAL), + E_CORE_ERROR => array($bootLogger, LogLevel::CRITICAL), + ); + + $this->assertSame($loggers, $handler->setLoggers(array())); + + $handler->handleError(E_DEPRECATED, 'Foo message', __FILE__, 123, array()); + + $logs = $bootLogger->cleanLogs(); + + $this->assertCount(1, $logs); + $log = $logs[0]; + $this->assertSame('info', $log[0]); + $this->assertSame('Deprecated: Foo message', $log[1]); + $this->assertArrayHasKey('exception', $log[2]); + $exception = $log[2]['exception']; + $this->assertInstanceOf(\ErrorException::class, $exception); + $this->assertSame('Deprecated: Foo message', $exception->getMessage()); + $this->assertSame(__FILE__, $exception->getFile()); + $this->assertSame(123, $exception->getLine()); + $this->assertSame(E_DEPRECATED, $exception->getSeverity()); + + $bootLogger->log(LogLevel::WARNING, 'Foo message', array('exception' => $exception)); + + $mockLogger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); + $mockLogger->expects($this->once()) + ->method('log') + ->with(LogLevel::WARNING, 'Foo message', array('exception' => $exception)); + + $handler->setLoggers(array(E_DEPRECATED => array($mockLogger, LogLevel::WARNING))); + } + + public function testSettingLoggerWhenExceptionIsBuffered() + { + $bootLogger = new BufferingLogger(); + $handler = new ErrorHandler($bootLogger); + + $exception = new \Exception('Foo message'); + + $mockLogger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); + $mockLogger->expects($this->once()) + ->method('log') + ->with(LogLevel::CRITICAL, 'Uncaught Exception: Foo message', array('exception' => $exception)); + + $handler->setExceptionHandler(function () use ($handler, $mockLogger) { + $handler->setDefaultLogger($mockLogger); + }); + + $handler->handleException($exception); + } + + public function testHandleFatalError() + { + try { + $handler = ErrorHandler::register(); + + $error = array( + 'type' => E_PARSE, + 'message' => 'foo', + 'file' => 'bar', + 'line' => 123, + ); + + $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); + + $logArgCheck = function ($level, $message, $context) { + $this->assertEquals('Fatal Parse Error: foo', $message); + $this->assertArrayHasKey('exception', $context); + $this->assertInstanceOf(\Exception::class, $context['exception']); + }; + + $logger + ->expects($this->once()) + ->method('log') + ->will($this->returnCallback($logArgCheck)) + ; + + $handler->setDefaultLogger($logger, E_PARSE); + + $handler->handleFatalError($error); + + restore_error_handler(); + restore_exception_handler(); + } catch (\Exception $e) { + restore_error_handler(); + restore_exception_handler(); + + throw $e; + } + } + + /** + * @requires PHP 7 + */ + public function testHandleErrorException() + { + $exception = new \Error("Class 'Foo' not found"); + + $handler = new ErrorHandler(); + $handler->setExceptionHandler(function () use (&$args) { + $args = func_get_args(); + }); + + $handler->handleException($exception); + + $this->assertInstanceOf('Symfony\Component\Debug\Exception\ClassNotFoundException', $args[0]); + $this->assertStringStartsWith("Attempted to load class \"Foo\" from the global namespace.\nDid you forget a \"use\" statement", $args[0]->getMessage()); + } + + public function testHandleFatalErrorOnHHVM() + { + try { + $handler = ErrorHandler::register(); + + $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); + $logger + ->expects($this->once()) + ->method('log') + ->with( + $this->equalTo(LogLevel::CRITICAL), + $this->equalTo('Fatal Error: foo') + ) + ; + + $handler->setDefaultLogger($logger, E_ERROR); + + $error = array( + 'type' => E_ERROR + 0x1000000, // This error level is used by HHVM for fatal errors + 'message' => 'foo', + 'file' => 'bar', + 'line' => 123, + 'context' => array(123), + 'backtrace' => array(456), + ); + + call_user_func_array(array($handler, 'handleError'), $error); + $handler->handleFatalError($error); + } finally { + restore_error_handler(); + restore_exception_handler(); + } + } +} diff --git a/vendor/symfony/debug/Tests/Exception/FlattenExceptionTest.php b/vendor/symfony/debug/Tests/Exception/FlattenExceptionTest.php new file mode 100644 index 00000000..e7762bde --- /dev/null +++ b/vendor/symfony/debug/Tests/Exception/FlattenExceptionTest.php @@ -0,0 +1,301 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Debug\Tests\Exception; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Debug\Exception\FlattenException; +use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException; +use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; +use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException; +use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException; +use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; +use Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException; +use Symfony\Component\HttpKernel\Exception\ConflictHttpException; +use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; +use Symfony\Component\HttpKernel\Exception\GoneHttpException; +use Symfony\Component\HttpKernel\Exception\LengthRequiredHttpException; +use Symfony\Component\HttpKernel\Exception\PreconditionFailedHttpException; +use Symfony\Component\HttpKernel\Exception\PreconditionRequiredHttpException; +use Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException; +use Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException; +use Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException; + +class FlattenExceptionTest extends TestCase +{ + public function testStatusCode() + { + $flattened = FlattenException::create(new \RuntimeException(), 403); + $this->assertEquals('403', $flattened->getStatusCode()); + + $flattened = FlattenException::create(new \RuntimeException()); + $this->assertEquals('500', $flattened->getStatusCode()); + + $flattened = FlattenException::create(new NotFoundHttpException()); + $this->assertEquals('404', $flattened->getStatusCode()); + + $flattened = FlattenException::create(new UnauthorizedHttpException('Basic realm="My Realm"')); + $this->assertEquals('401', $flattened->getStatusCode()); + + $flattened = FlattenException::create(new BadRequestHttpException()); + $this->assertEquals('400', $flattened->getStatusCode()); + + $flattened = FlattenException::create(new NotAcceptableHttpException()); + $this->assertEquals('406', $flattened->getStatusCode()); + + $flattened = FlattenException::create(new ConflictHttpException()); + $this->assertEquals('409', $flattened->getStatusCode()); + + $flattened = FlattenException::create(new MethodNotAllowedHttpException(array('POST'))); + $this->assertEquals('405', $flattened->getStatusCode()); + + $flattened = FlattenException::create(new AccessDeniedHttpException()); + $this->assertEquals('403', $flattened->getStatusCode()); + + $flattened = FlattenException::create(new GoneHttpException()); + $this->assertEquals('410', $flattened->getStatusCode()); + + $flattened = FlattenException::create(new LengthRequiredHttpException()); + $this->assertEquals('411', $flattened->getStatusCode()); + + $flattened = FlattenException::create(new PreconditionFailedHttpException()); + $this->assertEquals('412', $flattened->getStatusCode()); + + $flattened = FlattenException::create(new PreconditionRequiredHttpException()); + $this->assertEquals('428', $flattened->getStatusCode()); + + $flattened = FlattenException::create(new ServiceUnavailableHttpException()); + $this->assertEquals('503', $flattened->getStatusCode()); + + $flattened = FlattenException::create(new TooManyRequestsHttpException()); + $this->assertEquals('429', $flattened->getStatusCode()); + + $flattened = FlattenException::create(new UnsupportedMediaTypeHttpException()); + $this->assertEquals('415', $flattened->getStatusCode()); + + if (class_exists(SuspiciousOperationException::class)) { + $flattened = FlattenException::create(new SuspiciousOperationException()); + $this->assertEquals('400', $flattened->getStatusCode()); + } + } + + public function testHeadersForHttpException() + { + $flattened = FlattenException::create(new MethodNotAllowedHttpException(array('POST'))); + $this->assertEquals(array('Allow' => 'POST'), $flattened->getHeaders()); + + $flattened = FlattenException::create(new UnauthorizedHttpException('Basic realm="My Realm"')); + $this->assertEquals(array('WWW-Authenticate' => 'Basic realm="My Realm"'), $flattened->getHeaders()); + + $flattened = FlattenException::create(new ServiceUnavailableHttpException('Fri, 31 Dec 1999 23:59:59 GMT')); + $this->assertEquals(array('Retry-After' => 'Fri, 31 Dec 1999 23:59:59 GMT'), $flattened->getHeaders()); + + $flattened = FlattenException::create(new ServiceUnavailableHttpException(120)); + $this->assertEquals(array('Retry-After' => 120), $flattened->getHeaders()); + + $flattened = FlattenException::create(new TooManyRequestsHttpException('Fri, 31 Dec 1999 23:59:59 GMT')); + $this->assertEquals(array('Retry-After' => 'Fri, 31 Dec 1999 23:59:59 GMT'), $flattened->getHeaders()); + + $flattened = FlattenException::create(new TooManyRequestsHttpException(120)); + $this->assertEquals(array('Retry-After' => 120), $flattened->getHeaders()); + } + + /** + * @dataProvider flattenDataProvider + */ + public function testFlattenHttpException(\Exception $exception, $statusCode) + { + $flattened = FlattenException::create($exception); + $flattened2 = FlattenException::create($exception); + + $flattened->setPrevious($flattened2); + + $this->assertEquals($exception->getMessage(), $flattened->getMessage(), 'The message is copied from the original exception.'); + $this->assertEquals($exception->getCode(), $flattened->getCode(), 'The code is copied from the original exception.'); + $this->assertInstanceOf($flattened->getClass(), $exception, 'The class is set to the class of the original exception'); + } + + /** + * @dataProvider flattenDataProvider + */ + public function testPrevious(\Exception $exception, $statusCode) + { + $flattened = FlattenException::create($exception); + $flattened2 = FlattenException::create($exception); + + $flattened->setPrevious($flattened2); + + $this->assertSame($flattened2, $flattened->getPrevious()); + + $this->assertSame(array($flattened2), $flattened->getAllPrevious()); + } + + /** + * @requires PHP 7.0 + */ + public function testPreviousError() + { + $exception = new \Exception('test', 123, new \ParseError('Oh noes!', 42)); + + $flattened = FlattenException::create($exception)->getPrevious(); + + $this->assertEquals($flattened->getMessage(), 'Parse error: Oh noes!', 'The message is copied from the original exception.'); + $this->assertEquals($flattened->getCode(), 42, 'The code is copied from the original exception.'); + $this->assertEquals($flattened->getClass(), 'Symfony\Component\Debug\Exception\FatalThrowableError', 'The class is set to the class of the original exception'); + } + + /** + * @dataProvider flattenDataProvider + */ + public function testLine(\Exception $exception) + { + $flattened = FlattenException::create($exception); + $this->assertSame($exception->getLine(), $flattened->getLine()); + } + + /** + * @dataProvider flattenDataProvider + */ + public function testFile(\Exception $exception) + { + $flattened = FlattenException::create($exception); + $this->assertSame($exception->getFile(), $flattened->getFile()); + } + + /** + * @dataProvider flattenDataProvider + */ + public function testToArray(\Exception $exception, $statusCode) + { + $flattened = FlattenException::create($exception); + $flattened->setTrace(array(), 'foo.php', 123); + + $this->assertEquals(array( + array( + 'message' => 'test', + 'class' => 'Exception', + 'trace' => array(array( + 'namespace' => '', 'short_class' => '', 'class' => '', 'type' => '', 'function' => '', 'file' => 'foo.php', 'line' => 123, + 'args' => array(), + )), + ), + ), $flattened->toArray()); + } + + public function flattenDataProvider() + { + return array( + array(new \Exception('test', 123), 500), + ); + } + + public function testArguments() + { + $dh = opendir(__DIR__); + $fh = tmpfile(); + + $incomplete = unserialize('O:14:"BogusTestClass":0:{}'); + + $exception = $this->createException(array( + (object) array('foo' => 1), + new NotFoundHttpException(), + $incomplete, + $dh, + $fh, + function () {}, + array(1, 2), + array('foo' => 123), + null, + true, + false, + 0, + 0.0, + '0', + '', + INF, + NAN, + )); + + $flattened = FlattenException::create($exception); + $trace = $flattened->getTrace(); + $args = $trace[1]['args']; + $array = $args[0][1]; + + closedir($dh); + fclose($fh); + + $i = 0; + $this->assertSame(array('object', 'stdClass'), $array[$i++]); + $this->assertSame(array('object', 'Symfony\Component\HttpKernel\Exception\NotFoundHttpException'), $array[$i++]); + $this->assertSame(array('incomplete-object', 'BogusTestClass'), $array[$i++]); + $this->assertSame(array('resource', defined('HHVM_VERSION') ? 'Directory' : 'stream'), $array[$i++]); + $this->assertSame(array('resource', 'stream'), $array[$i++]); + + $args = $array[$i++]; + $this->assertSame($args[0], 'object'); + $this->assertTrue('Closure' === $args[1] || is_subclass_of($args[1], '\Closure'), 'Expect object class name to be Closure or a subclass of Closure.'); + + $this->assertSame(array('array', array(array('integer', 1), array('integer', 2))), $array[$i++]); + $this->assertSame(array('array', array('foo' => array('integer', 123))), $array[$i++]); + $this->assertSame(array('null', null), $array[$i++]); + $this->assertSame(array('boolean', true), $array[$i++]); + $this->assertSame(array('boolean', false), $array[$i++]); + $this->assertSame(array('integer', 0), $array[$i++]); + $this->assertSame(array('float', 0.0), $array[$i++]); + $this->assertSame(array('string', '0'), $array[$i++]); + $this->assertSame(array('string', ''), $array[$i++]); + $this->assertSame(array('float', INF), $array[$i++]); + + // assertEquals() does not like NAN values. + $this->assertEquals($array[$i][0], 'float'); + $this->assertTrue(is_nan($array[$i++][1])); + } + + public function testRecursionInArguments() + { + $a = array('foo', array(2, &$a)); + $exception = $this->createException($a); + + $flattened = FlattenException::create($exception); + $trace = $flattened->getTrace(); + $this->assertContains('*DEEP NESTED ARRAY*', serialize($trace)); + } + + public function testTooBigArray() + { + $a = array(); + for ($i = 0; $i < 20; ++$i) { + for ($j = 0; $j < 50; ++$j) { + for ($k = 0; $k < 10; ++$k) { + $a[$i][$j][$k] = 'value'; + } + } + } + $a[20] = 'value'; + $a[21] = 'value1'; + $exception = $this->createException($a); + + $flattened = FlattenException::create($exception); + $trace = $flattened->getTrace(); + + $this->assertSame($trace[1]['args'][0], array('array', array('array', '*SKIPPED over 10000 entries*'))); + + $serializeTrace = serialize($trace); + + $this->assertContains('*SKIPPED over 10000 entries*', $serializeTrace); + $this->assertNotContains('*value1*', $serializeTrace); + } + + private function createException($foo) + { + return new \Exception(); + } +} diff --git a/vendor/symfony/debug/Tests/ExceptionHandlerTest.php b/vendor/symfony/debug/Tests/ExceptionHandlerTest.php new file mode 100644 index 00000000..0285eff1 --- /dev/null +++ b/vendor/symfony/debug/Tests/ExceptionHandlerTest.php @@ -0,0 +1,133 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Debug\Tests; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Debug\ExceptionHandler; +use Symfony\Component\Debug\Exception\OutOfMemoryException; +use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; +use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException; + +require_once __DIR__.'/HeaderMock.php'; + +class ExceptionHandlerTest extends TestCase +{ + protected function setUp() + { + testHeader(); + } + + protected function tearDown() + { + testHeader(); + } + + public function testDebug() + { + $handler = new ExceptionHandler(false); + + ob_start(); + $handler->sendPhpResponse(new \RuntimeException('Foo')); + $response = ob_get_clean(); + + $this->assertContains('Whoops, looks like something went wrong.', $response); + $this->assertNotContains('<div class="trace trace-as-html">', $response); + + $handler = new ExceptionHandler(true); + + ob_start(); + $handler->sendPhpResponse(new \RuntimeException('Foo')); + $response = ob_get_clean(); + + $this->assertContains('Whoops, looks like something went wrong.', $response); + $this->assertContains('<div class="trace trace-as-html">', $response); + } + + public function testStatusCode() + { + $handler = new ExceptionHandler(false, 'iso8859-1'); + + ob_start(); + $handler->sendPhpResponse(new NotFoundHttpException('Foo')); + $response = ob_get_clean(); + + $this->assertContains('Sorry, the page you are looking for could not be found.', $response); + + $expectedHeaders = array( + array('HTTP/1.0 404', true, null), + array('Content-Type: text/html; charset=iso8859-1', true, null), + ); + + $this->assertSame($expectedHeaders, testHeader()); + } + + public function testHeaders() + { + $handler = new ExceptionHandler(false, 'iso8859-1'); + + ob_start(); + $handler->sendPhpResponse(new MethodNotAllowedHttpException(array('POST'))); + $response = ob_get_clean(); + + $expectedHeaders = array( + array('HTTP/1.0 405', true, null), + array('Allow: POST', false, null), + array('Content-Type: text/html; charset=iso8859-1', true, null), + ); + + $this->assertSame($expectedHeaders, testHeader()); + } + + public function testNestedExceptions() + { + $handler = new ExceptionHandler(true); + ob_start(); + $handler->sendPhpResponse(new \RuntimeException('Foo', 0, new \RuntimeException('Bar'))); + $response = ob_get_clean(); + + $this->assertStringMatchesFormat('%A<p class="break-long-words trace-message">Foo</p>%A<p class="break-long-words trace-message">Bar</p>%A', $response); + } + + public function testHandle() + { + $exception = new \Exception('foo'); + + $handler = $this->getMockBuilder('Symfony\Component\Debug\ExceptionHandler')->setMethods(array('sendPhpResponse'))->getMock(); + $handler + ->expects($this->exactly(2)) + ->method('sendPhpResponse'); + + $handler->handle($exception); + + $handler->setHandler(function ($e) use ($exception) { + $this->assertSame($exception, $e); + }); + + $handler->handle($exception); + } + + public function testHandleOutOfMemoryException() + { + $exception = new OutOfMemoryException('foo', 0, E_ERROR, __FILE__, __LINE__); + + $handler = $this->getMockBuilder('Symfony\Component\Debug\ExceptionHandler')->setMethods(array('sendPhpResponse'))->getMock(); + $handler + ->expects($this->once()) + ->method('sendPhpResponse'); + + $handler->setHandler(function ($e) { + $this->fail('OutOfMemoryException should bypass the handler'); + }); + + $handler->handle($exception); + } +} diff --git a/vendor/symfony/debug/Tests/FatalErrorHandler/ClassNotFoundFatalErrorHandlerTest.php b/vendor/symfony/debug/Tests/FatalErrorHandler/ClassNotFoundFatalErrorHandlerTest.php new file mode 100644 index 00000000..65c80fc1 --- /dev/null +++ b/vendor/symfony/debug/Tests/FatalErrorHandler/ClassNotFoundFatalErrorHandlerTest.php @@ -0,0 +1,176 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Debug\Tests\FatalErrorHandler; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Debug\Exception\FatalErrorException; +use Symfony\Component\Debug\FatalErrorHandler\ClassNotFoundFatalErrorHandler; +use Symfony\Component\Debug\DebugClassLoader; +use Composer\Autoload\ClassLoader as ComposerClassLoader; + +class ClassNotFoundFatalErrorHandlerTest extends TestCase +{ + public static function setUpBeforeClass() + { + foreach (spl_autoload_functions() as $function) { + if (!is_array($function)) { + continue; + } + + // get class loaders wrapped by DebugClassLoader + if ($function[0] instanceof DebugClassLoader) { + $function = $function[0]->getClassLoader(); + } + + if ($function[0] instanceof ComposerClassLoader) { + $function[0]->add('Symfony_Component_Debug_Tests_Fixtures', dirname(dirname(dirname(dirname(dirname(__DIR__)))))); + break; + } + } + } + + /** + * @dataProvider provideClassNotFoundData + */ + public function testHandleClassNotFound($error, $translatedMessage, $autoloader = null) + { + if ($autoloader) { + // Unregister all autoloaders to ensure the custom provided + // autoloader is the only one to be used during the test run. + $autoloaders = spl_autoload_functions(); + array_map('spl_autoload_unregister', $autoloaders); + spl_autoload_register($autoloader); + } + + $handler = new ClassNotFoundFatalErrorHandler(); + + $exception = $handler->handleError($error, new FatalErrorException('', 0, $error['type'], $error['file'], $error['line'])); + + if ($autoloader) { + spl_autoload_unregister($autoloader); + array_map('spl_autoload_register', $autoloaders); + } + + $this->assertInstanceOf('Symfony\Component\Debug\Exception\ClassNotFoundException', $exception); + $this->assertSame($translatedMessage, $exception->getMessage()); + $this->assertSame($error['type'], $exception->getSeverity()); + $this->assertSame($error['file'], $exception->getFile()); + $this->assertSame($error['line'], $exception->getLine()); + } + + public function provideClassNotFoundData() + { + $autoloader = new ComposerClassLoader(); + $autoloader->add('Symfony\Component\Debug\Exception\\', realpath(__DIR__.'/../../Exception')); + + $debugClassLoader = new DebugClassLoader(array($autoloader, 'loadClass')); + + return array( + array( + array( + 'type' => 1, + 'line' => 12, + 'file' => 'foo.php', + 'message' => 'Class \'WhizBangFactory\' not found', + ), + "Attempted to load class \"WhizBangFactory\" from the global namespace.\nDid you forget a \"use\" statement?", + ), + array( + array( + 'type' => 1, + 'line' => 12, + 'file' => 'foo.php', + 'message' => 'Class \'Foo\\Bar\\WhizBangFactory\' not found', + ), + "Attempted to load class \"WhizBangFactory\" from namespace \"Foo\\Bar\".\nDid you forget a \"use\" statement for another namespace?", + ), + array( + array( + 'type' => 1, + 'line' => 12, + 'file' => 'foo.php', + 'message' => 'Class \'UndefinedFunctionException\' not found', + ), + "Attempted to load class \"UndefinedFunctionException\" from the global namespace.\nDid you forget a \"use\" statement for \"Symfony\Component\Debug\Exception\UndefinedFunctionException\"?", + ), + array( + array( + 'type' => 1, + 'line' => 12, + 'file' => 'foo.php', + 'message' => 'Class \'PEARClass\' not found', + ), + "Attempted to load class \"PEARClass\" from the global namespace.\nDid you forget a \"use\" statement for \"Symfony_Component_Debug_Tests_Fixtures_PEARClass\"?", + ), + array( + array( + 'type' => 1, + 'line' => 12, + 'file' => 'foo.php', + 'message' => 'Class \'Foo\\Bar\\UndefinedFunctionException\' not found', + ), + "Attempted to load class \"UndefinedFunctionException\" from namespace \"Foo\Bar\".\nDid you forget a \"use\" statement for \"Symfony\Component\Debug\Exception\UndefinedFunctionException\"?", + ), + array( + array( + 'type' => 1, + 'line' => 12, + 'file' => 'foo.php', + 'message' => 'Class \'Foo\\Bar\\UndefinedFunctionException\' not found', + ), + "Attempted to load class \"UndefinedFunctionException\" from namespace \"Foo\Bar\".\nDid you forget a \"use\" statement for \"Symfony\Component\Debug\Exception\UndefinedFunctionException\"?", + array($autoloader, 'loadClass'), + ), + array( + array( + 'type' => 1, + 'line' => 12, + 'file' => 'foo.php', + 'message' => 'Class \'Foo\\Bar\\UndefinedFunctionException\' not found', + ), + "Attempted to load class \"UndefinedFunctionException\" from namespace \"Foo\Bar\".\nDid you forget a \"use\" statement for \"Symfony\Component\Debug\Exception\UndefinedFunctionException\"?", + array($debugClassLoader, 'loadClass'), + ), + array( + array( + 'type' => 1, + 'line' => 12, + 'file' => 'foo.php', + 'message' => 'Class \'Foo\\Bar\\UndefinedFunctionException\' not found', + ), + "Attempted to load class \"UndefinedFunctionException\" from namespace \"Foo\\Bar\".\nDid you forget a \"use\" statement for another namespace?", + function ($className) { /* do nothing here */ }, + ), + ); + } + + public function testCannotRedeclareClass() + { + if (!file_exists(__DIR__.'/../FIXTURES2/REQUIREDTWICE.PHP')) { + $this->markTestSkipped('Can only be run on case insensitive filesystems'); + } + + require_once __DIR__.'/../FIXTURES2/REQUIREDTWICE.PHP'; + + $error = array( + 'type' => 1, + 'line' => 12, + 'file' => 'foo.php', + 'message' => 'Class \'Foo\\Bar\\RequiredTwice\' not found', + ); + + $handler = new ClassNotFoundFatalErrorHandler(); + $exception = $handler->handleError($error, new FatalErrorException('', 0, $error['type'], $error['file'], $error['line'])); + + $this->assertInstanceOf('Symfony\Component\Debug\Exception\ClassNotFoundException', $exception); + } +} diff --git a/vendor/symfony/debug/Tests/FatalErrorHandler/UndefinedFunctionFatalErrorHandlerTest.php b/vendor/symfony/debug/Tests/FatalErrorHandler/UndefinedFunctionFatalErrorHandlerTest.php new file mode 100644 index 00000000..1dc21200 --- /dev/null +++ b/vendor/symfony/debug/Tests/FatalErrorHandler/UndefinedFunctionFatalErrorHandlerTest.php @@ -0,0 +1,81 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Debug\Tests\FatalErrorHandler; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Debug\Exception\FatalErrorException; +use Symfony\Component\Debug\FatalErrorHandler\UndefinedFunctionFatalErrorHandler; + +class UndefinedFunctionFatalErrorHandlerTest extends TestCase +{ + /** + * @dataProvider provideUndefinedFunctionData + */ + public function testUndefinedFunction($error, $translatedMessage) + { + $handler = new UndefinedFunctionFatalErrorHandler(); + $exception = $handler->handleError($error, new FatalErrorException('', 0, $error['type'], $error['file'], $error['line'])); + + $this->assertInstanceOf('Symfony\Component\Debug\Exception\UndefinedFunctionException', $exception); + // class names are case insensitive and PHP/HHVM do not return the same + $this->assertSame(strtolower($translatedMessage), strtolower($exception->getMessage())); + $this->assertSame($error['type'], $exception->getSeverity()); + $this->assertSame($error['file'], $exception->getFile()); + $this->assertSame($error['line'], $exception->getLine()); + } + + public function provideUndefinedFunctionData() + { + return array( + array( + array( + 'type' => 1, + 'line' => 12, + 'file' => 'foo.php', + 'message' => 'Call to undefined function test_namespaced_function()', + ), + "Attempted to call function \"test_namespaced_function\" from the global namespace.\nDid you mean to call \"\\symfony\\component\\debug\\tests\\fatalerrorhandler\\test_namespaced_function\"?", + ), + array( + array( + 'type' => 1, + 'line' => 12, + 'file' => 'foo.php', + 'message' => 'Call to undefined function Foo\\Bar\\Baz\\test_namespaced_function()', + ), + "Attempted to call function \"test_namespaced_function\" from namespace \"Foo\\Bar\\Baz\".\nDid you mean to call \"\\symfony\\component\\debug\\tests\\fatalerrorhandler\\test_namespaced_function\"?", + ), + array( + array( + 'type' => 1, + 'line' => 12, + 'file' => 'foo.php', + 'message' => 'Call to undefined function foo()', + ), + 'Attempted to call function "foo" from the global namespace.', + ), + array( + array( + 'type' => 1, + 'line' => 12, + 'file' => 'foo.php', + 'message' => 'Call to undefined function Foo\\Bar\\Baz\\foo()', + ), + 'Attempted to call function "foo" from namespace "Foo\Bar\Baz".', + ), + ); + } +} + +function test_namespaced_function() +{ +} diff --git a/vendor/symfony/debug/Tests/FatalErrorHandler/UndefinedMethodFatalErrorHandlerTest.php b/vendor/symfony/debug/Tests/FatalErrorHandler/UndefinedMethodFatalErrorHandlerTest.php new file mode 100644 index 00000000..739e5b2b --- /dev/null +++ b/vendor/symfony/debug/Tests/FatalErrorHandler/UndefinedMethodFatalErrorHandlerTest.php @@ -0,0 +1,76 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Debug\Tests\FatalErrorHandler; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Debug\Exception\FatalErrorException; +use Symfony\Component\Debug\FatalErrorHandler\UndefinedMethodFatalErrorHandler; + +class UndefinedMethodFatalErrorHandlerTest extends TestCase +{ + /** + * @dataProvider provideUndefinedMethodData + */ + public function testUndefinedMethod($error, $translatedMessage) + { + $handler = new UndefinedMethodFatalErrorHandler(); + $exception = $handler->handleError($error, new FatalErrorException('', 0, $error['type'], $error['file'], $error['line'])); + + $this->assertInstanceOf('Symfony\Component\Debug\Exception\UndefinedMethodException', $exception); + $this->assertSame($translatedMessage, $exception->getMessage()); + $this->assertSame($error['type'], $exception->getSeverity()); + $this->assertSame($error['file'], $exception->getFile()); + $this->assertSame($error['line'], $exception->getLine()); + } + + public function provideUndefinedMethodData() + { + return array( + array( + array( + 'type' => 1, + 'line' => 12, + 'file' => 'foo.php', + 'message' => 'Call to undefined method SplObjectStorage::what()', + ), + 'Attempted to call an undefined method named "what" of class "SplObjectStorage".', + ), + array( + array( + 'type' => 1, + 'line' => 12, + 'file' => 'foo.php', + 'message' => 'Call to undefined method SplObjectStorage::walid()', + ), + "Attempted to call an undefined method named \"walid\" of class \"SplObjectStorage\".\nDid you mean to call \"valid\"?", + ), + array( + array( + 'type' => 1, + 'line' => 12, + 'file' => 'foo.php', + 'message' => 'Call to undefined method SplObjectStorage::offsetFet()', + ), + "Attempted to call an undefined method named \"offsetFet\" of class \"SplObjectStorage\".\nDid you mean to call e.g. \"offsetGet\", \"offsetSet\" or \"offsetUnset\"?", + ), + array( + array( + 'type' => 1, + 'message' => 'Call to undefined method class@anonymous::test()', + 'file' => '/home/possum/work/symfony/test.php', + 'line' => 11, + ), + 'Attempted to call an undefined method named "test" of class "class@anonymous".', + ), + ); + } +} diff --git a/vendor/symfony/debug/Tests/Fixtures/AnnotatedClass.php b/vendor/symfony/debug/Tests/Fixtures/AnnotatedClass.php new file mode 100644 index 00000000..dff9517d --- /dev/null +++ b/vendor/symfony/debug/Tests/Fixtures/AnnotatedClass.php @@ -0,0 +1,13 @@ +<?php + +namespace Symfony\Component\Debug\Tests\Fixtures; + +class AnnotatedClass +{ + /** + * @deprecated since version 3.4. + */ + public function deprecatedMethod() + { + } +} diff --git a/vendor/symfony/debug/Tests/Fixtures/ClassAlias.php b/vendor/symfony/debug/Tests/Fixtures/ClassAlias.php new file mode 100644 index 00000000..9d6dbaa7 --- /dev/null +++ b/vendor/symfony/debug/Tests/Fixtures/ClassAlias.php @@ -0,0 +1,3 @@ +<?php + +class_alias('Symfony\Component\Debug\Tests\Fixtures\NotPSR0bis', 'Symfony\Component\Debug\Tests\Fixtures\ClassAlias'); diff --git a/vendor/symfony/debug/Tests/Fixtures/DeprecatedClass.php b/vendor/symfony/debug/Tests/Fixtures/DeprecatedClass.php new file mode 100644 index 00000000..51fde5af --- /dev/null +++ b/vendor/symfony/debug/Tests/Fixtures/DeprecatedClass.php @@ -0,0 +1,12 @@ +<?php + +namespace Symfony\Component\Debug\Tests\Fixtures; + +/** + * @deprecated but this is a test + * deprecation notice + * @foobar + */ +class DeprecatedClass +{ +} diff --git a/vendor/symfony/debug/Tests/Fixtures/DeprecatedInterface.php b/vendor/symfony/debug/Tests/Fixtures/DeprecatedInterface.php new file mode 100644 index 00000000..6bab62f9 --- /dev/null +++ b/vendor/symfony/debug/Tests/Fixtures/DeprecatedInterface.php @@ -0,0 +1,12 @@ +<?php + +namespace Symfony\Component\Debug\Tests\Fixtures; + +/** + * @deprecated but this is a test + * deprecation notice + * @foobar + */ +interface DeprecatedInterface +{ +} diff --git a/vendor/symfony/debug/Tests/Fixtures/ExtendedFinalMethod.php b/vendor/symfony/debug/Tests/Fixtures/ExtendedFinalMethod.php new file mode 100644 index 00000000..2bd337e5 --- /dev/null +++ b/vendor/symfony/debug/Tests/Fixtures/ExtendedFinalMethod.php @@ -0,0 +1,17 @@ +<?php + +namespace Symfony\Component\Debug\Tests\Fixtures; + +class ExtendedFinalMethod extends FinalMethod +{ + /** + * {@inheritdoc} + */ + public function finalMethod() + { + } + + public function anotherMethod() + { + } +} diff --git a/vendor/symfony/debug/Tests/Fixtures/FinalClass.php b/vendor/symfony/debug/Tests/Fixtures/FinalClass.php new file mode 100644 index 00000000..2cf26b19 --- /dev/null +++ b/vendor/symfony/debug/Tests/Fixtures/FinalClass.php @@ -0,0 +1,10 @@ +<?php + +namespace Symfony\Component\Debug\Tests\Fixtures; + +/** + * @final since version 3.3. + */ +class FinalClass +{ +} diff --git a/vendor/symfony/debug/Tests/Fixtures/FinalMethod.php b/vendor/symfony/debug/Tests/Fixtures/FinalMethod.php new file mode 100644 index 00000000..92ec4218 --- /dev/null +++ b/vendor/symfony/debug/Tests/Fixtures/FinalMethod.php @@ -0,0 +1,17 @@ +<?php + +namespace Symfony\Component\Debug\Tests\Fixtures; + +class FinalMethod +{ + /** + * @final since version 3.3. + */ + public function finalMethod() + { + } + + public function anotherMethod() + { + } +} diff --git a/vendor/symfony/debug/Tests/Fixtures/InternalClass.php b/vendor/symfony/debug/Tests/Fixtures/InternalClass.php new file mode 100644 index 00000000..119842c2 --- /dev/null +++ b/vendor/symfony/debug/Tests/Fixtures/InternalClass.php @@ -0,0 +1,15 @@ +<?php + +namespace Symfony\Component\Debug\Tests\Fixtures; + +/** + * @internal since version 3.4. + */ +class InternalClass +{ + use InternalTrait2; + + public function usedInInternalClass() + { + } +} diff --git a/vendor/symfony/debug/Tests/Fixtures/InternalInterface.php b/vendor/symfony/debug/Tests/Fixtures/InternalInterface.php new file mode 100644 index 00000000..dd79f501 --- /dev/null +++ b/vendor/symfony/debug/Tests/Fixtures/InternalInterface.php @@ -0,0 +1,10 @@ +<?php + +namespace Symfony\Component\Debug\Tests\Fixtures; + +/** + * @internal + */ +interface InternalInterface +{ +} diff --git a/vendor/symfony/debug/Tests/Fixtures/InternalTrait.php b/vendor/symfony/debug/Tests/Fixtures/InternalTrait.php new file mode 100644 index 00000000..7bb4635c --- /dev/null +++ b/vendor/symfony/debug/Tests/Fixtures/InternalTrait.php @@ -0,0 +1,10 @@ +<?php + +namespace Symfony\Component\Debug\Tests\Fixtures; + +/** + * @internal + */ +trait InternalTrait +{ +} diff --git a/vendor/symfony/debug/Tests/Fixtures/InternalTrait2.php b/vendor/symfony/debug/Tests/Fixtures/InternalTrait2.php new file mode 100644 index 00000000..05f18e83 --- /dev/null +++ b/vendor/symfony/debug/Tests/Fixtures/InternalTrait2.php @@ -0,0 +1,23 @@ +<?php + +namespace Symfony\Component\Debug\Tests\Fixtures; + +/** + * @internal + */ +trait InternalTrait2 +{ + /** + * @internal since version 3.4 + */ + public function internalMethod() + { + } + + /** + * @internal but should not trigger a deprecation + */ + public function usedInInternalClass() + { + } +} diff --git a/vendor/symfony/debug/Tests/Fixtures/NonDeprecatedInterface.php b/vendor/symfony/debug/Tests/Fixtures/NonDeprecatedInterface.php new file mode 100644 index 00000000..a4179a57 --- /dev/null +++ b/vendor/symfony/debug/Tests/Fixtures/NonDeprecatedInterface.php @@ -0,0 +1,7 @@ +<?php + +namespace Symfony\Component\Debug\Tests\Fixtures; + +interface NonDeprecatedInterface extends DeprecatedInterface +{ +} diff --git a/vendor/symfony/debug/Tests/Fixtures/PEARClass.php b/vendor/symfony/debug/Tests/Fixtures/PEARClass.php new file mode 100644 index 00000000..39f22818 --- /dev/null +++ b/vendor/symfony/debug/Tests/Fixtures/PEARClass.php @@ -0,0 +1,5 @@ +<?php + +class Symfony_Component_Debug_Tests_Fixtures_PEARClass +{ +} diff --git a/vendor/symfony/debug/Tests/Fixtures/Throwing.php b/vendor/symfony/debug/Tests/Fixtures/Throwing.php new file mode 100644 index 00000000..21e0aba1 --- /dev/null +++ b/vendor/symfony/debug/Tests/Fixtures/Throwing.php @@ -0,0 +1,3 @@ +<?php + +throw new \Exception('boo'); diff --git a/vendor/symfony/debug/Tests/Fixtures/ToStringThrower.php b/vendor/symfony/debug/Tests/Fixtures/ToStringThrower.php new file mode 100644 index 00000000..40a5fb7f --- /dev/null +++ b/vendor/symfony/debug/Tests/Fixtures/ToStringThrower.php @@ -0,0 +1,24 @@ +<?php + +namespace Symfony\Component\Debug\Tests\Fixtures; + +class ToStringThrower +{ + private $exception; + + public function __construct(\Exception $e) + { + $this->exception = $e; + } + + public function __toString() + { + try { + throw $this->exception; + } catch (\Exception $e) { + // Using user_error() here is on purpose so we do not forget + // that this alias also should work alongside with trigger_error(). + return user_error($e, E_USER_ERROR); + } + } +} diff --git a/vendor/symfony/debug/Tests/Fixtures/casemismatch.php b/vendor/symfony/debug/Tests/Fixtures/casemismatch.php new file mode 100644 index 00000000..691d660f --- /dev/null +++ b/vendor/symfony/debug/Tests/Fixtures/casemismatch.php @@ -0,0 +1,7 @@ +<?php + +namespace Symfony\Component\Debug\Tests\Fixtures; + +class CaseMismatch +{ +} diff --git a/vendor/symfony/debug/Tests/Fixtures/notPsr0Bis.php b/vendor/symfony/debug/Tests/Fixtures/notPsr0Bis.php new file mode 100644 index 00000000..4cf52671 --- /dev/null +++ b/vendor/symfony/debug/Tests/Fixtures/notPsr0Bis.php @@ -0,0 +1,7 @@ +<?php + +namespace Symfony\Component\Debug\Tests\Fixtures; + +class NotPSR0bis +{ +} diff --git a/vendor/symfony/debug/Tests/Fixtures/psr4/Psr4CaseMismatch.php b/vendor/symfony/debug/Tests/Fixtures/psr4/Psr4CaseMismatch.php new file mode 100644 index 00000000..ec48dd22 --- /dev/null +++ b/vendor/symfony/debug/Tests/Fixtures/psr4/Psr4CaseMismatch.php @@ -0,0 +1,7 @@ +<?php + +namespace Symfony\Component\Debug\Tests\Fixtures; + +class PSR4CaseMismatch +{ +} diff --git a/vendor/symfony/debug/Tests/Fixtures/reallyNotPsr0.php b/vendor/symfony/debug/Tests/Fixtures/reallyNotPsr0.php new file mode 100644 index 00000000..8554725a --- /dev/null +++ b/vendor/symfony/debug/Tests/Fixtures/reallyNotPsr0.php @@ -0,0 +1,7 @@ +<?php + +namespace Symfony\Component\Debug\Tests\Fixtures; + +class NotPSR0 +{ +} diff --git a/vendor/symfony/debug/Tests/Fixtures2/RequiredTwice.php b/vendor/symfony/debug/Tests/Fixtures2/RequiredTwice.php new file mode 100644 index 00000000..604bc37f --- /dev/null +++ b/vendor/symfony/debug/Tests/Fixtures2/RequiredTwice.php @@ -0,0 +1,7 @@ +<?php + +namespace Symfony\Component\Debug\Tests\Fixtures2; + +class RequiredTwice +{ +} diff --git a/vendor/symfony/debug/Tests/HeaderMock.php b/vendor/symfony/debug/Tests/HeaderMock.php new file mode 100644 index 00000000..65d0b588 --- /dev/null +++ b/vendor/symfony/debug/Tests/HeaderMock.php @@ -0,0 +1,38 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Debug; + +function headers_sent() +{ + return false; +} + +function header($str, $replace = true, $status = null) +{ + Tests\testHeader($str, $replace, $status); +} + +namespace Symfony\Component\Debug\Tests; + +function testHeader() +{ + static $headers = array(); + + if (!$h = func_get_args()) { + $h = $headers; + $headers = array(); + + return $h; + } + + $headers[] = func_get_args(); +} diff --git a/vendor/symfony/debug/Tests/MockExceptionHandler.php b/vendor/symfony/debug/Tests/MockExceptionHandler.php new file mode 100644 index 00000000..2d6ce564 --- /dev/null +++ b/vendor/symfony/debug/Tests/MockExceptionHandler.php @@ -0,0 +1,24 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Debug\Tests; + +use Symfony\Component\Debug\ExceptionHandler; + +class MockExceptionHandler extends ExceptionHandler +{ + public $e; + + public function handle(\Exception $e) + { + $this->e = $e; + } +} diff --git a/vendor/symfony/debug/Tests/phpt/exception_rethrown.phpt b/vendor/symfony/debug/Tests/phpt/exception_rethrown.phpt new file mode 100644 index 00000000..877e208f --- /dev/null +++ b/vendor/symfony/debug/Tests/phpt/exception_rethrown.phpt @@ -0,0 +1,36 @@ +--TEST-- +Test rethrowing in custom exception handler +--FILE-- +<?php + +namespace Symfony\Component\Debug; + +$vendor = __DIR__; +while (!file_exists($vendor.'/vendor')) { + $vendor = dirname($vendor); +} +require $vendor.'/vendor/autoload.php'; + +if (true) { + class TestLogger extends \Psr\Log\AbstractLogger + { + public function log($level, $message, array $context = array()) + { + echo $message, "\n"; + } + } +} + +set_exception_handler(function ($e) { echo 123; throw $e; }); +ErrorHandler::register()->setDefaultLogger(new TestLogger()); +ini_set('display_errors', 1); + +throw new \Exception('foo'); + +?> +--EXPECTF-- +Uncaught Exception: foo +123 +Fatal error: Uncaught %s:25 +Stack trace: +%a diff --git a/vendor/symfony/debug/Tests/phpt/fatal_with_nested_handlers.phpt b/vendor/symfony/debug/Tests/phpt/fatal_with_nested_handlers.phpt new file mode 100644 index 00000000..bd7b644d --- /dev/null +++ b/vendor/symfony/debug/Tests/phpt/fatal_with_nested_handlers.phpt @@ -0,0 +1,40 @@ +--TEST-- +Test catching fatal errors when handlers are nested +--FILE-- +<?php + +namespace Symfony\Component\Debug; + +$vendor = __DIR__; +while (!file_exists($vendor.'/vendor')) { + $vendor = dirname($vendor); +} +require $vendor.'/vendor/autoload.php'; + +Debug::enable(); +ini_set('display_errors', 0); + +$eHandler = set_error_handler('var_dump'); +$xHandler = set_exception_handler('var_dump'); + +var_dump(array( + $eHandler[0] === $xHandler[0] ? 'Error and exception handlers do match' : 'Error and exception handlers are different', +)); + +$eHandler[0]->setExceptionHandler('print_r'); + +if (true) { + class Broken implements \Serializable {}; +} + +?> +--EXPECTF-- +array(1) { + [0]=> + string(37) "Error and exception handlers do match" +} +object(Symfony\Component\Debug\Exception\FatalErrorException)#%d (%d) { + ["message":protected]=> + string(199) "Error: Class Symfony\Component\Debug\Broken contains 2 abstract methods and must therefore be declared abstract or implement the remaining methods (Serializable::serialize, Serializable::unserialize)" +%a +} diff --git a/vendor/symfony/debug/composer.json b/vendor/symfony/debug/composer.json new file mode 100644 index 00000000..f98a5d07 --- /dev/null +++ b/vendor/symfony/debug/composer.json @@ -0,0 +1,40 @@ +{ + "name": "symfony/debug", + "type": "library", + "description": "Symfony Debug Component", + "keywords": [], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": "^5.5.9|>=7.0.8", + "psr/log": "~1.0" + }, + "conflict": { + "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" + }, + "require-dev": { + "symfony/http-kernel": "~2.8|~3.0|~4.0" + }, + "autoload": { + "psr-4": { "Symfony\\Component\\Debug\\": "" }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + } +} diff --git a/vendor/symfony/debug/phpunit.xml.dist b/vendor/symfony/debug/phpunit.xml.dist new file mode 100644 index 00000000..12e58612 --- /dev/null +++ b/vendor/symfony/debug/phpunit.xml.dist @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd" + backupGlobals="false" + colors="true" + bootstrap="vendor/autoload.php" + failOnRisky="true" + failOnWarning="true" +> + <php> + <ini name="error_reporting" value="-1" /> + </php> + + <testsuites> + <testsuite name="Symfony Debug Component Test Suite"> + <directory>./Tests/</directory> + </testsuite> + <testsuite name="Symfony Debug Extension Test Suite"> + <directory suffix=".phpt">./Resources/ext/tests/</directory> + </testsuite> + </testsuites> + + <filter> + <whitelist> + <directory>./</directory> + <exclude> + <directory>./Tests</directory> + <directory>./vendor</directory> + </exclude> + </whitelist> + </filter> +</phpunit> diff --git a/vendor/symfony/event-dispatcher/CHANGELOG.md b/vendor/symfony/event-dispatcher/CHANGELOG.md index bb42ee19..c6aa5389 100644 --- a/vendor/symfony/event-dispatcher/CHANGELOG.md +++ b/vendor/symfony/event-dispatcher/CHANGELOG.md @@ -1,6 +1,25 @@ CHANGELOG ========= +3.4.0 +----- + + * Implementing `TraceableEventDispatcherInterface` without the `reset()` method has been deprecated. + +3.3.0 +----- + + * The ContainerAwareEventDispatcher class has been deprecated. Use EventDispatcher with closure factories instead. + +3.0.0 +----- + + * The method `getListenerPriority($eventName, $listener)` has been added to the + `EventDispatcherInterface`. + * The methods `Event::setDispatcher()`, `Event::getDispatcher()`, `Event::setName()` + and `Event::getName()` have been removed. + The event dispatcher and the event name are passed to the listener call. + 2.5.0 ----- diff --git a/vendor/symfony/event-dispatcher/ContainerAwareEventDispatcher.php b/vendor/symfony/event-dispatcher/ContainerAwareEventDispatcher.php index b92defe6..7a2b68be 100644 --- a/vendor/symfony/event-dispatcher/ContainerAwareEventDispatcher.php +++ b/vendor/symfony/event-dispatcher/ContainerAwareEventDispatcher.php @@ -20,38 +20,34 @@ use Symfony\Component\DependencyInjection\ContainerInterface; * @author Fabien Potencier <fabien@symfony.com> * @author Bernhard Schussek <bschussek@gmail.com> * @author Jordan Alliot <jordan.alliot@gmail.com> + * + * @deprecated since 3.3, to be removed in 4.0. Use EventDispatcher with closure factories instead. */ class ContainerAwareEventDispatcher extends EventDispatcher { - /** - * The container from where services are loaded. - * - * @var ContainerInterface - */ private $container; /** * The service IDs of the event listeners and subscribers. - * - * @var array */ private $listenerIds = array(); /** * The services registered as listeners. - * - * @var array */ private $listeners = array(); - /** - * Constructor. - * - * @param ContainerInterface $container A ContainerInterface instance - */ public function __construct(ContainerInterface $container) { $this->container = $container; + + $class = get_class($this); + if ($this instanceof \PHPUnit_Framework_MockObject_MockObject || $this instanceof \Prophecy\Doubler\DoubleInterface) { + $class = get_parent_class($class); + } + if (__CLASS__ !== $class) { + @trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use EventDispatcher with closure factories instead.', __CLASS__), E_USER_DEPRECATED); + } } /** @@ -68,6 +64,8 @@ class ContainerAwareEventDispatcher extends EventDispatcher */ public function addListenerService($eventName, $callback, $priority = 0) { + @trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use EventDispatcher with closure factories instead.', __CLASS__), E_USER_DEPRECATED); + if (!is_array($callback) || 2 !== count($callback)) { throw new \InvalidArgumentException('Expected an array("service", "method") argument'); } @@ -80,8 +78,7 @@ class ContainerAwareEventDispatcher extends EventDispatcher $this->lazyLoad($eventName); if (isset($this->listenerIds[$eventName])) { - foreach ($this->listenerIds[$eventName] as $i => $args) { - list($serviceId, $method, $priority) = $args; + foreach ($this->listenerIds[$eventName] as $i => list($serviceId, $method)) { $key = $serviceId.'.'.$method; if (isset($this->listeners[$eventName][$key]) && $listener === array($this->listeners[$eventName][$key], $method)) { unset($this->listeners[$eventName][$key]); @@ -105,7 +102,7 @@ class ContainerAwareEventDispatcher extends EventDispatcher public function hasListeners($eventName = null) { if (null === $eventName) { - return (bool) count($this->listenerIds) || (bool) count($this->listeners); + return $this->listenerIds || $this->listeners || parent::hasListeners(); } if (isset($this->listenerIds[$eventName])) { @@ -132,6 +129,16 @@ class ContainerAwareEventDispatcher extends EventDispatcher } /** + * {@inheritdoc} + */ + public function getListenerPriority($eventName, $listener) + { + $this->lazyLoad($eventName); + + return parent::getListenerPriority($eventName, $listener); + } + + /** * Adds a service as event subscriber. * * @param string $serviceId The service ID of the subscriber service @@ -139,6 +146,8 @@ class ContainerAwareEventDispatcher extends EventDispatcher */ public function addSubscriberService($serviceId, $class) { + @trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use EventDispatcher with closure factories instead.', __CLASS__), E_USER_DEPRECATED); + foreach ($class::getSubscribedEvents() as $eventName => $params) { if (is_string($params)) { $this->listenerIds[$eventName][] = array($serviceId, $params, 0); @@ -154,6 +163,8 @@ class ContainerAwareEventDispatcher extends EventDispatcher public function getContainer() { + @trigger_error('The '.__METHOD__.'() method is deprecated since version 3.3 as its class will be removed in 4.0. Inject the container or the services you need in your listeners/subscribers instead.', E_USER_DEPRECATED); + return $this->container; } @@ -168,14 +179,13 @@ class ContainerAwareEventDispatcher extends EventDispatcher protected function lazyLoad($eventName) { if (isset($this->listenerIds[$eventName])) { - foreach ($this->listenerIds[$eventName] as $args) { - list($serviceId, $method, $priority) = $args; + foreach ($this->listenerIds[$eventName] as list($serviceId, $method, $priority)) { $listener = $this->container->get($serviceId); $key = $serviceId.'.'.$method; if (!isset($this->listeners[$eventName][$key])) { $this->addListener($eventName, array($listener, $method), $priority); - } elseif ($listener !== $this->listeners[$eventName][$key]) { + } elseif ($this->listeners[$eventName][$key] !== $listener) { parent::removeListener($eventName, array($this->listeners[$eventName][$key], $method)); $this->addListener($eventName, array($listener, $method), $priority); } diff --git a/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php b/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php index 12e2b1c6..9b5c689a 100644 --- a/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php +++ b/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php @@ -33,13 +33,6 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface private $dispatcher; private $wrappedListeners; - /** - * Constructor. - * - * @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance - * @param Stopwatch $stopwatch A Stopwatch instance - * @param LoggerInterface $logger A LoggerInterface instance - */ public function __construct(EventDispatcherInterface $dispatcher, Stopwatch $stopwatch, LoggerInterface $logger = null) { $this->dispatcher = $dispatcher; @@ -102,6 +95,24 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface /** * {@inheritdoc} */ + public function getListenerPriority($eventName, $listener) + { + // we might have wrapped listeners for the event (if called while dispatching) + // in that case get the priority by wrapper + if (isset($this->wrappedListeners[$eventName])) { + foreach ($this->wrappedListeners[$eventName] as $index => $wrappedListener) { + if ($wrappedListener->getWrappedListener() === $listener) { + return $this->dispatcher->getListenerPriority($eventName, $wrappedListener); + } + } + } + + return $this->dispatcher->getListenerPriority($eventName, $listener); + } + + /** + * {@inheritdoc} + */ public function hasListeners($eventName = null) { return $this->dispatcher->hasListeners($eventName); @@ -145,8 +156,7 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface $called = array(); foreach ($this->called as $eventName => $listeners) { foreach ($listeners as $listener) { - $info = $this->getListenerInfo($listener->getWrappedListener(), $eventName); - $called[$eventName.'.'.$info['pretty']] = $info; + $called[$eventName.'.'.$listener->getPretty()] = $listener->getInfo($eventName); } } @@ -184,15 +194,24 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface } if (!$called) { - $info = $this->getListenerInfo($listener, $eventName); - $notCalled[$eventName.'.'.$info['pretty']] = $info; + if (!$listener instanceof WrappedListener) { + $listener = new WrappedListener($listener, null, $this->stopwatch, $this); + } + $notCalled[$eventName.'.'.$listener->getPretty()] = $listener->getInfo($eventName); } } } + uasort($notCalled, array($this, 'sortListenersByPriority')); + return $notCalled; } + public function reset() + { + $this->called = array(); + } + /** * Proxies all method calls to the original event dispatcher. * @@ -229,12 +248,11 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface private function preProcess($eventName) { foreach ($this->dispatcher->getListeners($eventName) as $listener) { - $this->dispatcher->removeListener($eventName, $listener); - $info = $this->getListenerInfo($listener, $eventName); - $name = isset($info['class']) ? $info['class'] : $info['type']; - $wrappedListener = new WrappedListener($listener, $name, $this->stopwatch, $this); + $priority = $this->getListenerPriority($eventName, $listener); + $wrappedListener = new WrappedListener($listener, null, $this->stopwatch, $this); $this->wrappedListeners[$eventName][] = $wrappedListener; - $this->dispatcher->addListener($eventName, $wrappedListener); + $this->dispatcher->removeListener($eventName, $listener); + $this->dispatcher->addListener($eventName, $wrappedListener, $priority); } } @@ -247,13 +265,17 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface continue; } // Unwrap listener + $priority = $this->getListenerPriority($eventName, $listener); $this->dispatcher->removeListener($eventName, $listener); - $this->dispatcher->addListener($eventName, $listener->getWrappedListener()); + $this->dispatcher->addListener($eventName, $listener->getWrappedListener(), $priority); + + if (null !== $this->logger) { + $context = array('event' => $eventName, 'listener' => $listener->getPretty()); + } - $info = $this->getListenerInfo($listener->getWrappedListener(), $eventName); if ($listener->wasCalled()) { if (null !== $this->logger) { - $this->logger->debug(sprintf('Notified event "%s" to listener "%s".', $eventName, $info['pretty'])); + $this->logger->debug('Notified event "{event}" to listener "{listener}".', $context); } if (!isset($this->called[$eventName])) { @@ -264,12 +286,12 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface } if (null !== $this->logger && $skipped) { - $this->logger->debug(sprintf('Listener "%s" was not called for event "%s".', $info['pretty'], $eventName)); + $this->logger->debug('Listener "{listener}" was not called for event "{event}".', $context); } if ($listener->stoppedPropagation()) { if (null !== $this->logger) { - $this->logger->debug(sprintf('Listener "%s" stopped propagation of the event "%s".', $info['pretty'], $eventName)); + $this->logger->debug('Listener "{listener}" stopped propagation of the event "{event}".', $context); } $skipped = true; @@ -277,63 +299,24 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface } } - /** - * Returns information about the listener. - * - * @param object $listener The listener - * @param string $eventName The event name - * - * @return array Information about the listener - */ - private function getListenerInfo($listener, $eventName) + private function sortListenersByPriority($a, $b) { - $info = array( - 'event' => $eventName, - ); - if ($listener instanceof \Closure) { - $info += array( - 'type' => 'Closure', - 'pretty' => 'closure', - ); - } elseif (is_string($listener)) { - try { - $r = new \ReflectionFunction($listener); - $file = $r->getFileName(); - $line = $r->getStartLine(); - } catch (\ReflectionException $e) { - $file = null; - $line = null; - } - $info += array( - 'type' => 'Function', - 'function' => $listener, - 'file' => $file, - 'line' => $line, - 'pretty' => $listener, - ); - } elseif (is_array($listener) || (is_object($listener) && is_callable($listener))) { - if (!is_array($listener)) { - $listener = array($listener, '__invoke'); - } - $class = is_object($listener[0]) ? get_class($listener[0]) : $listener[0]; - try { - $r = new \ReflectionMethod($class, $listener[1]); - $file = $r->getFileName(); - $line = $r->getStartLine(); - } catch (\ReflectionException $e) { - $file = null; - $line = null; - } - $info += array( - 'type' => 'Method', - 'class' => $class, - 'method' => $listener[1], - 'file' => $file, - 'line' => $line, - 'pretty' => $class.'::'.$listener[1], - ); + if (is_int($a['priority']) && !is_int($b['priority'])) { + return 1; + } + + if (!is_int($a['priority']) && is_int($b['priority'])) { + return -1; + } + + if ($a['priority'] === $b['priority']) { + return 0; + } + + if ($a['priority'] > $b['priority']) { + return -1; } - return $info; + return 1; } } diff --git a/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcherInterface.php b/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcherInterface.php index 5483e815..f0212753 100644 --- a/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcherInterface.php +++ b/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcherInterface.php @@ -15,6 +15,8 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * @author Fabien Potencier <fabien@symfony.com> + * + * @method reset() Resets the trace. */ interface TraceableEventDispatcherInterface extends EventDispatcherInterface { diff --git a/vendor/symfony/event-dispatcher/Debug/WrappedListener.php b/vendor/symfony/event-dispatcher/Debug/WrappedListener.php index e16627d6..f7b0273e 100644 --- a/vendor/symfony/event-dispatcher/Debug/WrappedListener.php +++ b/vendor/symfony/event-dispatcher/Debug/WrappedListener.php @@ -14,6 +14,7 @@ namespace Symfony\Component\EventDispatcher\Debug; use Symfony\Component\Stopwatch\Stopwatch; use Symfony\Component\EventDispatcher\Event; use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\VarDumper\Caster\ClassStub; /** * @author Fabien Potencier <fabien@symfony.com> @@ -26,6 +27,9 @@ class WrappedListener private $stoppedPropagation; private $stopwatch; private $dispatcher; + private $pretty; + private $stub; + private static $hasClassStub; public function __construct($listener, $name, Stopwatch $stopwatch, EventDispatcherInterface $dispatcher = null) { @@ -35,6 +39,26 @@ class WrappedListener $this->dispatcher = $dispatcher; $this->called = false; $this->stoppedPropagation = false; + + if (is_array($listener)) { + $this->name = is_object($listener[0]) ? get_class($listener[0]) : $listener[0]; + $this->pretty = $this->name.'::'.$listener[1]; + } elseif ($listener instanceof \Closure) { + $this->pretty = $this->name = 'closure'; + } elseif (is_string($listener)) { + $this->pretty = $this->name = $listener; + } else { + $this->name = get_class($listener); + $this->pretty = $this->name.'::__invoke'; + } + + if (null !== $name) { + $this->name = $name; + } + + if (null === self::$hasClassStub) { + self::$hasClassStub = class_exists(ClassStub::class); + } } public function getWrappedListener() @@ -52,6 +76,25 @@ class WrappedListener return $this->stoppedPropagation; } + public function getPretty() + { + return $this->pretty; + } + + public function getInfo($eventName) + { + if (null === $this->stub) { + $this->stub = self::$hasClassStub ? new ClassStub($this->pretty.'()', $this->listener) : $this->pretty.'()'; + } + + return array( + 'event' => $eventName, + 'priority' => null !== $this->dispatcher ? $this->dispatcher->getListenerPriority($eventName, $this->listener) : null, + 'pretty' => $this->pretty, + 'stub' => $this->stub, + ); + } + public function __invoke(Event $event, $eventName, EventDispatcherInterface $dispatcher) { $this->called = true; diff --git a/vendor/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php b/vendor/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php index ebfe435f..9f9c09c5 100644 --- a/vendor/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php +++ b/vendor/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php @@ -11,32 +11,27 @@ namespace Symfony\Component\EventDispatcher\DependencyInjection; +use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * Compiler pass to register tagged services for an event dispatcher. */ class RegisterListenersPass implements CompilerPassInterface { - /** - * @var string - */ protected $dispatcherService; - - /** - * @var string - */ protected $listenerTag; - - /** - * @var string - */ protected $subscriberTag; + private $hotPathEvents = array(); + private $hotPathTagName; + /** - * Constructor. - * * @param string $dispatcherService Service name of the event dispatcher in processed container * @param string $listenerTag Tag name used for listener * @param string $subscriberTag Tag name used for subscribers @@ -48,6 +43,14 @@ class RegisterListenersPass implements CompilerPassInterface $this->subscriberTag = $subscriberTag; } + public function setHotPathEvents(array $hotPathEvents, $tagName = 'container.hot_path') + { + $this->hotPathEvents = array_flip($hotPathEvents); + $this->hotPathTagName = $tagName; + + return $this; + } + public function process(ContainerBuilder $container) { if (!$container->hasDefinition($this->dispatcherService) && !$container->hasAlias($this->dispatcherService)) { @@ -56,21 +59,12 @@ class RegisterListenersPass implements CompilerPassInterface $definition = $container->findDefinition($this->dispatcherService); - foreach ($container->findTaggedServiceIds($this->listenerTag) as $id => $events) { - $def = $container->getDefinition($id); - if (!$def->isPublic()) { - throw new \InvalidArgumentException(sprintf('The service "%s" must be public as event listeners are lazy-loaded.', $id)); - } - - if ($def->isAbstract()) { - throw new \InvalidArgumentException(sprintf('The service "%s" must not be abstract as event listeners are lazy-loaded.', $id)); - } - + foreach ($container->findTaggedServiceIds($this->listenerTag, true) as $id => $events) { foreach ($events as $event) { $priority = isset($event['priority']) ? $event['priority'] : 0; if (!isset($event['event'])) { - throw new \InvalidArgumentException(sprintf('Service "%s" must define the "event" attribute on "%s" tags.', $id, $this->listenerTag)); + throw new InvalidArgumentException(sprintf('Service "%s" must define the "event" attribute on "%s" tags.', $id, $this->listenerTag)); } if (!isset($event['method'])) { @@ -81,29 +75,65 @@ class RegisterListenersPass implements CompilerPassInterface $event['method'] = preg_replace('/[^a-z0-9]/i', '', $event['method']); } - $definition->addMethodCall('addListenerService', array($event['event'], array($id, $event['method']), $priority)); + $definition->addMethodCall('addListener', array($event['event'], array(new ServiceClosureArgument(new Reference($id)), $event['method']), $priority)); + + if (isset($this->hotPathEvents[$event['event']])) { + $container->getDefinition($id)->addTag($this->hotPathTagName); + } } } - foreach ($container->findTaggedServiceIds($this->subscriberTag) as $id => $attributes) { - $def = $container->getDefinition($id); - if (!$def->isPublic()) { - throw new \InvalidArgumentException(sprintf('The service "%s" must be public as event subscribers are lazy-loaded.', $id)); - } + $extractingDispatcher = new ExtractingEventDispatcher(); - if ($def->isAbstract()) { - throw new \InvalidArgumentException(sprintf('The service "%s" must not be abstract as event subscribers are lazy-loaded.', $id)); - } + foreach ($container->findTaggedServiceIds($this->subscriberTag, true) as $id => $attributes) { + $def = $container->getDefinition($id); // We must assume that the class value has been correctly filled, even if the service is created by a factory $class = $container->getParameterBag()->resolveValue($def->getClass()); - $interface = 'Symfony\Component\EventDispatcher\EventSubscriberInterface'; + if (!is_subclass_of($class, $interface)) { - throw new \InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, $interface)); + if (!class_exists($class, false)) { + throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); + } + + throw new InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, $interface)); } + $container->addObjectResource($class); - $definition->addMethodCall('addSubscriberService', array($id, $class)); + ExtractingEventDispatcher::$subscriber = $class; + $extractingDispatcher->addSubscriber($extractingDispatcher); + foreach ($extractingDispatcher->listeners as $args) { + $args[1] = array(new ServiceClosureArgument(new Reference($id)), $args[1]); + $definition->addMethodCall('addListener', $args); + + if (isset($this->hotPathEvents[$args[0]])) { + $container->getDefinition($id)->addTag('container.hot_path'); + } + } + $extractingDispatcher->listeners = array(); } } } + +/** + * @internal + */ +class ExtractingEventDispatcher extends EventDispatcher implements EventSubscriberInterface +{ + public $listeners = array(); + + public static $subscriber; + + public function addListener($eventName, $listener, $priority = 0) + { + $this->listeners[] = array($eventName, $listener[1], $priority); + } + + public static function getSubscribedEvents() + { + $callback = array(self::$subscriber, 'getSubscribedEvents'); + + return $callback(); + } +} diff --git a/vendor/symfony/event-dispatcher/Event.php b/vendor/symfony/event-dispatcher/Event.php index 4a563495..9c56b2f5 100644 --- a/vendor/symfony/event-dispatcher/Event.php +++ b/vendor/symfony/event-dispatcher/Event.php @@ -33,21 +33,11 @@ class Event private $propagationStopped = false; /** - * @var EventDispatcher Dispatcher that dispatched this event - */ - private $dispatcher; - - /** - * @var string This event's name - */ - private $name; - - /** * Returns whether further event listeners should be triggered. * * @see Event::stopPropagation() * - * @return bool Whether propagation was already stopped for this event. + * @return bool Whether propagation was already stopped for this event */ public function isPropagationStopped() { @@ -65,56 +55,4 @@ class Event { $this->propagationStopped = true; } - - /** - * Stores the EventDispatcher that dispatches this Event. - * - * @param EventDispatcherInterface $dispatcher - * - * @deprecated since version 2.4, to be removed in 3.0. The event dispatcher is passed to the listener call. - */ - public function setDispatcher(EventDispatcherInterface $dispatcher) - { - $this->dispatcher = $dispatcher; - } - - /** - * Returns the EventDispatcher that dispatches this Event. - * - * @return EventDispatcherInterface - * - * @deprecated since version 2.4, to be removed in 3.0. The event dispatcher is passed to the listener call. - */ - public function getDispatcher() - { - @trigger_error('The '.__METHOD__.' method is deprecated since version 2.4 and will be removed in 3.0. The event dispatcher instance can be received in the listener call instead.', E_USER_DEPRECATED); - - return $this->dispatcher; - } - - /** - * Gets the event's name. - * - * @return string - * - * @deprecated since version 2.4, to be removed in 3.0. The event name is passed to the listener call. - */ - public function getName() - { - @trigger_error('The '.__METHOD__.' method is deprecated since version 2.4 and will be removed in 3.0. The event name can be received in the listener call instead.', E_USER_DEPRECATED); - - return $this->name; - } - - /** - * Sets the event's name property. - * - * @param string $name The event name. - * - * @deprecated since version 2.4, to be removed in 3.0. The event name is passed to the listener call. - */ - public function setName($name) - { - $this->name = $name; - } } diff --git a/vendor/symfony/event-dispatcher/EventDispatcher.php b/vendor/symfony/event-dispatcher/EventDispatcher.php index f1b63f70..bc79a958 100644 --- a/vendor/symfony/event-dispatcher/EventDispatcher.php +++ b/vendor/symfony/event-dispatcher/EventDispatcher.php @@ -24,6 +24,7 @@ namespace Symfony\Component\EventDispatcher; * @author Fabien Potencier <fabien@symfony.com> * @author Jordi Boggiano <j.boggiano@seld.be> * @author Jordan Alliot <jordan.alliot@gmail.com> + * @author Nicolas Grekas <p@tchwork.com> */ class EventDispatcher implements EventDispatcherInterface { @@ -39,9 +40,6 @@ class EventDispatcher implements EventDispatcherInterface $event = new Event(); } - $event->setDispatcher($this); - $event->setName($eventName); - if ($listeners = $this->getListeners($eventName)) { $this->doDispatch($listeners, $eventName, $event); } @@ -55,7 +53,7 @@ class EventDispatcher implements EventDispatcherInterface public function getListeners($eventName = null) { if (null !== $eventName) { - if (!isset($this->listeners[$eventName])) { + if (empty($this->listeners[$eventName])) { return array(); } @@ -78,9 +76,45 @@ class EventDispatcher implements EventDispatcherInterface /** * {@inheritdoc} */ + public function getListenerPriority($eventName, $listener) + { + if (empty($this->listeners[$eventName])) { + return; + } + + if (is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) { + $listener[0] = $listener[0](); + } + + foreach ($this->listeners[$eventName] as $priority => $listeners) { + foreach ($listeners as $k => $v) { + if ($v !== $listener && is_array($v) && isset($v[0]) && $v[0] instanceof \Closure) { + $v[0] = $v[0](); + $this->listeners[$eventName][$priority][$k] = $v; + } + if ($v === $listener) { + return $priority; + } + } + } + } + + /** + * {@inheritdoc} + */ public function hasListeners($eventName = null) { - return (bool) count($this->getListeners($eventName)); + if (null !== $eventName) { + return !empty($this->listeners[$eventName]); + } + + foreach ($this->listeners as $eventListeners) { + if ($eventListeners) { + return true; + } + } + + return false; } /** @@ -97,13 +131,30 @@ class EventDispatcher implements EventDispatcherInterface */ public function removeListener($eventName, $listener) { - if (!isset($this->listeners[$eventName])) { + if (empty($this->listeners[$eventName])) { return; } + if (is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) { + $listener[0] = $listener[0](); + } + foreach ($this->listeners[$eventName] as $priority => $listeners) { - if (false !== ($key = array_search($listener, $listeners, true))) { - unset($this->listeners[$eventName][$priority][$key], $this->sorted[$eventName]); + foreach ($listeners as $k => $v) { + if ($v !== $listener && is_array($v) && isset($v[0]) && $v[0] instanceof \Closure) { + $v[0] = $v[0](); + } + if ($v === $listener) { + unset($listeners[$k], $this->sorted[$eventName]); + } else { + $listeners[$k] = $v; + } + } + + if ($listeners) { + $this->listeners[$eventName][$priority] = $listeners; + } else { + unset($this->listeners[$eventName][$priority]); } } } @@ -148,9 +199,9 @@ class EventDispatcher implements EventDispatcherInterface * This method can be overridden to add functionality that is executed * for each listener. * - * @param callable[] $listeners The event listeners. - * @param string $eventName The name of the event to dispatch. - * @param Event $event The event object to pass to the event handlers/listeners. + * @param callable[] $listeners The event listeners + * @param string $eventName The name of the event to dispatch + * @param Event $event The event object to pass to the event handlers/listeners */ protected function doDispatch($listeners, $eventName, Event $event) { @@ -158,20 +209,28 @@ class EventDispatcher implements EventDispatcherInterface if ($event->isPropagationStopped()) { break; } - call_user_func($listener, $event, $eventName, $this); + \call_user_func($listener, $event, $eventName, $this); } } /** * Sorts the internal list of listeners for the given event by priority. * - * @param string $eventName The name of the event. + * @param string $eventName The name of the event */ private function sortListeners($eventName) { + krsort($this->listeners[$eventName]); $this->sorted[$eventName] = array(); - krsort($this->listeners[$eventName]); - $this->sorted[$eventName] = call_user_func_array('array_merge', $this->listeners[$eventName]); + foreach ($this->listeners[$eventName] as $priority => $listeners) { + foreach ($listeners as $k => $listener) { + if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) { + $listener[0] = $listener[0](); + $this->listeners[$eventName][$priority][$k] = $listener; + } + $this->sorted[$eventName][] = $listener; + } + } } } diff --git a/vendor/symfony/event-dispatcher/EventDispatcherInterface.php b/vendor/symfony/event-dispatcher/EventDispatcherInterface.php index a9bdd2c8..d3d0cb8a 100644 --- a/vendor/symfony/event-dispatcher/EventDispatcherInterface.php +++ b/vendor/symfony/event-dispatcher/EventDispatcherInterface.php @@ -26,8 +26,8 @@ interface EventDispatcherInterface * @param string $eventName The name of the event to dispatch. The name of * the event is the name of the method that is * invoked on listeners. - * @param Event $event The event to pass to the event handlers/listeners. - * If not supplied, an empty Event instance is created. + * @param Event $event The event to pass to the event handlers/listeners + * If not supplied, an empty Event instance is created * * @return Event */ @@ -48,8 +48,6 @@ interface EventDispatcherInterface * * The subscriber is asked for all the events he is * interested in and added as a listener for these events. - * - * @param EventSubscriberInterface $subscriber The subscriber. */ public function addSubscriber(EventSubscriberInterface $subscriber); @@ -61,11 +59,6 @@ interface EventDispatcherInterface */ public function removeListener($eventName, $listener); - /** - * Removes an event subscriber. - * - * @param EventSubscriberInterface $subscriber The subscriber - */ public function removeSubscriber(EventSubscriberInterface $subscriber); /** @@ -78,6 +71,18 @@ interface EventDispatcherInterface public function getListeners($eventName = null); /** + * Gets the listener priority for a specific event. + * + * Returns null if the event or the listener does not exist. + * + * @param string $eventName The name of the event + * @param callable $listener The listener + * + * @return int|null The event listener priority + */ + public function getListenerPriority($eventName, $listener); + + /** * Checks whether an event has any registered listeners. * * @param string $eventName The name of the event diff --git a/vendor/symfony/event-dispatcher/GenericEvent.php b/vendor/symfony/event-dispatcher/GenericEvent.php index 03cbcfe3..95c99408 100644 --- a/vendor/symfony/event-dispatcher/GenericEvent.php +++ b/vendor/symfony/event-dispatcher/GenericEvent.php @@ -20,25 +20,14 @@ namespace Symfony\Component\EventDispatcher; */ class GenericEvent extends Event implements \ArrayAccess, \IteratorAggregate { - /** - * Event subject. - * - * @var mixed usually object or callable - */ protected $subject; - - /** - * Array of arguments. - * - * @var array - */ protected $arguments; /** * Encapsulate an event with $subject and $args. * - * @param mixed $subject The subject of the event, usually an object. - * @param array $arguments Arguments to store in the event. + * @param mixed $subject The subject of the event, usually an object or a callable + * @param array $arguments Arguments to store in the event */ public function __construct($subject = null, array $arguments = array()) { @@ -49,7 +38,7 @@ class GenericEvent extends Event implements \ArrayAccess, \IteratorAggregate /** * Getter for subject property. * - * @return mixed $subject The observer subject. + * @return mixed $subject The observer subject */ public function getSubject() { @@ -59,11 +48,11 @@ class GenericEvent extends Event implements \ArrayAccess, \IteratorAggregate /** * Get argument by key. * - * @param string $key Key. + * @param string $key Key * - * @return mixed Contents of array key. + * @return mixed Contents of array key * - * @throws \InvalidArgumentException If key is not found. + * @throws \InvalidArgumentException if key is not found */ public function getArgument($key) { @@ -77,10 +66,10 @@ class GenericEvent extends Event implements \ArrayAccess, \IteratorAggregate /** * Add argument to event. * - * @param string $key Argument name. - * @param mixed $value Value. + * @param string $key Argument name + * @param mixed $value Value * - * @return GenericEvent + * @return $this */ public function setArgument($key, $value) { @@ -102,9 +91,9 @@ class GenericEvent extends Event implements \ArrayAccess, \IteratorAggregate /** * Set args property. * - * @param array $args Arguments. + * @param array $args Arguments * - * @return GenericEvent + * @return $this */ public function setArguments(array $args = array()) { @@ -116,7 +105,7 @@ class GenericEvent extends Event implements \ArrayAccess, \IteratorAggregate /** * Has argument. * - * @param string $key Key of arguments array. + * @param string $key Key of arguments array * * @return bool */ @@ -128,11 +117,11 @@ class GenericEvent extends Event implements \ArrayAccess, \IteratorAggregate /** * ArrayAccess for argument getter. * - * @param string $key Array key. + * @param string $key Array key * * @return mixed * - * @throws \InvalidArgumentException If key does not exist in $this->args. + * @throws \InvalidArgumentException if key does not exist in $this->args */ public function offsetGet($key) { @@ -142,8 +131,8 @@ class GenericEvent extends Event implements \ArrayAccess, \IteratorAggregate /** * ArrayAccess for argument setter. * - * @param string $key Array key to set. - * @param mixed $value Value. + * @param string $key Array key to set + * @param mixed $value Value */ public function offsetSet($key, $value) { @@ -153,7 +142,7 @@ class GenericEvent extends Event implements \ArrayAccess, \IteratorAggregate /** * ArrayAccess for unset argument. * - * @param string $key Array key. + * @param string $key Array key */ public function offsetUnset($key) { @@ -165,7 +154,7 @@ class GenericEvent extends Event implements \ArrayAccess, \IteratorAggregate /** * ArrayAccess has argument. * - * @param string $key Array key. + * @param string $key Array key * * @return bool */ diff --git a/vendor/symfony/event-dispatcher/ImmutableEventDispatcher.php b/vendor/symfony/event-dispatcher/ImmutableEventDispatcher.php index 7ef9ece7..b3cf56c5 100644 --- a/vendor/symfony/event-dispatcher/ImmutableEventDispatcher.php +++ b/vendor/symfony/event-dispatcher/ImmutableEventDispatcher.php @@ -18,18 +18,8 @@ namespace Symfony\Component\EventDispatcher; */ class ImmutableEventDispatcher implements EventDispatcherInterface { - /** - * The proxied dispatcher. - * - * @var EventDispatcherInterface - */ private $dispatcher; - /** - * Creates an unmodifiable proxy for an event dispatcher. - * - * @param EventDispatcherInterface $dispatcher The proxied event dispatcher. - */ public function __construct(EventDispatcherInterface $dispatcher) { $this->dispatcher = $dispatcher; @@ -86,6 +76,14 @@ class ImmutableEventDispatcher implements EventDispatcherInterface /** * {@inheritdoc} */ + public function getListenerPriority($eventName, $listener) + { + return $this->dispatcher->getListenerPriority($eventName, $listener); + } + + /** + * {@inheritdoc} + */ public function hasListeners($eventName = null) { return $this->dispatcher->hasListeners($eventName); diff --git a/vendor/symfony/event-dispatcher/LICENSE b/vendor/symfony/event-dispatcher/LICENSE index 12a74531..17d16a13 100644 --- a/vendor/symfony/event-dispatcher/LICENSE +++ b/vendor/symfony/event-dispatcher/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2016 Fabien Potencier +Copyright (c) 2004-2017 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/symfony/event-dispatcher/Tests/AbstractEventDispatcherTest.php b/vendor/symfony/event-dispatcher/Tests/AbstractEventDispatcherTest.php index 2e4c3fd9..9443f216 100644 --- a/vendor/symfony/event-dispatcher/Tests/AbstractEventDispatcherTest.php +++ b/vendor/symfony/event-dispatcher/Tests/AbstractEventDispatcherTest.php @@ -11,11 +11,12 @@ namespace Symfony\Component\EventDispatcher\Tests; +use PHPUnit\Framework\TestCase; use Symfony\Component\EventDispatcher\Event; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\EventDispatcher\EventSubscriberInterface; -abstract class AbstractEventDispatcherTest extends \PHPUnit_Framework_TestCase +abstract class AbstractEventDispatcherTest extends TestCase { /* Some pseudo events */ const preFoo = 'pre.foo'; @@ -55,6 +56,7 @@ abstract class AbstractEventDispatcherTest extends \PHPUnit_Framework_TestCase { $this->dispatcher->addListener('pre.foo', array($this->listener, 'preFoo')); $this->dispatcher->addListener('post.foo', array($this->listener, 'postFoo')); + $this->assertTrue($this->dispatcher->hasListeners()); $this->assertTrue($this->dispatcher->hasListeners(self::preFoo)); $this->assertTrue($this->dispatcher->hasListeners(self::postFoo)); $this->assertCount(1, $this->dispatcher->getListeners(self::preFoo)); @@ -108,6 +110,20 @@ abstract class AbstractEventDispatcherTest extends \PHPUnit_Framework_TestCase $this->assertSame($expected, $this->dispatcher->getListeners()); } + public function testGetListenerPriority() + { + $listener1 = new TestEventListener(); + $listener2 = new TestEventListener(); + + $this->dispatcher->addListener('pre.foo', $listener1, -10); + $this->dispatcher->addListener('pre.foo', $listener2); + + $this->assertSame(-10, $this->dispatcher->getListenerPriority('pre.foo', $listener1)); + $this->assertSame(0, $this->dispatcher->getListenerPriority('pre.foo', $listener2)); + $this->assertNull($this->dispatcher->getListenerPriority('pre.bar', $listener2)); + $this->assertNull($this->dispatcher->getListenerPriority('pre.foo', function () {})); + } + public function testDispatch() { $this->dispatcher->addListener('pre.foo', array($this->listener, 'preFoo')); @@ -122,16 +138,6 @@ abstract class AbstractEventDispatcherTest extends \PHPUnit_Framework_TestCase $this->assertSame($event, $return); } - /** - * @group legacy - */ - public function testLegacyDispatch() - { - $event = new Event(); - $return = $this->dispatcher->dispatch(self::preFoo, $event); - $this->assertEquals('pre.foo', $event->getName()); - } - public function testDispatchForClosure() { $invoked = 0; @@ -249,19 +255,6 @@ abstract class AbstractEventDispatcherTest extends \PHPUnit_Framework_TestCase $this->assertFalse($this->dispatcher->hasListeners(self::preFoo)); } - /** - * @group legacy - */ - public function testLegacyEventReceivesTheDispatcherInstance() - { - $dispatcher = null; - $this->dispatcher->addListener('test', function ($event) use (&$dispatcher) { - $dispatcher = $event->getDispatcher(); - }); - $this->dispatcher->dispatch('test'); - $this->assertSame($this->dispatcher, $dispatcher); - } - public function testEventReceivesTheDispatcherInstanceAsArgument() { $listener = new TestWithDispatcher(); @@ -310,6 +303,73 @@ abstract class AbstractEventDispatcherTest extends \PHPUnit_Framework_TestCase $this->assertFalse($this->dispatcher->hasListeners('foo')); $this->assertFalse($this->dispatcher->hasListeners()); } + + public function testHasListenersIsLazy() + { + $called = 0; + $listener = array(function () use (&$called) { ++$called; }, 'onFoo'); + $this->dispatcher->addListener('foo', $listener); + $this->assertTrue($this->dispatcher->hasListeners()); + $this->assertTrue($this->dispatcher->hasListeners('foo')); + $this->assertSame(0, $called); + } + + public function testDispatchLazyListener() + { + $called = 0; + $factory = function () use (&$called) { + ++$called; + + return new TestWithDispatcher(); + }; + $this->dispatcher->addListener('foo', array($factory, 'foo')); + $this->assertSame(0, $called); + $this->dispatcher->dispatch('foo', new Event()); + $this->dispatcher->dispatch('foo', new Event()); + $this->assertSame(1, $called); + } + + public function testRemoveFindsLazyListeners() + { + $test = new TestWithDispatcher(); + $factory = function () use ($test) { return $test; }; + + $this->dispatcher->addListener('foo', array($factory, 'foo')); + $this->assertTrue($this->dispatcher->hasListeners('foo')); + $this->dispatcher->removeListener('foo', array($test, 'foo')); + $this->assertFalse($this->dispatcher->hasListeners('foo')); + + $this->dispatcher->addListener('foo', array($test, 'foo')); + $this->assertTrue($this->dispatcher->hasListeners('foo')); + $this->dispatcher->removeListener('foo', array($factory, 'foo')); + $this->assertFalse($this->dispatcher->hasListeners('foo')); + } + + public function testPriorityFindsLazyListeners() + { + $test = new TestWithDispatcher(); + $factory = function () use ($test) { return $test; }; + + $this->dispatcher->addListener('foo', array($factory, 'foo'), 3); + $this->assertSame(3, $this->dispatcher->getListenerPriority('foo', array($test, 'foo'))); + $this->dispatcher->removeListener('foo', array($factory, 'foo')); + + $this->dispatcher->addListener('foo', array($test, 'foo'), 5); + $this->assertSame(5, $this->dispatcher->getListenerPriority('foo', array($factory, 'foo'))); + } + + public function testGetLazyListeners() + { + $test = new TestWithDispatcher(); + $factory = function () use ($test) { return $test; }; + + $this->dispatcher->addListener('foo', array($factory, 'foo'), 3); + $this->assertSame(array(array($test, 'foo')), $this->dispatcher->getListeners('foo')); + + $this->dispatcher->removeListener('foo', array($test, 'foo')); + $this->dispatcher->addListener('bar', array($factory, 'foo'), 3); + $this->assertSame(array('bar' => array(array($test, 'foo'))), $this->dispatcher->getListeners()); + } } class CallableClass diff --git a/vendor/symfony/event-dispatcher/Tests/ContainerAwareEventDispatcherTest.php b/vendor/symfony/event-dispatcher/Tests/ContainerAwareEventDispatcherTest.php index 0f3f5ba7..9d5eecc5 100644 --- a/vendor/symfony/event-dispatcher/Tests/ContainerAwareEventDispatcherTest.php +++ b/vendor/symfony/event-dispatcher/Tests/ContainerAwareEventDispatcherTest.php @@ -12,11 +12,13 @@ namespace Symfony\Component\EventDispatcher\Tests; use Symfony\Component\DependencyInjection\Container; -use Symfony\Component\DependencyInjection\Scope; use Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher; use Symfony\Component\EventDispatcher\Event; use Symfony\Component\EventDispatcher\EventSubscriberInterface; +/** + * @group legacy + */ class ContainerAwareEventDispatcherTest extends AbstractEventDispatcherTest { protected function createEventDispatcher() @@ -30,7 +32,7 @@ class ContainerAwareEventDispatcherTest extends AbstractEventDispatcherTest { $event = new Event(); - $service = $this->getMock('Symfony\Component\EventDispatcher\Tests\Service'); + $service = $this->getMockBuilder('Symfony\Component\EventDispatcher\Tests\Service')->getMock(); $service ->expects($this->once()) @@ -51,7 +53,7 @@ class ContainerAwareEventDispatcherTest extends AbstractEventDispatcherTest { $event = new Event(); - $service = $this->getMock('Symfony\Component\EventDispatcher\Tests\SubscriberService'); + $service = $this->getMockBuilder('Symfony\Component\EventDispatcher\Tests\SubscriberService')->getMock(); $service ->expects($this->once()) @@ -86,7 +88,7 @@ class ContainerAwareEventDispatcherTest extends AbstractEventDispatcherTest { $event = new Event(); - $service = $this->getMock('Symfony\Component\EventDispatcher\Tests\Service'); + $service = $this->getMockBuilder('Symfony\Component\EventDispatcher\Tests\Service')->getMock(); $service ->expects($this->once()) @@ -104,73 +106,11 @@ class ContainerAwareEventDispatcherTest extends AbstractEventDispatcherTest $dispatcher->dispatch('onEvent', $event); } - /** - * @expectedException \InvalidArgumentException - */ - public function testTriggerAListenerServiceOutOfScope() - { - $service = $this->getMock('Symfony\Component\EventDispatcher\Tests\Service'); - - $scope = new Scope('scope'); - $container = new Container(); - $container->addScope($scope); - $container->enterScope('scope'); - - $container->set('service.listener', $service, 'scope'); - - $dispatcher = new ContainerAwareEventDispatcher($container); - $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent')); - - $container->leaveScope('scope'); - $dispatcher->dispatch('onEvent'); - } - - public function testReEnteringAScope() - { - $event = new Event(); - - $service1 = $this->getMock('Symfony\Component\EventDispatcher\Tests\Service'); - - $service1 - ->expects($this->exactly(2)) - ->method('onEvent') - ->with($event) - ; - - $scope = new Scope('scope'); - $container = new Container(); - $container->addScope($scope); - $container->enterScope('scope'); - - $container->set('service.listener', $service1, 'scope'); - - $dispatcher = new ContainerAwareEventDispatcher($container); - $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent')); - $dispatcher->dispatch('onEvent', $event); - - $service2 = $this->getMock('Symfony\Component\EventDispatcher\Tests\Service'); - - $service2 - ->expects($this->once()) - ->method('onEvent') - ->with($event) - ; - - $container->enterScope('scope'); - $container->set('service.listener', $service2, 'scope'); - - $dispatcher->dispatch('onEvent', $event); - - $container->leaveScope('scope'); - - $dispatcher->dispatch('onEvent'); - } - public function testHasListenersOnLazyLoad() { $event = new Event(); - $service = $this->getMock('Symfony\Component\EventDispatcher\Tests\Service'); + $service = $this->getMockBuilder('Symfony\Component\EventDispatcher\Tests\Service')->getMock(); $container = new Container(); $container->set('service.listener', $service); @@ -178,9 +118,6 @@ class ContainerAwareEventDispatcherTest extends AbstractEventDispatcherTest $dispatcher = new ContainerAwareEventDispatcher($container); $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent')); - $event->setDispatcher($dispatcher); - $event->setName('onEvent'); - $service ->expects($this->once()) ->method('onEvent') @@ -196,7 +133,7 @@ class ContainerAwareEventDispatcherTest extends AbstractEventDispatcherTest public function testGetListenersOnLazyLoad() { - $service = $this->getMock('Symfony\Component\EventDispatcher\Tests\Service'); + $service = $this->getMockBuilder('Symfony\Component\EventDispatcher\Tests\Service')->getMock(); $container = new Container(); $container->set('service.listener', $service); @@ -206,14 +143,14 @@ class ContainerAwareEventDispatcherTest extends AbstractEventDispatcherTest $listeners = $dispatcher->getListeners(); - $this->assertTrue(isset($listeners['onEvent'])); + $this->assertArrayHasKey('onEvent', $listeners); $this->assertCount(1, $dispatcher->getListeners('onEvent')); } public function testRemoveAfterDispatch() { - $service = $this->getMock('Symfony\Component\EventDispatcher\Tests\Service'); + $service = $this->getMockBuilder('Symfony\Component\EventDispatcher\Tests\Service')->getMock(); $container = new Container(); $container->set('service.listener', $service); @@ -228,7 +165,7 @@ class ContainerAwareEventDispatcherTest extends AbstractEventDispatcherTest public function testRemoveBeforeDispatch() { - $service = $this->getMock('Symfony\Component\EventDispatcher\Tests\Service'); + $service = $this->getMockBuilder('Symfony\Component\EventDispatcher\Tests\Service')->getMock(); $container = new Container(); $container->set('service.listener', $service); diff --git a/vendor/symfony/event-dispatcher/Tests/Debug/TraceableEventDispatcherTest.php b/vendor/symfony/event-dispatcher/Tests/Debug/TraceableEventDispatcherTest.php index 4aa6226e..53a3421a 100644 --- a/vendor/symfony/event-dispatcher/Tests/Debug/TraceableEventDispatcherTest.php +++ b/vendor/symfony/event-dispatcher/Tests/Debug/TraceableEventDispatcherTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\EventDispatcher\Tests\Debug; +use PHPUnit\Framework\TestCase; use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; @@ -18,14 +19,14 @@ use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\EventDispatcher\Event; use Symfony\Component\Stopwatch\Stopwatch; -class TraceableEventDispatcherTest extends \PHPUnit_Framework_TestCase +class TraceableEventDispatcherTest extends TestCase { public function testAddRemoveListener() { $dispatcher = new EventDispatcher(); $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch()); - $tdispatcher->addListener('foo', $listener = function () {; }); + $tdispatcher->addListener('foo', $listener = function () {}); $listeners = $dispatcher->getListeners('foo'); $this->assertCount(1, $listeners); $this->assertSame($listener, $listeners[0]); @@ -39,7 +40,7 @@ class TraceableEventDispatcherTest extends \PHPUnit_Framework_TestCase $dispatcher = new EventDispatcher(); $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch()); - $tdispatcher->addListener('foo', $listener = function () {; }); + $tdispatcher->addListener('foo', $listener = function () {}); $this->assertSame($dispatcher->getListeners('foo'), $tdispatcher->getListeners('foo')); } @@ -51,11 +52,42 @@ class TraceableEventDispatcherTest extends \PHPUnit_Framework_TestCase $this->assertFalse($dispatcher->hasListeners('foo')); $this->assertFalse($tdispatcher->hasListeners('foo')); - $tdispatcher->addListener('foo', $listener = function () {; }); + $tdispatcher->addListener('foo', $listener = function () {}); $this->assertTrue($dispatcher->hasListeners('foo')); $this->assertTrue($tdispatcher->hasListeners('foo')); } + public function testGetListenerPriority() + { + $dispatcher = new EventDispatcher(); + $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch()); + + $tdispatcher->addListener('foo', function () {}, 123); + + $listeners = $dispatcher->getListeners('foo'); + $this->assertSame(123, $tdispatcher->getListenerPriority('foo', $listeners[0])); + + // Verify that priority is preserved when listener is removed and re-added + // in preProcess() and postProcess(). + $tdispatcher->dispatch('foo', new Event()); + $listeners = $dispatcher->getListeners('foo'); + $this->assertSame(123, $tdispatcher->getListenerPriority('foo', $listeners[0])); + } + + public function testGetListenerPriorityWhileDispatching() + { + $tdispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch()); + $priorityWhileDispatching = null; + + $listener = function () use ($tdispatcher, &$priorityWhileDispatching, &$listener) { + $priorityWhileDispatching = $tdispatcher->getListenerPriority('bar', $listener); + }; + + $tdispatcher->addListener('bar', $listener, 5); + $tdispatcher->dispatch('bar'); + $this->assertSame(5, $priorityWhileDispatching); + } + public function testAddRemoveSubscriber() { $dispatcher = new EventDispatcher(); @@ -74,19 +106,39 @@ class TraceableEventDispatcherTest extends \PHPUnit_Framework_TestCase public function testGetCalledListeners() { - $dispatcher = new EventDispatcher(); - $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch()); - $tdispatcher->addListener('foo', $listener = function () {; }); + $tdispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch()); + $tdispatcher->addListener('foo', function () {}, 5); + $listeners = $tdispatcher->getNotCalledListeners(); + $this->assertArrayHasKey('stub', $listeners['foo.closure']); + unset($listeners['foo.closure']['stub']); $this->assertEquals(array(), $tdispatcher->getCalledListeners()); - $this->assertEquals(array('foo.closure' => array('event' => 'foo', 'type' => 'Closure', 'pretty' => 'closure')), $tdispatcher->getNotCalledListeners()); + $this->assertEquals(array('foo.closure' => array('event' => 'foo', 'pretty' => 'closure', 'priority' => 5)), $listeners); $tdispatcher->dispatch('foo'); - $this->assertEquals(array('foo.closure' => array('event' => 'foo', 'type' => 'Closure', 'pretty' => 'closure')), $tdispatcher->getCalledListeners()); + $listeners = $tdispatcher->getCalledListeners(); + $this->assertArrayHasKey('stub', $listeners['foo.closure']); + unset($listeners['foo.closure']['stub']); + $this->assertEquals(array('foo.closure' => array('event' => 'foo', 'pretty' => 'closure', 'priority' => 5)), $listeners); $this->assertEquals(array(), $tdispatcher->getNotCalledListeners()); } + public function testClearCalledListeners() + { + $tdispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch()); + $tdispatcher->addListener('foo', function () {}, 5); + + $tdispatcher->dispatch('foo'); + $tdispatcher->reset(); + + $listeners = $tdispatcher->getNotCalledListeners(); + $this->assertArrayHasKey('stub', $listeners['foo.closure']); + unset($listeners['foo.closure']['stub']); + $this->assertEquals(array(), $tdispatcher->getCalledListeners()); + $this->assertEquals(array('foo.closure' => array('event' => 'foo', 'pretty' => 'closure', 'priority' => 5)), $listeners); + } + public function testGetCalledListenersNested() { $tdispatcher = null; @@ -103,31 +155,31 @@ class TraceableEventDispatcherTest extends \PHPUnit_Framework_TestCase public function testLogger() { - $logger = $this->getMock('Psr\Log\LoggerInterface'); + $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); $dispatcher = new EventDispatcher(); $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch(), $logger); - $tdispatcher->addListener('foo', $listener1 = function () {; }); - $tdispatcher->addListener('foo', $listener2 = function () {; }); + $tdispatcher->addListener('foo', $listener1 = function () {}); + $tdispatcher->addListener('foo', $listener2 = function () {}); - $logger->expects($this->at(0))->method('debug')->with('Notified event "foo" to listener "closure".'); - $logger->expects($this->at(1))->method('debug')->with('Notified event "foo" to listener "closure".'); + $logger->expects($this->at(0))->method('debug')->with('Notified event "{event}" to listener "{listener}".', array('event' => 'foo', 'listener' => 'closure')); + $logger->expects($this->at(1))->method('debug')->with('Notified event "{event}" to listener "{listener}".', array('event' => 'foo', 'listener' => 'closure')); $tdispatcher->dispatch('foo'); } public function testLoggerWithStoppedEvent() { - $logger = $this->getMock('Psr\Log\LoggerInterface'); + $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); $dispatcher = new EventDispatcher(); $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch(), $logger); $tdispatcher->addListener('foo', $listener1 = function (Event $event) { $event->stopPropagation(); }); - $tdispatcher->addListener('foo', $listener2 = function () {; }); + $tdispatcher->addListener('foo', $listener2 = function () {}); - $logger->expects($this->at(0))->method('debug')->with('Notified event "foo" to listener "closure".'); - $logger->expects($this->at(1))->method('debug')->with('Listener "closure" stopped propagation of the event "foo".'); - $logger->expects($this->at(2))->method('debug')->with('Listener "closure" was not called for event "foo".'); + $logger->expects($this->at(0))->method('debug')->with('Notified event "{event}" to listener "{listener}".', array('event' => 'foo', 'listener' => 'closure')); + $logger->expects($this->at(1))->method('debug')->with('Listener "{listener}" stopped propagation of the event "{event}".', array('event' => 'foo', 'listener' => 'closure')); + $logger->expects($this->at(2))->method('debug')->with('Listener "{listener}" was not called for event "{event}".', array('event' => 'foo', 'listener' => 'closure')); $tdispatcher->dispatch('foo'); } @@ -138,26 +190,32 @@ class TraceableEventDispatcherTest extends \PHPUnit_Framework_TestCase $dispatcher = new EventDispatcher(); $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch()); - $tdispatcher->addListener('foo', $listener1 = function () use (&$called) { $called[] = 'foo1'; }); - $tdispatcher->addListener('foo', $listener2 = function () use (&$called) { $called[] = 'foo2'; }); + $tdispatcher->addListener('foo', function () use (&$called) { $called[] = 'foo1'; }, 10); + $tdispatcher->addListener('foo', function () use (&$called) { $called[] = 'foo2'; }, 20); $tdispatcher->dispatch('foo'); - $this->assertEquals(array('foo1', 'foo2'), $called); + $this->assertSame(array('foo2', 'foo1'), $called); } public function testDispatchNested() { $dispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch()); $loop = 1; + $dispatchedEvents = 0; $dispatcher->addListener('foo', $listener1 = function () use ($dispatcher, &$loop) { ++$loop; if (2 == $loop) { $dispatcher->dispatch('foo'); } }); + $dispatcher->addListener('foo', function () use (&$dispatchedEvents) { + ++$dispatchedEvents; + }); $dispatcher->dispatch('foo'); + + $this->assertSame(2, $dispatchedEvents); } public function testDispatchReusedEventNested() diff --git a/vendor/symfony/event-dispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php b/vendor/symfony/event-dispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php index 0fdd6372..dbb1aa5c 100644 --- a/vendor/symfony/event-dispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php +++ b/vendor/symfony/event-dispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php @@ -11,10 +11,13 @@ namespace Symfony\Component\EventDispatcher\Tests\DependencyInjection; +use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass; -class RegisterListenersPassTest extends \PHPUnit_Framework_TestCase +class RegisterListenersPassTest extends TestCase { /** * Tests that event subscribers not implementing EventSubscriberInterface @@ -29,18 +32,12 @@ class RegisterListenersPassTest extends \PHPUnit_Framework_TestCase 'my_event_subscriber' => array(0 => array()), ); - $definition = $this->getMock('Symfony\Component\DependencyInjection\Definition'); - $definition->expects($this->atLeastOnce()) - ->method('isPublic') - ->will($this->returnValue(true)); + $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); $definition->expects($this->atLeastOnce()) ->method('getClass') ->will($this->returnValue('stdClass')); - $builder = $this->getMock( - 'Symfony\Component\DependencyInjection\ContainerBuilder', - array('hasDefinition', 'findTaggedServiceIds', 'getDefinition') - ); + $builder = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'getDefinition'))->getMock(); $builder->expects($this->any()) ->method('hasDefinition') ->will($this->returnValue(true)); @@ -64,18 +61,12 @@ class RegisterListenersPassTest extends \PHPUnit_Framework_TestCase 'my_event_subscriber' => array(0 => array()), ); - $definition = $this->getMock('Symfony\Component\DependencyInjection\Definition'); - $definition->expects($this->atLeastOnce()) - ->method('isPublic') - ->will($this->returnValue(true)); + $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); $definition->expects($this->atLeastOnce()) ->method('getClass') ->will($this->returnValue('Symfony\Component\EventDispatcher\Tests\DependencyInjection\SubscriberService')); - $builder = $this->getMock( - 'Symfony\Component\DependencyInjection\ContainerBuilder', - array('hasDefinition', 'findTaggedServiceIds', 'getDefinition', 'findDefinition') - ); + $builder = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'getDefinition', 'findDefinition'))->getMock(); $builder->expects($this->any()) ->method('hasDefinition') ->will($this->returnValue(true)); @@ -99,35 +90,7 @@ class RegisterListenersPassTest extends \PHPUnit_Framework_TestCase /** * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The service "foo" must be public as event listeners are lazy-loaded. - */ - public function testPrivateEventListener() - { - $container = new ContainerBuilder(); - $container->register('foo', 'stdClass')->setPublic(false)->addTag('kernel.event_listener', array()); - $container->register('event_dispatcher', 'stdClass'); - - $registerListenersPass = new RegisterListenersPass(); - $registerListenersPass->process($container); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The service "foo" must be public as event subscribers are lazy-loaded. - */ - public function testPrivateEventSubscriber() - { - $container = new ContainerBuilder(); - $container->register('foo', 'stdClass')->setPublic(false)->addTag('kernel.event_subscriber', array()); - $container->register('event_dispatcher', 'stdClass'); - - $registerListenersPass = new RegisterListenersPass(); - $registerListenersPass->process($container); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The service "foo" must not be abstract as event listeners are lazy-loaded. + * @expectedExceptionMessage The service "foo" tagged "kernel.event_listener" must not be abstract. */ public function testAbstractEventListener() { @@ -141,7 +104,7 @@ class RegisterListenersPassTest extends \PHPUnit_Framework_TestCase /** * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The service "foo" must not be abstract as event subscribers are lazy-loaded. + * @expectedExceptionMessage The service "foo" tagged "kernel.event_subscriber" must not be abstract. */ public function testAbstractEventSubscriber() { @@ -165,16 +128,29 @@ class RegisterListenersPassTest extends \PHPUnit_Framework_TestCase $registerListenersPass->process($container); $definition = $container->getDefinition('event_dispatcher'); - $expected_calls = array( + $expectedCalls = array( array( - 'addSubscriberService', + 'addListener', array( - 'foo', - 'Symfony\Component\EventDispatcher\Tests\DependencyInjection\SubscriberService', + 'event', + array(new ServiceClosureArgument(new Reference('foo')), 'onEvent'), + 0, ), ), ); - $this->assertSame($expected_calls, $definition->getMethodCalls()); + $this->assertEquals($expectedCalls, $definition->getMethodCalls()); + } + + public function testHotPathEvents() + { + $container = new ContainerBuilder(); + + $container->register('foo', SubscriberService::class)->addTag('kernel.event_subscriber', array()); + $container->register('event_dispatcher', 'stdClass'); + + (new RegisterListenersPass())->setHotPathEvents(array('event'))->process($container); + + $this->assertTrue($container->getDefinition('foo')->hasTag('container.hot_path')); } /** @@ -196,5 +172,8 @@ class SubscriberService implements \Symfony\Component\EventDispatcher\EventSubsc { public static function getSubscribedEvents() { + return array( + 'event' => 'onEvent', + ); } } diff --git a/vendor/symfony/event-dispatcher/Tests/EventTest.php b/vendor/symfony/event-dispatcher/Tests/EventTest.php index 9a822670..5be2ea09 100644 --- a/vendor/symfony/event-dispatcher/Tests/EventTest.php +++ b/vendor/symfony/event-dispatcher/Tests/EventTest.php @@ -11,13 +11,13 @@ namespace Symfony\Component\EventDispatcher\Tests; +use PHPUnit\Framework\TestCase; use Symfony\Component\EventDispatcher\Event; -use Symfony\Component\EventDispatcher\EventDispatcher; /** * Test class for Event. */ -class EventTest extends \PHPUnit_Framework_TestCase +class EventTest extends TestCase { /** * @var \Symfony\Component\EventDispatcher\Event @@ -25,18 +25,12 @@ class EventTest extends \PHPUnit_Framework_TestCase protected $event; /** - * @var \Symfony\Component\EventDispatcher\EventDispatcher - */ - protected $dispatcher; - - /** * Sets up the fixture, for example, opens a network connection. * This method is called before a test is executed. */ protected function setUp() { $this->event = new Event(); - $this->dispatcher = new EventDispatcher(); } /** @@ -46,7 +40,6 @@ class EventTest extends \PHPUnit_Framework_TestCase protected function tearDown() { $this->event = null; - $this->dispatcher = null; } public function testIsPropagationStopped() @@ -59,38 +52,4 @@ class EventTest extends \PHPUnit_Framework_TestCase $this->event->stopPropagation(); $this->assertTrue($this->event->isPropagationStopped()); } - - /** - * @group legacy - */ - public function testLegacySetDispatcher() - { - $this->event->setDispatcher($this->dispatcher); - $this->assertSame($this->dispatcher, $this->event->getDispatcher()); - } - - /** - * @group legacy - */ - public function testLegacyGetDispatcher() - { - $this->assertNull($this->event->getDispatcher()); - } - - /** - * @group legacy - */ - public function testLegacyGetName() - { - $this->assertNull($this->event->getName()); - } - - /** - * @group legacy - */ - public function testLegacySetName() - { - $this->event->setName('foo'); - $this->assertEquals('foo', $this->event->getName()); - } } diff --git a/vendor/symfony/event-dispatcher/Tests/GenericEventTest.php b/vendor/symfony/event-dispatcher/Tests/GenericEventTest.php index aebd82da..9cf68c98 100644 --- a/vendor/symfony/event-dispatcher/Tests/GenericEventTest.php +++ b/vendor/symfony/event-dispatcher/Tests/GenericEventTest.php @@ -11,12 +11,13 @@ namespace Symfony\Component\EventDispatcher\Tests; +use PHPUnit\Framework\TestCase; use Symfony\Component\EventDispatcher\GenericEvent; /** * Test class for Event. */ -class GenericEventTest extends \PHPUnit_Framework_TestCase +class GenericEventTest extends TestCase { /** * @var GenericEvent @@ -95,7 +96,7 @@ class GenericEventTest extends \PHPUnit_Framework_TestCase $this->assertEquals('Event', $this->event['name']); // test getting invalid arg - $this->setExpectedException('InvalidArgumentException'); + $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('InvalidArgumentException'); $this->assertFalse($this->event['nameNotExist']); } @@ -113,8 +114,8 @@ class GenericEventTest extends \PHPUnit_Framework_TestCase public function testOffsetIsset() { - $this->assertTrue(isset($this->event['name'])); - $this->assertFalse(isset($this->event['nameNotExist'])); + $this->assertArrayHasKey('name', $this->event); + $this->assertArrayNotHasKey('nameNotExist', $this->event); } public function testHasArgument() diff --git a/vendor/symfony/event-dispatcher/Tests/ImmutableEventDispatcherTest.php b/vendor/symfony/event-dispatcher/Tests/ImmutableEventDispatcherTest.php index 80a7e43b..04f2861e 100644 --- a/vendor/symfony/event-dispatcher/Tests/ImmutableEventDispatcherTest.php +++ b/vendor/symfony/event-dispatcher/Tests/ImmutableEventDispatcherTest.php @@ -11,13 +11,14 @@ namespace Symfony\Component\EventDispatcher\Tests; +use PHPUnit\Framework\TestCase; use Symfony\Component\EventDispatcher\Event; use Symfony\Component\EventDispatcher\ImmutableEventDispatcher; /** * @author Bernhard Schussek <bschussek@gmail.com> */ -class ImmutableEventDispatcherTest extends \PHPUnit_Framework_TestCase +class ImmutableEventDispatcherTest extends TestCase { /** * @var \PHPUnit_Framework_MockObject_MockObject @@ -31,7 +32,7 @@ class ImmutableEventDispatcherTest extends \PHPUnit_Framework_TestCase protected function setUp() { - $this->innerDispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); + $this->innerDispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock(); $this->dispatcher = new ImmutableEventDispatcher($this->innerDispatcher); } @@ -80,7 +81,7 @@ class ImmutableEventDispatcherTest extends \PHPUnit_Framework_TestCase */ public function testAddSubscriberDisallowed() { - $subscriber = $this->getMock('Symfony\Component\EventDispatcher\EventSubscriberInterface'); + $subscriber = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventSubscriberInterface')->getMock(); $this->dispatcher->addSubscriber($subscriber); } @@ -98,7 +99,7 @@ class ImmutableEventDispatcherTest extends \PHPUnit_Framework_TestCase */ public function testRemoveSubscriberDisallowed() { - $subscriber = $this->getMock('Symfony\Component\EventDispatcher\EventSubscriberInterface'); + $subscriber = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventSubscriberInterface')->getMock(); $this->dispatcher->removeSubscriber($subscriber); } diff --git a/vendor/symfony/event-dispatcher/composer.json b/vendor/symfony/event-dispatcher/composer.json index 3a20c35f..75b881b9 100644 --- a/vendor/symfony/event-dispatcher/composer.json +++ b/vendor/symfony/event-dispatcher/composer.json @@ -16,15 +16,18 @@ } ], "require": { - "php": ">=5.3.9" + "php": "^5.5.9|>=7.0.8" }, "require-dev": { - "symfony/dependency-injection": "~2.6", - "symfony/expression-language": "~2.6", - "symfony/config": "~2.0,>=2.0.5", - "symfony/stopwatch": "~2.3", + "symfony/dependency-injection": "~3.3|~4.0", + "symfony/expression-language": "~2.8|~3.0|~4.0", + "symfony/config": "~2.8|~3.0|~4.0", + "symfony/stopwatch": "~2.8|~3.0|~4.0", "psr/log": "~1.0" }, + "conflict": { + "symfony/dependency-injection": "<3.3" + }, "suggest": { "symfony/dependency-injection": "", "symfony/http-kernel": "" @@ -38,7 +41,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "2.7-dev" + "dev-master": "3.4-dev" } } } diff --git a/vendor/symfony/event-dispatcher/phpunit.xml.dist b/vendor/symfony/event-dispatcher/phpunit.xml.dist index ae0586e0..b3ad1bdf 100644 --- a/vendor/symfony/event-dispatcher/phpunit.xml.dist +++ b/vendor/symfony/event-dispatcher/phpunit.xml.dist @@ -5,6 +5,8 @@ backupGlobals="false" colors="true" bootstrap="vendor/autoload.php" + failOnRisky="true" + failOnWarning="true" > <php> <ini name="error_reporting" value="-1" /> diff --git a/vendor/symfony/polyfill-mbstring/composer.json b/vendor/symfony/polyfill-mbstring/composer.json index 48fc3ddf..5946b5d8 100644 --- a/vendor/symfony/polyfill-mbstring/composer.json +++ b/vendor/symfony/polyfill-mbstring/composer.json @@ -28,7 +28,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "1.6-dev" } } } |