From 5cefd19f489ce7ccdc847471e7e468404d013392 Mon Sep 17 00:00:00 2001 From: Anton Medvedev Date: Sat, 19 Oct 2024 23:35:57 +0200 Subject: [PATCH] Install deps with support of php7.3 --- deps/composer.json | 2 + deps/composer.lock | 3515 +++++++++++++++-- deps/vendor/composer/autoload_classmap.php | 1 - deps/vendor/composer/autoload_files.php | 5 +- deps/vendor/composer/autoload_namespaces.php | 1 + deps/vendor/composer/autoload_psr4.php | 4 +- deps/vendor/composer/autoload_real.php | 2 - deps/vendor/composer/autoload_static.php | 36 +- deps/vendor/composer/installed.json | 803 ++-- deps/vendor/composer/installed.php | 183 +- deps/vendor/composer/platform_check.php | 26 - .../vendor/evenement/evenement/.gitattributes | 7 - deps/vendor/evenement/evenement/.gitignore | 2 + deps/vendor/evenement/evenement/.travis.yml | 24 + deps/vendor/evenement/evenement/CHANGELOG.md | 35 + deps/vendor/evenement/evenement/README.md | 55 +- deps/vendor/evenement/evenement/composer.json | 12 +- .../evenement/evenement/doc/00-intro.md | 28 + deps/vendor/evenement/evenement/doc/01-api.md | 91 + .../evenement/doc/02-plugin-system.md | 155 + .../examples/benchmark-emit-no-arguments.php | 28 + .../examples/benchmark-emit-once.php | 30 + .../examples/benchmark-emit-one-argument.php | 28 + .../evenement/examples/benchmark-emit.php | 28 + .../benchmark-remove-listener-once.php | 39 + .../evenement/evenement/phpunit.xml.dist | 24 + .../src/{ => Evenement}/EventEmitter.php | 0 .../{ => Evenement}/EventEmitterInterface.php | 0 .../src/{ => Evenement}/EventEmitterTrait.php | 43 +- .../Evenement/Tests/EventEmitterTest.php | 438 ++ .../tests/Evenement/Tests/Listener.php | 51 + .../tests/Evenement/Tests/functions.php | 17 + .../justinrainbow/json-schema/.php_cs.dist | 34 + .../justinrainbow/json-schema/composer.json | 17 +- .../justinrainbow/json-schema/demo/README.md | 14 + .../justinrainbow/json-schema/demo/data.json | 3 + .../justinrainbow/json-schema/demo/demo.php | 18 + .../json-schema/demo/schema.json | 3 + .../json-schema/phpunit.xml.dist | 26 + .../JsonSchema/Constraints/BaseConstraint.php | 4 +- .../Constraints/CollectionConstraint.php | 4 +- .../src/JsonSchema/Constraints/Constraint.php | 18 +- .../Constraints/ConstraintInterface.php | 4 +- .../JsonSchema/Constraints/EnumConstraint.php | 2 +- .../src/JsonSchema/Constraints/Factory.php | 4 +- .../Constraints/FormatConstraint.php | 2 +- .../Constraints/NumberConstraint.php | 2 +- .../Constraints/ObjectConstraint.php | 10 +- .../Constraints/SchemaConstraint.php | 2 +- .../Constraints/StringConstraint.php | 2 +- .../JsonSchema/Constraints/TypeConstraint.php | 4 +- .../Constraints/UndefinedConstraint.php | 3 +- .../Exception/JsonDecodingException.php | 2 +- .../src/JsonSchema/SchemaStorage.php | 4 +- deps/vendor/psr/container/composer.json | 7 +- .../src/ContainerExceptionInterface.php | 4 +- .../psr/container/src/ContainerInterface.php | 2 +- deps/vendor/psr/http-message/README.md | 5 +- deps/vendor/psr/http-message/composer.json | 4 +- .../psr/http-message/docs/PSR7-Interfaces.md | 130 - .../psr/http-message/docs/PSR7-Usage.md | 159 - .../psr/http-message/src/MessageInterface.php | 16 +- .../psr/http-message/src/RequestInterface.php | 10 +- .../http-message/src/ResponseInterface.php | 4 +- .../src/ServerRequestInterface.php | 8 +- .../psr/http-message/src/StreamInterface.php | 12 +- .../src/UploadedFileInterface.php | 4 +- .../psr/http-message/src/UriInterface.php | 17 +- deps/vendor/react/cache/CHANGELOG.md | 11 - deps/vendor/react/cache/README.md | 11 +- deps/vendor/react/cache/composer.json | 14 +- deps/vendor/react/dns/CHANGELOG.md | 41 - deps/vendor/react/dns/README.md | 15 +- deps/vendor/react/dns/composer.json | 16 +- .../react/dns/src/Query/ExecutorInterface.php | 2 +- .../react/dns/src/Query/RetryExecutor.php | 9 +- .../dns/src/Query/TcpTransportExecutor.php | 27 +- .../react/dns/src/Query/TimeoutExecutor.php | 59 +- .../dns/src/Query/UdpTransportExecutor.php | 27 +- .../vendor/react/dns/src/Resolver/Factory.php | 16 +- .../dns/src/Resolver/ResolverInterface.php | 4 +- deps/vendor/react/event-loop/CHANGELOG.md | 42 - deps/vendor/react/event-loop/README.md | 101 +- deps/vendor/react/event-loop/composer.json | 10 +- .../vendor/react/event-loop/src/ExtEvLoop.php | 4 +- .../react/event-loop/src/ExtEventLoop.php | 2 +- .../react/event-loop/src/ExtLibevLoop.php | 2 +- .../react/event-loop/src/ExtLibeventLoop.php | 4 +- deps/vendor/react/event-loop/src/Loop.php | 67 +- .../react/event-loop/src/LoopInterface.php | 55 +- .../react/event-loop/src/StreamSelectLoop.php | 34 +- .../react/event-loop/src/Timer/Timers.php | 12 +- deps/vendor/react/http/CHANGELOG.md | 108 +- deps/vendor/react/http/README.md | 123 +- deps/vendor/react/http/composer.json | 28 +- deps/vendor/react/http/src/Browser.php | 85 +- deps/vendor/react/http/src/Client/Client.php | 24 +- deps/vendor/react/http/src/Client/Request.php | 237 ++ .../react/http/src/Client/RequestData.php | 128 + .../react/http/src/Io/AbstractMessage.php | 172 - .../react/http/src/Io/AbstractRequest.php | 156 - .../http/src/Io/ClientConnectionManager.php | 137 - .../react/http/src/Io/ClientRequestState.php | 16 - .../react/http/src/Io/ClientRequestStream.php | 307 -- deps/vendor/react/http/src/Io/Clock.php | 54 - .../react/http/src/Io/MultipartParser.php | 29 +- .../react/http/src/Io/RequestHeaderParser.php | 214 +- deps/vendor/react/http/src/Io/Sender.php | 35 +- .../react/http/src/Io/StreamingServer.php | 42 +- deps/vendor/react/http/src/Io/Transaction.php | 183 +- .../vendor/react/http/src/Message/Request.php | 57 - .../react/http/src/Message/Response.php | 141 +- .../react/http/src/Message/ServerRequest.php | 166 +- deps/vendor/react/http/src/Message/Uri.php | 356 -- .../LimitConcurrentRequestsMiddleware.php | 2 +- .../RequestBodyBufferMiddleware.php | 75 +- deps/vendor/react/promise-stream/CHANGELOG.md | 79 + deps/vendor/react/promise-stream/LICENSE | 21 + deps/vendor/react/promise-stream/README.md | 292 ++ .../vendor/react/promise-stream/composer.json | 47 + .../src/UnwrapReadableStream.php | 137 + .../src/UnwrapWritableStream.php | 164 + .../react/promise-stream/src/functions.php | 370 ++ .../promise-stream/src/functions_include.php | 7 + deps/vendor/react/promise-timer/CHANGELOG.md | 115 + deps/vendor/react/promise-timer/LICENSE | 21 + deps/vendor/react/promise-timer/README.md | 321 ++ deps/vendor/react/promise-timer/composer.json | 44 + .../promise-timer/src/TimeoutException.php | 35 + .../react/promise-timer/src/functions.php | 335 ++ .../promise-timer/src/functions_include.php | 7 + deps/vendor/react/promise/CHANGELOG.md | 278 +- deps/vendor/react/promise/README.md | 562 ++- deps/vendor/react/promise/composer.json | 19 +- .../src/CancellablePromiseInterface.php | 17 + .../src/{Internal => }/CancellationQueue.php | 23 +- deps/vendor/react/promise/src/Deferred.php | 69 +- .../src/Exception/CompositeException.php | 32 - .../promise/src/ExtendedPromiseInterface.php | 98 + .../react/promise/src/FulfilledPromise.php | 71 + .../promise/src/Internal/FulfilledPromise.php | 89 - .../promise/src/Internal/RejectedPromise.php | 128 - deps/vendor/react/promise/src/LazyPromise.php | 66 + deps/vendor/react/promise/src/Promise.php | 239 +- .../react/promise/src/PromiseInterface.php | 129 +- .../react/promise/src/PromisorInterface.php | 13 + .../react/promise/src/RejectedPromise.php | 79 + .../src/UnhandledRejectionException.php | 31 + deps/vendor/react/promise/src/functions.php | 424 +- deps/vendor/react/socket/CHANGELOG.md | 55 - deps/vendor/react/socket/README.md | 13 +- deps/vendor/react/socket/composer.json | 18 +- deps/vendor/react/socket/src/Connection.php | 8 +- deps/vendor/react/socket/src/Connector.php | 2 +- .../react/socket/src/ConnectorInterface.php | 3 +- deps/vendor/react/socket/src/DnsConnector.php | 12 +- deps/vendor/react/socket/src/FdServer.php | 24 +- .../src/HappyEyeBallsConnectionBuilder.php | 27 +- .../socket/src/HappyEyeBallsConnector.php | 19 +- .../react/socket/src/SecureConnector.php | 20 +- deps/vendor/react/socket/src/SecureServer.php | 6 +- deps/vendor/react/socket/src/Server.php | 12 +- deps/vendor/react/socket/src/SocketServer.php | 70 +- .../react/socket/src/StreamEncryption.php | 19 +- deps/vendor/react/socket/src/TcpConnector.php | 34 +- deps/vendor/react/socket/src/TcpServer.php | 10 +- .../react/socket/src/TimeoutConnector.php | 78 +- .../vendor/react/socket/src/UnixConnector.php | 11 +- deps/vendor/react/socket/src/UnixServer.php | 36 +- deps/vendor/react/stream/CHANGELOG.md | 25 - deps/vendor/react/stream/README.md | 13 +- deps/vendor/react/stream/composer.json | 6 +- .../react/stream/src/DuplexResourceStream.php | 17 +- .../stream/src/ReadableResourceStream.php | 11 +- .../vendor/react/stream/src/ThroughStream.php | 19 +- .../stream/src/WritableResourceStream.php | 12 +- .../stream/src/WritableStreamInterface.php | 2 +- deps/vendor/ringcentral/psr7/.gitignore | 11 + deps/vendor/ringcentral/psr7/.travis.yml | 21 + deps/vendor/ringcentral/psr7/CHANGELOG.md | 28 + deps/vendor/ringcentral/psr7/Dockerfile | 5 + deps/vendor/ringcentral/psr7/LICENSE | 19 + deps/vendor/ringcentral/psr7/Makefile | 21 + deps/vendor/ringcentral/psr7/README.md | 587 +++ deps/vendor/ringcentral/psr7/composer.json | 35 + deps/vendor/ringcentral/psr7/phpunit.xml.dist | 17 + .../ringcentral/psr7/src/AppendStream.php | 233 ++ .../ringcentral/psr7/src/BufferStream.php | 137 + .../ringcentral/psr7/src/CachingStream.php | 135 + .../ringcentral/psr7/src/DroppingStream.php | 41 + deps/vendor/ringcentral/psr7/src/FnStream.php | 163 + .../ringcentral/psr7/src/InflateStream.php | 27 + .../ringcentral/psr7/src/LazyOpenStream.php | 39 + .../ringcentral/psr7/src/LimitStream.php | 154 + .../ringcentral/psr7/src/MessageTrait.php | 167 + .../ringcentral/psr7/src/MultipartStream.php | 152 + .../ringcentral/psr7/src/NoSeekStream.php | 21 + .../ringcentral/psr7/src/PumpStream.php | 165 + deps/vendor/ringcentral/psr7/src/Request.php | 146 + deps/vendor/ringcentral/psr7/src/Response.php | 129 + .../ringcentral/psr7/src/ServerRequest.php | 122 + deps/vendor/ringcentral/psr7/src/Stream.php | 245 ++ .../psr7/src/StreamDecoratorTrait.php | 139 + .../ringcentral/psr7/src/StreamWrapper.php | 121 + deps/vendor/ringcentral/psr7/src/Uri.php | 601 +++ .../vendor/ringcentral/psr7/src/functions.php | 835 ++++ .../psr7/src/functions_include.php | 6 + .../psr7/tests/AppendStreamTest.php | 186 + .../psr7/tests/BufferStreamTest.php | 63 + .../psr7/tests/CachingStreamTest.php | 166 + .../psr7/tests/DroppingStreamTest.php | 26 + .../ringcentral/psr7/tests/FnStreamTest.php | 92 + .../ringcentral/psr7/tests/FunctionsTest.php | 604 +++ .../psr7/tests/InflateStreamTest.php | 21 + .../psr7/tests/LazyOpenStreamTest.php | 64 + .../psr7/tests/LimitStreamTest.php | 166 + .../psr7/tests/MultipartStreamTest.php | 214 + .../psr7/tests/NoSeekStreamTest.php | 40 + .../ringcentral/psr7/tests/PumpStreamTest.php | 72 + .../ringcentral/psr7/tests/RequestTest.php | 157 + .../ringcentral/psr7/tests/ResponseTest.php | 154 + .../psr7/tests/ServerRequestTest.php | 85 + .../psr7/tests/StreamDecoratorTraitTest.php | 123 + .../ringcentral/psr7/tests/StreamTest.php | 163 + .../psr7/tests/StreamWrapperTest.php | 100 + .../vendor/ringcentral/psr7/tests/UriTest.php | 258 ++ .../ringcentral/psr7/tests/bootstrap.php | 13 + deps/vendor/symfony/console/Application.php | 6 +- .../console/CI/GithubActionReporter.php | 8 +- .../symfony/console/Command/Command.php | 16 +- .../console/Command/CompleteCommand.php | 4 +- .../console/Command/DumpCompletionCommand.php | 18 +- .../symfony/console/Command/LazyCommand.php | 6 +- .../symfony/console/Command/LockableTrait.php | 2 +- .../console/Completion/CompletionInput.php | 2 +- .../Descriptor/ApplicationDescription.php | 2 +- .../console/Descriptor/XmlDescriptor.php | 2 +- .../console/Event/ConsoleCommandEvent.php | 5 +- .../console/Event/ConsoleErrorEvent.php | 2 +- .../console/EventListener/ErrorListener.php | 2 +- .../Exception/CommandNotFoundException.php | 2 +- .../Formatter/NullOutputFormatterStyle.php | 4 +- .../console/Formatter/OutputFormatter.php | 11 +- .../Formatter/OutputFormatterStyle.php | 9 +- .../OutputFormatterStyleInterface.php | 4 +- .../Formatter/OutputFormatterStyleStack.php | 4 +- deps/vendor/symfony/console/Helper/Dumper.php | 2 +- deps/vendor/symfony/console/Helper/Helper.php | 4 +- .../console/Helper/HelperInterface.php | 2 +- .../symfony/console/Helper/HelperSet.php | 4 +- .../symfony/console/Helper/ProcessHelper.php | 6 +- .../symfony/console/Helper/ProgressBar.php | 9 +- .../console/Helper/ProgressIndicator.php | 4 +- .../symfony/console/Helper/QuestionHelper.php | 27 +- deps/vendor/symfony/console/Helper/Table.php | 16 +- .../symfony/console/Helper/TableStyle.php | 6 +- .../symfony/console/Input/ArgvInput.php | 2 +- .../symfony/console/Input/ArrayInput.php | 2 +- deps/vendor/symfony/console/Input/Input.php | 2 +- .../symfony/console/Input/InputArgument.php | 4 +- .../symfony/console/Input/InputOption.php | 8 +- deps/vendor/symfony/console/LICENSE | 2 +- .../symfony/console/Output/ConsoleOutput.php | 2 +- .../console/Output/ConsoleSectionOutput.php | 2 +- deps/vendor/symfony/console/Output/Output.php | 2 +- .../symfony/console/Output/StreamOutput.php | 34 +- .../console/Output/TrimmedBufferOutput.php | 2 +- .../symfony/console/Question/Question.php | 4 +- .../symfony/console/Resources/completion.bash | 2 +- .../console/SingleCommandApplication.php | 2 +- .../symfony/console/Style/StyleInterface.php | 4 +- .../symfony/console/Style/SymfonyStyle.php | 10 +- deps/vendor/symfony/console/Terminal.php | 20 +- .../symfony/console/Tester/TesterTrait.php | 8 +- deps/vendor/symfony/console/composer.json | 2 +- .../symfony/deprecation-contracts/.gitignore | 3 + .../symfony/deprecation-contracts/LICENSE | 2 +- .../symfony/deprecation-contracts/README.md | 2 +- .../deprecation-contracts/composer.json | 4 +- .../deprecation-contracts/function.php | 2 +- deps/vendor/symfony/polyfill-ctype/LICENSE | 2 +- deps/vendor/symfony/polyfill-ctype/README.md | 2 +- .../symfony/polyfill-ctype/composer.json | 5 +- .../polyfill-intl-grapheme/Grapheme.php | 2 +- .../symfony/polyfill-intl-grapheme/LICENSE | 2 +- .../symfony/polyfill-intl-grapheme/README.md | 2 +- .../polyfill-intl-grapheme/composer.json | 5 +- .../symfony/polyfill-intl-normalizer/LICENSE | 2 +- .../polyfill-intl-normalizer/Normalizer.php | 2 +- .../polyfill-intl-normalizer/README.md | 2 +- .../polyfill-intl-normalizer/composer.json | 5 +- deps/vendor/symfony/polyfill-mbstring/LICENSE | 2 +- .../symfony/polyfill-mbstring/Mbstring.php | 246 +- .../symfony/polyfill-mbstring/README.md | 2 +- .../Resources/unidata/caseFolding.php | 119 - .../symfony/polyfill-mbstring/bootstrap.php | 25 - .../symfony/polyfill-mbstring/bootstrap80.php | 26 +- .../symfony/polyfill-mbstring/composer.json | 5 +- deps/vendor/symfony/polyfill-php73/LICENSE | 2 +- deps/vendor/symfony/polyfill-php73/README.md | 2 +- .../symfony/polyfill-php73/composer.json | 5 +- deps/vendor/symfony/polyfill-php80/LICENSE | 2 +- deps/vendor/symfony/polyfill-php80/README.md | 7 +- .../Resources/stubs/Attribute.php | 9 - .../Resources/stubs/PhpToken.php | 11 +- .../Resources/stubs/Stringable.php | 9 - .../Resources/stubs/UnhandledMatchError.php | 9 - .../Resources/stubs/ValueError.php | 9 - .../symfony/polyfill-php80/composer.json | 5 +- deps/vendor/symfony/polyfill-php81/LICENSE | 2 +- deps/vendor/symfony/polyfill-php81/README.md | 1 - .../Resources/stubs/CURLStringFile.php | 51 - .../Resources/stubs/ReturnTypeWillChange.php | 9 - .../symfony/polyfill-php81/composer.json | 5 +- .../symfony/process/ExecutableFinder.php | 34 +- deps/vendor/symfony/process/InputStream.php | 2 +- deps/vendor/symfony/process/LICENSE | 2 +- .../symfony/process/PhpExecutableFinder.php | 16 +- deps/vendor/symfony/process/PhpProcess.php | 6 +- .../symfony/process/Pipes/AbstractPipes.php | 2 +- .../symfony/process/Pipes/WindowsPipes.php | 2 +- deps/vendor/symfony/process/Process.php | 49 +- deps/vendor/symfony/process/ProcessUtils.php | 2 +- .../symfony/service-contracts/.gitignore | 3 + .../Attribute/SubscribedService.php | 24 +- deps/vendor/symfony/service-contracts/LICENSE | 2 +- .../symfony/service-contracts/README.md | 2 +- .../service-contracts/ResetInterface.php | 3 - .../ServiceCollectionInterface.php | 26 - .../service-contracts/ServiceLocatorTrait.php | 27 +- .../ServiceMethodsSubscriberTrait.php | 80 - .../ServiceProviderInterface.php | 11 +- .../ServiceSubscriberInterface.php | 15 +- .../ServiceSubscriberTrait.php | 115 +- .../Test/ServiceLocatorTest.php | 80 +- .../Test/ServiceLocatorTestCase.php | 96 - .../symfony/service-contracts/composer.json | 16 +- deps/vendor/symfony/string/AbstractString.php | 249 +- .../symfony/string/AbstractUnicodeString.php | 124 +- deps/vendor/symfony/string/ByteString.php | 123 +- deps/vendor/symfony/string/CHANGELOG.md | 5 - .../vendor/symfony/string/CodePointString.php | 44 +- .../string/Inflector/EnglishInflector.php | 133 +- .../string/Inflector/FrenchInflector.php | 10 +- deps/vendor/symfony/string/LICENSE | 2 +- deps/vendor/symfony/string/LazyString.php | 53 +- .../Resources/data/wcswidth_table_wide.php | 94 +- .../Resources/data/wcswidth_table_zero.php | 92 +- .../symfony/string/Resources/functions.php | 2 +- .../symfony/string/Slugger/AsciiSlugger.php | 75 +- .../string/Slugger/SluggerInterface.php | 2 +- deps/vendor/symfony/string/UnicodeString.php | 108 +- deps/vendor/symfony/string/composer.json | 16 +- .../symfony/yaml/Command/LintCommand.php | 4 +- deps/vendor/symfony/yaml/Dumper.php | 50 +- .../symfony/yaml/Exception/ParseException.php | 2 +- deps/vendor/symfony/yaml/Inline.php | 42 +- deps/vendor/symfony/yaml/LICENSE | 2 +- deps/vendor/symfony/yaml/Parser.php | 25 +- .../symfony/yaml/Resources/bin/yaml-lint | 4 - 360 files changed, 17885 insertions(+), 6871 deletions(-) delete mode 100644 deps/vendor/composer/platform_check.php delete mode 100644 deps/vendor/evenement/evenement/.gitattributes create mode 100644 deps/vendor/evenement/evenement/.gitignore create mode 100644 deps/vendor/evenement/evenement/.travis.yml create mode 100644 deps/vendor/evenement/evenement/CHANGELOG.md create mode 100644 deps/vendor/evenement/evenement/doc/00-intro.md create mode 100644 deps/vendor/evenement/evenement/doc/01-api.md create mode 100644 deps/vendor/evenement/evenement/doc/02-plugin-system.md create mode 100644 deps/vendor/evenement/evenement/examples/benchmark-emit-no-arguments.php create mode 100644 deps/vendor/evenement/evenement/examples/benchmark-emit-once.php create mode 100644 deps/vendor/evenement/evenement/examples/benchmark-emit-one-argument.php create mode 100644 deps/vendor/evenement/evenement/examples/benchmark-emit.php create mode 100644 deps/vendor/evenement/evenement/examples/benchmark-remove-listener-once.php create mode 100644 deps/vendor/evenement/evenement/phpunit.xml.dist rename deps/vendor/evenement/evenement/src/{ => Evenement}/EventEmitter.php (100%) rename deps/vendor/evenement/evenement/src/{ => Evenement}/EventEmitterInterface.php (100%) rename deps/vendor/evenement/evenement/src/{ => Evenement}/EventEmitterTrait.php (75%) create mode 100644 deps/vendor/evenement/evenement/tests/Evenement/Tests/EventEmitterTest.php create mode 100644 deps/vendor/evenement/evenement/tests/Evenement/Tests/Listener.php create mode 100644 deps/vendor/evenement/evenement/tests/Evenement/Tests/functions.php create mode 100644 deps/vendor/justinrainbow/json-schema/.php_cs.dist create mode 100644 deps/vendor/justinrainbow/json-schema/demo/README.md create mode 100644 deps/vendor/justinrainbow/json-schema/demo/data.json create mode 100644 deps/vendor/justinrainbow/json-schema/demo/demo.php create mode 100644 deps/vendor/justinrainbow/json-schema/demo/schema.json create mode 100644 deps/vendor/justinrainbow/json-schema/phpunit.xml.dist delete mode 100644 deps/vendor/psr/http-message/docs/PSR7-Interfaces.md delete mode 100644 deps/vendor/psr/http-message/docs/PSR7-Usage.md create mode 100644 deps/vendor/react/http/src/Client/Request.php create mode 100644 deps/vendor/react/http/src/Client/RequestData.php delete mode 100644 deps/vendor/react/http/src/Io/AbstractMessage.php delete mode 100644 deps/vendor/react/http/src/Io/AbstractRequest.php delete mode 100644 deps/vendor/react/http/src/Io/ClientConnectionManager.php delete mode 100644 deps/vendor/react/http/src/Io/ClientRequestState.php delete mode 100644 deps/vendor/react/http/src/Io/ClientRequestStream.php delete mode 100644 deps/vendor/react/http/src/Io/Clock.php delete mode 100644 deps/vendor/react/http/src/Message/Request.php delete mode 100644 deps/vendor/react/http/src/Message/Uri.php create mode 100644 deps/vendor/react/promise-stream/CHANGELOG.md create mode 100644 deps/vendor/react/promise-stream/LICENSE create mode 100644 deps/vendor/react/promise-stream/README.md create mode 100644 deps/vendor/react/promise-stream/composer.json create mode 100644 deps/vendor/react/promise-stream/src/UnwrapReadableStream.php create mode 100644 deps/vendor/react/promise-stream/src/UnwrapWritableStream.php create mode 100644 deps/vendor/react/promise-stream/src/functions.php create mode 100644 deps/vendor/react/promise-stream/src/functions_include.php create mode 100644 deps/vendor/react/promise-timer/CHANGELOG.md create mode 100644 deps/vendor/react/promise-timer/LICENSE create mode 100644 deps/vendor/react/promise-timer/README.md create mode 100644 deps/vendor/react/promise-timer/composer.json create mode 100644 deps/vendor/react/promise-timer/src/TimeoutException.php create mode 100644 deps/vendor/react/promise-timer/src/functions.php create mode 100644 deps/vendor/react/promise-timer/src/functions_include.php create mode 100644 deps/vendor/react/promise/src/CancellablePromiseInterface.php rename deps/vendor/react/promise/src/{Internal => }/CancellationQueue.php (66%) delete mode 100644 deps/vendor/react/promise/src/Exception/CompositeException.php create mode 100644 deps/vendor/react/promise/src/ExtendedPromiseInterface.php create mode 100644 deps/vendor/react/promise/src/FulfilledPromise.php delete mode 100644 deps/vendor/react/promise/src/Internal/FulfilledPromise.php delete mode 100644 deps/vendor/react/promise/src/Internal/RejectedPromise.php create mode 100644 deps/vendor/react/promise/src/LazyPromise.php create mode 100644 deps/vendor/react/promise/src/PromisorInterface.php create mode 100644 deps/vendor/react/promise/src/RejectedPromise.php create mode 100644 deps/vendor/react/promise/src/UnhandledRejectionException.php create mode 100644 deps/vendor/ringcentral/psr7/.gitignore create mode 100644 deps/vendor/ringcentral/psr7/.travis.yml create mode 100644 deps/vendor/ringcentral/psr7/CHANGELOG.md create mode 100644 deps/vendor/ringcentral/psr7/Dockerfile create mode 100644 deps/vendor/ringcentral/psr7/LICENSE create mode 100644 deps/vendor/ringcentral/psr7/Makefile create mode 100644 deps/vendor/ringcentral/psr7/README.md create mode 100644 deps/vendor/ringcentral/psr7/composer.json create mode 100644 deps/vendor/ringcentral/psr7/phpunit.xml.dist create mode 100644 deps/vendor/ringcentral/psr7/src/AppendStream.php create mode 100644 deps/vendor/ringcentral/psr7/src/BufferStream.php create mode 100644 deps/vendor/ringcentral/psr7/src/CachingStream.php create mode 100644 deps/vendor/ringcentral/psr7/src/DroppingStream.php create mode 100644 deps/vendor/ringcentral/psr7/src/FnStream.php create mode 100644 deps/vendor/ringcentral/psr7/src/InflateStream.php create mode 100644 deps/vendor/ringcentral/psr7/src/LazyOpenStream.php create mode 100644 deps/vendor/ringcentral/psr7/src/LimitStream.php create mode 100644 deps/vendor/ringcentral/psr7/src/MessageTrait.php create mode 100644 deps/vendor/ringcentral/psr7/src/MultipartStream.php create mode 100644 deps/vendor/ringcentral/psr7/src/NoSeekStream.php create mode 100644 deps/vendor/ringcentral/psr7/src/PumpStream.php create mode 100644 deps/vendor/ringcentral/psr7/src/Request.php create mode 100644 deps/vendor/ringcentral/psr7/src/Response.php create mode 100644 deps/vendor/ringcentral/psr7/src/ServerRequest.php create mode 100644 deps/vendor/ringcentral/psr7/src/Stream.php create mode 100644 deps/vendor/ringcentral/psr7/src/StreamDecoratorTrait.php create mode 100644 deps/vendor/ringcentral/psr7/src/StreamWrapper.php create mode 100644 deps/vendor/ringcentral/psr7/src/Uri.php create mode 100644 deps/vendor/ringcentral/psr7/src/functions.php create mode 100644 deps/vendor/ringcentral/psr7/src/functions_include.php create mode 100644 deps/vendor/ringcentral/psr7/tests/AppendStreamTest.php create mode 100644 deps/vendor/ringcentral/psr7/tests/BufferStreamTest.php create mode 100644 deps/vendor/ringcentral/psr7/tests/CachingStreamTest.php create mode 100644 deps/vendor/ringcentral/psr7/tests/DroppingStreamTest.php create mode 100644 deps/vendor/ringcentral/psr7/tests/FnStreamTest.php create mode 100644 deps/vendor/ringcentral/psr7/tests/FunctionsTest.php create mode 100644 deps/vendor/ringcentral/psr7/tests/InflateStreamTest.php create mode 100644 deps/vendor/ringcentral/psr7/tests/LazyOpenStreamTest.php create mode 100644 deps/vendor/ringcentral/psr7/tests/LimitStreamTest.php create mode 100644 deps/vendor/ringcentral/psr7/tests/MultipartStreamTest.php create mode 100644 deps/vendor/ringcentral/psr7/tests/NoSeekStreamTest.php create mode 100644 deps/vendor/ringcentral/psr7/tests/PumpStreamTest.php create mode 100644 deps/vendor/ringcentral/psr7/tests/RequestTest.php create mode 100644 deps/vendor/ringcentral/psr7/tests/ResponseTest.php create mode 100644 deps/vendor/ringcentral/psr7/tests/ServerRequestTest.php create mode 100644 deps/vendor/ringcentral/psr7/tests/StreamDecoratorTraitTest.php create mode 100644 deps/vendor/ringcentral/psr7/tests/StreamTest.php create mode 100644 deps/vendor/ringcentral/psr7/tests/StreamWrapperTest.php create mode 100644 deps/vendor/ringcentral/psr7/tests/UriTest.php create mode 100644 deps/vendor/ringcentral/psr7/tests/bootstrap.php create mode 100644 deps/vendor/symfony/deprecation-contracts/.gitignore delete mode 100644 deps/vendor/symfony/polyfill-mbstring/Resources/unidata/caseFolding.php delete mode 100644 deps/vendor/symfony/polyfill-php81/Resources/stubs/CURLStringFile.php create mode 100644 deps/vendor/symfony/service-contracts/.gitignore delete mode 100644 deps/vendor/symfony/service-contracts/ServiceCollectionInterface.php delete mode 100644 deps/vendor/symfony/service-contracts/ServiceMethodsSubscriberTrait.php delete mode 100644 deps/vendor/symfony/service-contracts/Test/ServiceLocatorTestCase.php diff --git a/deps/composer.json b/deps/composer.json index 7f4591a64..8b4bb48b2 100644 --- a/deps/composer.json +++ b/deps/composer.json @@ -1,5 +1,7 @@ { "require": { + "php": "^8.0|^7.3", + "ext-json": "*", "justinrainbow/json-schema": "^5.2", "psr/http-message": "^1", "react/http": "^1.5", diff --git a/deps/composer.lock b/deps/composer.lock index c11050c45..3042e95e4 100644 --- a/deps/composer.lock +++ b/deps/composer.lock @@ -4,32 +4,32 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "6e0324fc886fd55694e53338d30399bc", + "content-hash": "2e4a876ba583ea7b5ddf4bebd46c0262", "packages": [ { "name": "evenement/evenement", - "version": "v3.0.2", + "version": "v3.0.1", "source": { "type": "git", "url": "https://github.com/igorw/evenement.git", - "reference": "0a16b0d71ab13284339abb99d9d2bd813640efbc" + "reference": "531bfb9d15f8aa57454f5f0285b18bec903b8fb7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/igorw/evenement/zipball/0a16b0d71ab13284339abb99d9d2bd813640efbc", - "reference": "0a16b0d71ab13284339abb99d9d2bd813640efbc", + "url": "https://api.github.com/repos/igorw/evenement/zipball/531bfb9d15f8aa57454f5f0285b18bec903b8fb7", + "reference": "531bfb9d15f8aa57454f5f0285b18bec903b8fb7", "shasum": "" }, "require": { "php": ">=7.0" }, "require-dev": { - "phpunit/phpunit": "^9 || ^6" + "phpunit/phpunit": "^6.0" }, "type": "library", "autoload": { - "psr-4": { - "Evenement\\": "src/" + "psr-0": { + "Evenement": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -49,9 +49,9 @@ ], "support": { "issues": "https://github.com/igorw/evenement/issues", - "source": "https://github.com/igorw/evenement/tree/v3.0.2" + "source": "https://github.com/igorw/evenement/tree/master" }, - "time": "2023-08-08T05:53:35+00:00" + "time": "2017-07-23T21:35:13+00:00" }, { "name": "fig/http-message-util", @@ -111,20 +111,20 @@ }, { "name": "justinrainbow/json-schema", - "version": "5.3.0", + "version": "5.2.11", "source": { "type": "git", - "url": "https://github.com/jsonrainbow/json-schema.git", - "reference": "feb2ca6dd1cebdaf1ed60a4c8de2e53ce11c4fd8" + "url": "https://github.com/justinrainbow/json-schema.git", + "reference": "2ab6744b7296ded80f8cc4f9509abbff393399aa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/feb2ca6dd1cebdaf1ed60a4c8de2e53ce11c4fd8", - "reference": "feb2ca6dd1cebdaf1ed60a4c8de2e53ce11c4fd8", + "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/2ab6744b7296ded80f8cc4f9509abbff393399aa", + "reference": "2ab6744b7296ded80f8cc4f9509abbff393399aa", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=5.3.3" }, "require-dev": { "friendsofphp/php-cs-fixer": "~2.2.20||~2.15.1", @@ -135,6 +135,11 @@ "bin/validate-json" ], "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0.x-dev" + } + }, "autoload": { "psr-4": { "JsonSchema\\": "src/JsonSchema/" @@ -169,34 +174,29 @@ "schema" ], "support": { - "issues": "https://github.com/jsonrainbow/json-schema/issues", - "source": "https://github.com/jsonrainbow/json-schema/tree/5.3.0" + "issues": "https://github.com/justinrainbow/json-schema/issues", + "source": "https://github.com/justinrainbow/json-schema/tree/5.2.11" }, - "time": "2024-07-06T21:00:26+00:00" + "time": "2021-07-22T09:24:00+00:00" }, { "name": "psr/container", - "version": "2.0.2", + "version": "1.1.1", "source": { "type": "git", "url": "https://github.com/php-fig/container.git", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "url": "https://api.github.com/repos/php-fig/container/zipball/8622567409010282b7aeebe4bb841fe98b58dcaf", + "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf", "shasum": "" }, "require": { - "php": ">=7.4.0" + "php": ">=7.2.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, "autoload": { "psr-4": { "Psr\\Container\\": "src/" @@ -223,31 +223,31 @@ ], "support": { "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/2.0.2" + "source": "https://github.com/php-fig/container/tree/1.1.1" }, - "time": "2021-11-05T16:47:00+00:00" + "time": "2021-03-05T17:36:06+00:00" }, { "name": "psr/http-message", - "version": "1.1", + "version": "1.0.1", "source": { "type": "git", "url": "https://github.com/php-fig/http-message.git", - "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba" + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/cb6ce4845ce34a8ad9e68117c10ee90a29919eba", - "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0" + "php": ">=5.3.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1.x-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { @@ -276,22 +276,22 @@ "response" ], "support": { - "source": "https://github.com/php-fig/http-message/tree/1.1" + "source": "https://github.com/php-fig/http-message/tree/master" }, - "time": "2023-04-04T09:50:52+00:00" + "time": "2016-08-06T14:39:51+00:00" }, { "name": "react/cache", - "version": "v1.2.0", + "version": "v1.1.1", "source": { "type": "git", "url": "https://github.com/reactphp/cache.git", - "reference": "d47c472b64aa5608225f47965a484b75c7817d5b" + "reference": "4bf736a2cccec7298bdf745db77585966fc2ca7e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/cache/zipball/d47c472b64aa5608225f47965a484b75c7817d5b", - "reference": "d47c472b64aa5608225f47965a484b75c7817d5b", + "url": "https://api.github.com/repos/reactphp/cache/zipball/4bf736a2cccec7298bdf745db77585966fc2ca7e", + "reference": "4bf736a2cccec7298bdf745db77585966fc2ca7e", "shasum": "" }, "require": { @@ -299,7 +299,7 @@ "react/promise": "^3.0 || ^2.0 || ^1.1" }, "require-dev": { - "phpunit/phpunit": "^9.5 || ^5.7 || ^4.8.35" + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35" }, "type": "library", "autoload": { @@ -342,45 +342,49 @@ ], "support": { "issues": "https://github.com/reactphp/cache/issues", - "source": "https://github.com/reactphp/cache/tree/v1.2.0" + "source": "https://github.com/reactphp/cache/tree/v1.1.1" }, "funding": [ { - "url": "https://opencollective.com/reactphp", - "type": "open_collective" + "url": "https://github.com/WyriHaximus", + "type": "github" + }, + { + "url": "https://github.com/clue", + "type": "github" } ], - "time": "2022-11-30T15:59:55+00:00" + "time": "2021-02-02T06:47:52+00:00" }, { "name": "react/dns", - "version": "v1.13.0", + "version": "v1.9.0", "source": { "type": "git", "url": "https://github.com/reactphp/dns.git", - "reference": "eb8ae001b5a455665c89c1df97f6fb682f8fb0f5" + "reference": "6d38296756fa644e6cb1bfe95eff0f9a4ed6edcb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/dns/zipball/eb8ae001b5a455665c89c1df97f6fb682f8fb0f5", - "reference": "eb8ae001b5a455665c89c1df97f6fb682f8fb0f5", + "url": "https://api.github.com/repos/reactphp/dns/zipball/6d38296756fa644e6cb1bfe95eff0f9a4ed6edcb", + "reference": "6d38296756fa644e6cb1bfe95eff0f9a4ed6edcb", "shasum": "" }, "require": { "php": ">=5.3.0", "react/cache": "^1.0 || ^0.6 || ^0.5", "react/event-loop": "^1.2", - "react/promise": "^3.2 || ^2.7 || ^1.2.1" + "react/promise": "^3.0 || ^2.7 || ^1.2.1", + "react/promise-timer": "^1.8" }, "require-dev": { - "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", - "react/async": "^4.3 || ^3 || ^2", - "react/promise-timer": "^1.11" + "clue/block-react": "^1.2", + "phpunit/phpunit": "^9.3 || ^4.8.35" }, "type": "library", "autoload": { "psr-4": { - "React\\Dns\\": "src/" + "React\\Dns\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -418,43 +422,49 @@ ], "support": { "issues": "https://github.com/reactphp/dns/issues", - "source": "https://github.com/reactphp/dns/tree/v1.13.0" + "source": "https://github.com/reactphp/dns/tree/v1.9.0" }, "funding": [ { - "url": "https://opencollective.com/reactphp", - "type": "open_collective" + "url": "https://github.com/WyriHaximus", + "type": "github" + }, + { + "url": "https://github.com/clue", + "type": "github" } ], - "time": "2024-06-13T14:18:03+00:00" + "time": "2021-12-20T08:46:54+00:00" }, { "name": "react/event-loop", - "version": "v1.5.0", + "version": "v1.2.0", "source": { "type": "git", "url": "https://github.com/reactphp/event-loop.git", - "reference": "bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354" + "reference": "be6dee480fc4692cec0504e65eb486e3be1aa6f2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/event-loop/zipball/bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354", - "reference": "bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354", + "url": "https://api.github.com/repos/reactphp/event-loop/zipball/be6dee480fc4692cec0504e65eb486e3be1aa6f2", + "reference": "be6dee480fc4692cec0504e65eb486e3be1aa6f2", "shasum": "" }, "require": { "php": ">=5.3.0" }, "require-dev": { - "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35" }, "suggest": { - "ext-pcntl": "For signal handling support when using the StreamSelectLoop" + "ext-event": "~1.0 for ExtEventLoop", + "ext-pcntl": "For signal handling support when using the StreamSelectLoop", + "ext-uv": "* for ExtUvLoop" }, "type": "library", "autoload": { "psr-4": { - "React\\EventLoop\\": "src/" + "React\\EventLoop\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -490,28 +500,32 @@ ], "support": { "issues": "https://github.com/reactphp/event-loop/issues", - "source": "https://github.com/reactphp/event-loop/tree/v1.5.0" + "source": "https://github.com/reactphp/event-loop/tree/v1.2.0" }, "funding": [ { - "url": "https://opencollective.com/reactphp", - "type": "open_collective" + "url": "https://github.com/WyriHaximus", + "type": "github" + }, + { + "url": "https://github.com/clue", + "type": "github" } ], - "time": "2023-11-13T13:48:05+00:00" + "time": "2021-07-11T12:31:24+00:00" }, { "name": "react/http", - "version": "v1.10.0", + "version": "v1.6.0", "source": { "type": "git", "url": "https://github.com/reactphp/http.git", - "reference": "8111281ee57f22b7194f5dba225e609ba7ce4d20" + "reference": "59961cc4a5b14481728f07c591546be18fa3a5c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/http/zipball/8111281ee57f22b7194f5dba225e609ba7ce4d20", - "reference": "8111281ee57f22b7194f5dba225e609ba7ce4d20", + "url": "https://api.github.com/repos/reactphp/http/zipball/59961cc4a5b14481728f07c591546be18fa3a5c7", + "reference": "59961cc4a5b14481728f07c591546be18fa3a5c7", "shasum": "" }, "require": { @@ -520,23 +534,23 @@ "php": ">=5.3.0", "psr/http-message": "^1.0", "react/event-loop": "^1.2", - "react/promise": "^3 || ^2.3 || ^1.2.1", - "react/socket": "^1.12", - "react/stream": "^1.2" + "react/promise": "^2.3 || ^1.2.1", + "react/promise-stream": "^1.1", + "react/socket": "^1.9", + "react/stream": "^1.2", + "ringcentral/psr7": "^1.2" }, "require-dev": { - "clue/http-proxy-react": "^1.8", - "clue/reactphp-ssh-proxy": "^1.4", - "clue/socks-react": "^1.4", - "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", - "react/async": "^4 || ^3 || ^2", - "react/promise-stream": "^1.4", - "react/promise-timer": "^1.9" + "clue/block-react": "^1.5", + "clue/http-proxy-react": "^1.7", + "clue/reactphp-ssh-proxy": "^1.3", + "clue/socks-react": "^1.3", + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35" }, "type": "library", "autoload": { "psr-4": { - "React\\Http\\": "src/" + "React\\Http\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -581,36 +595,39 @@ ], "support": { "issues": "https://github.com/reactphp/http/issues", - "source": "https://github.com/reactphp/http/tree/v1.10.0" + "source": "https://github.com/reactphp/http/tree/v1.6.0" }, "funding": [ { - "url": "https://opencollective.com/reactphp", - "type": "open_collective" + "url": "https://github.com/WyriHaximus", + "type": "github" + }, + { + "url": "https://github.com/clue", + "type": "github" } ], - "time": "2024-03-27T17:20:46+00:00" + "time": "2022-02-03T13:17:37+00:00" }, { "name": "react/promise", - "version": "v3.2.0", + "version": "v2.9.0", "source": { "type": "git", "url": "https://github.com/reactphp/promise.git", - "reference": "8a164643313c71354582dc850b42b33fa12a4b63" + "reference": "234f8fd1023c9158e2314fa9d7d0e6a83db42910" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/promise/zipball/8a164643313c71354582dc850b42b33fa12a4b63", - "reference": "8a164643313c71354582dc850b42b33fa12a4b63", + "url": "https://api.github.com/repos/reactphp/promise/zipball/234f8fd1023c9158e2314fa9d7d0e6a83db42910", + "reference": "234f8fd1023c9158e2314fa9d7d0e6a83db42910", "shasum": "" }, "require": { - "php": ">=7.1.0" + "php": ">=5.4.0" }, "require-dev": { - "phpstan/phpstan": "1.10.39 || 1.4.10", - "phpunit/phpunit": "^9.6 || ^7.5" + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.36" }, "type": "library", "autoload": { @@ -654,48 +671,221 @@ ], "support": { "issues": "https://github.com/reactphp/promise/issues", - "source": "https://github.com/reactphp/promise/tree/v3.2.0" + "source": "https://github.com/reactphp/promise/tree/v2.9.0" + }, + "funding": [ + { + "url": "https://github.com/WyriHaximus", + "type": "github" + }, + { + "url": "https://github.com/clue", + "type": "github" + } + ], + "time": "2022-02-11T10:27:51+00:00" + }, + { + "name": "react/promise-stream", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/promise-stream.git", + "reference": "3ebd94fe0d8edbf44937948af28d02d5437e9949" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/promise-stream/zipball/3ebd94fe0d8edbf44937948af28d02d5437e9949", + "reference": "3ebd94fe0d8edbf44937948af28d02d5437e9949", + "shasum": "" + }, + "require": { + "php": ">=5.3", + "react/promise": "^2.1 || ^1.2", + "react/stream": "^1.0 || ^0.7 || ^0.6 || ^0.5 || ^0.4.6" + }, + "require-dev": { + "clue/block-react": "^1.0", + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35", + "react/event-loop": "^1.0 || ^0.5 || ^0.4 || ^0.3", + "react/promise-timer": "^1.0" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "React\\Promise\\Stream\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "The missing link between Promise-land and Stream-land for ReactPHP", + "homepage": "https://github.com/reactphp/promise-stream", + "keywords": [ + "Buffer", + "async", + "promise", + "reactphp", + "stream", + "unwrap" + ], + "support": { + "issues": "https://github.com/reactphp/promise-stream/issues", + "source": "https://github.com/reactphp/promise-stream/tree/v1.3.0" + }, + "funding": [ + { + "url": "https://github.com/WyriHaximus", + "type": "github" + }, + { + "url": "https://github.com/clue", + "type": "github" + } + ], + "time": "2021-10-18T10:47:09+00:00" + }, + { + "name": "react/promise-timer", + "version": "v1.8.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/promise-timer.git", + "reference": "0bbbcc79589e5bfdddba68a287f1cb805581a479" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/promise-timer/zipball/0bbbcc79589e5bfdddba68a287f1cb805581a479", + "reference": "0bbbcc79589e5bfdddba68a287f1cb805581a479", + "shasum": "" + }, + "require": { + "php": ">=5.3", + "react/event-loop": "^1.2", + "react/promise": "^3.0 || ^2.7.0 || ^1.2.1" + }, + "require-dev": { + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "React\\Promise\\Timer\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "A trivial implementation of timeouts for Promises, built on top of ReactPHP.", + "homepage": "https://github.com/reactphp/promise-timer", + "keywords": [ + "async", + "event-loop", + "promise", + "reactphp", + "timeout", + "timer" + ], + "support": { + "issues": "https://github.com/reactphp/promise-timer/issues", + "source": "https://github.com/reactphp/promise-timer/tree/v1.8.0" }, "funding": [ { - "url": "https://opencollective.com/reactphp", - "type": "open_collective" + "url": "https://github.com/WyriHaximus", + "type": "github" + }, + { + "url": "https://github.com/clue", + "type": "github" } ], - "time": "2024-05-24T10:39:05+00:00" + "time": "2021-12-06T11:08:48+00:00" }, { "name": "react/socket", - "version": "v1.16.0", + "version": "v1.11.0", "source": { "type": "git", "url": "https://github.com/reactphp/socket.git", - "reference": "23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1" + "reference": "f474156aaab4f09041144fa8b57c7d70aed32a1c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/socket/zipball/23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1", - "reference": "23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1", + "url": "https://api.github.com/repos/reactphp/socket/zipball/f474156aaab4f09041144fa8b57c7d70aed32a1c", + "reference": "f474156aaab4f09041144fa8b57c7d70aed32a1c", "shasum": "" }, "require": { "evenement/evenement": "^3.0 || ^2.0 || ^1.0", "php": ">=5.3.0", - "react/dns": "^1.13", + "react/dns": "^1.8", "react/event-loop": "^1.2", - "react/promise": "^3.2 || ^2.6 || ^1.2.1", - "react/stream": "^1.4" + "react/promise": "^2.6.0 || ^1.2.1", + "react/promise-timer": "^1.8", + "react/stream": "^1.2" }, "require-dev": { - "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", - "react/async": "^4.3 || ^3.3 || ^2", - "react/promise-stream": "^1.4", - "react/promise-timer": "^1.11" + "clue/block-react": "^1.5", + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35", + "react/promise-stream": "^1.2" }, "type": "library", "autoload": { "psr-4": { - "React\\Socket\\": "src/" + "React\\Socket\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -734,28 +924,32 @@ ], "support": { "issues": "https://github.com/reactphp/socket/issues", - "source": "https://github.com/reactphp/socket/tree/v1.16.0" + "source": "https://github.com/reactphp/socket/tree/v1.11.0" }, "funding": [ { - "url": "https://opencollective.com/reactphp", - "type": "open_collective" + "url": "https://github.com/WyriHaximus", + "type": "github" + }, + { + "url": "https://github.com/clue", + "type": "github" } ], - "time": "2024-07-26T10:38:09+00:00" + "time": "2022-01-14T10:14:32+00:00" }, { "name": "react/stream", - "version": "v1.4.0", + "version": "v1.2.0", "source": { "type": "git", "url": "https://github.com/reactphp/stream.git", - "reference": "1e5b0acb8fe55143b5b426817155190eb6f5b18d" + "reference": "7a423506ee1903e89f1e08ec5f0ed430ff784ae9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/stream/zipball/1e5b0acb8fe55143b5b426817155190eb6f5b18d", - "reference": "1e5b0acb8fe55143b5b426817155190eb6f5b18d", + "url": "https://api.github.com/repos/reactphp/stream/zipball/7a423506ee1903e89f1e08ec5f0ed430ff784ae9", + "reference": "7a423506ee1903e89f1e08ec5f0ed430ff784ae9", "shasum": "" }, "require": { @@ -765,12 +959,12 @@ }, "require-dev": { "clue/stream-filter": "~1.2", - "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35" }, "type": "library", "autoload": { "psr-4": { - "React\\Stream\\": "src/" + "React\\Stream\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -812,28 +1006,93 @@ ], "support": { "issues": "https://github.com/reactphp/stream/issues", - "source": "https://github.com/reactphp/stream/tree/v1.4.0" + "source": "https://github.com/reactphp/stream/tree/v1.2.0" }, "funding": [ { - "url": "https://opencollective.com/reactphp", - "type": "open_collective" + "url": "https://github.com/WyriHaximus", + "type": "github" + }, + { + "url": "https://github.com/clue", + "type": "github" + } + ], + "time": "2021-07-11T12:37:55+00:00" + }, + { + "name": "ringcentral/psr7", + "version": "1.3.0", + "source": { + "type": "git", + "url": "https://github.com/ringcentral/psr7.git", + "reference": "360faaec4b563958b673fb52bbe94e37f14bc686" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ringcentral/psr7/zipball/360faaec4b563958b673fb52bbe94e37f14bc686", + "reference": "360faaec4b563958b673fb52bbe94e37f14bc686", + "shasum": "" + }, + "require": { + "php": ">=5.3", + "psr/http-message": "~1.0" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "RingCentral\\Psr7\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" } ], - "time": "2024-06-11T12:45:25+00:00" + "description": "PSR-7 message implementation", + "keywords": [ + "http", + "message", + "stream", + "uri" + ], + "support": { + "source": "https://github.com/ringcentral/psr7/tree/master" + }, + "time": "2018-05-29T20:21:04+00:00" }, { "name": "symfony/console", - "version": "v5.4.44", + "version": "v5.4.17", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "5b5a0aa66e3296e303e22490f90f521551835a83" + "reference": "58422fdcb0e715ed05b385f70d3e8b5ed4bbd45f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/5b5a0aa66e3296e303e22490f90f521551835a83", - "reference": "5b5a0aa66e3296e303e22490f90f521551835a83", + "url": "https://api.github.com/repos/symfony/console/zipball/58422fdcb0e715ed05b385f70d3e8b5ed4bbd45f", + "reference": "58422fdcb0e715ed05b385f70d3e8b5ed4bbd45f", "shasum": "" }, "require": { @@ -898,12 +1157,12 @@ "homepage": "https://symfony.com", "keywords": [ "cli", - "command-line", + "command line", "console", "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v5.4.44" + "source": "https://github.com/symfony/console/tree/v5.4.17" }, "funding": [ { @@ -919,29 +1178,29 @@ "type": "tidelift" } ], - "time": "2024-09-20T07:56:40+00:00" + "time": "2022-12-28T14:15:31+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v3.5.0", + "version": "v2.5.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1" + "reference": "6f981ee24cf69ee7ce9736146d1c57c2780598a8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", - "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/6f981ee24cf69ee7ce9736146d1c57c2780598a8", + "reference": "6f981ee24cf69ee7ce9736146d1c57c2780598a8", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=7.1" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.5-dev" + "dev-main": "2.5-dev" }, "thanks": { "name": "symfony/contracts", @@ -970,7 +1229,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.0" }, "funding": [ { @@ -986,24 +1245,24 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2021-07-12T14:48:14+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.31.0", + "version": "v1.25.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" + "reference": "30885182c981ab175d4d034db0f6f469898070ab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", - "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/30885182c981ab175d4d034db0f6f469898070ab", + "reference": "30885182c981ab175d4d034db0f6f469898070ab", "shasum": "" }, "require": { - "php": ">=7.2" + "php": ">=7.1" }, "provide": { "ext-ctype": "*" @@ -1013,6 +1272,9 @@ }, "type": "library", "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -1049,7 +1311,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.25.0" }, "funding": [ { @@ -1065,30 +1327,33 @@ "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2021-10-20T20:35:02+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.31.0", + "version": "v1.25.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe" + "reference": "81b86b50cf841a64252b439e738e97f4a34e2783" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", - "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/81b86b50cf841a64252b439e738e97f4a34e2783", + "reference": "81b86b50cf841a64252b439e738e97f4a34e2783", "shasum": "" }, "require": { - "php": ">=7.2" + "php": ">=7.1" }, "suggest": { "ext-intl": "For best performance" }, "type": "library", "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -1127,7 +1392,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.25.0" }, "funding": [ { @@ -1143,30 +1408,33 @@ "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2021-11-23T21:10:46+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.31.0", + "version": "v1.25.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "3833d7255cc303546435cb650316bff708a1c75c" + "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", - "reference": "3833d7255cc303546435cb650316bff708a1c75c", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8590a5f561694770bdcd3f9b5c69dde6945028e8", + "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8", "shasum": "" }, "require": { - "php": ">=7.2" + "php": ">=7.1" }, "suggest": { "ext-intl": "For best performance" }, "type": "library", "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -1208,7 +1476,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.25.0" }, "funding": [ { @@ -1224,24 +1492,24 @@ "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2021-02-19T12:13:01+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.31.0", + "version": "v1.25.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" + "reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", - "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/0abb51d2f102e00a4eefcf46ba7fec406d245825", + "reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825", "shasum": "" }, "require": { - "php": ">=7.2" + "php": ">=7.1" }, "provide": { "ext-mbstring": "*" @@ -1251,6 +1519,9 @@ }, "type": "library", "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -1288,7 +1559,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.25.0" }, "funding": [ { @@ -1304,27 +1575,30 @@ "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2021-11-30T18:21:41+00:00" }, { "name": "symfony/polyfill-php73", - "version": "v1.31.0", + "version": "v1.25.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb" + "reference": "cc5db0e22b3cb4111010e48785a97f670b350ca5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/0f68c03565dcaaf25a890667542e8bd75fe7e5bb", - "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/cc5db0e22b3cb4111010e48785a97f670b350ca5", + "reference": "cc5db0e22b3cb4111010e48785a97f670b350ca5", "shasum": "" }, "require": { - "php": ">=7.2" + "php": ">=7.1" }, "type": "library", "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -1364,7 +1638,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-php73/tree/v1.25.0" }, "funding": [ { @@ -1380,27 +1654,30 @@ "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2021-06-05T21:20:04+00:00" }, { "name": "symfony/polyfill-php80", - "version": "v1.31.0", + "version": "v1.25.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8" + "reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", - "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/4407588e0d3f1f52efb65fbe92babe41f37fe50c", + "reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c", "shasum": "" }, "require": { - "php": ">=7.2" + "php": ">=7.1" }, "type": "library", "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -1444,7 +1721,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.25.0" }, "funding": [ { @@ -1460,27 +1737,30 @@ "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2022-03-04T08:16:47+00:00" }, { "name": "symfony/polyfill-php81", - "version": "v1.31.0", + "version": "v1.26.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php81.git", - "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c" + "reference": "13f6d1271c663dc5ae9fb843a8f16521db7687a1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", - "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/13f6d1271c663dc5ae9fb843a8f16521db7687a1", + "reference": "13f6d1271c663dc5ae9fb843a8f16521db7687a1", "shasum": "" }, "require": { - "php": ">=7.2" + "php": ">=7.1" }, "type": "library", "extra": { + "branch-alias": { + "dev-main": "1.26-dev" + }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -1520,7 +1800,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-php81/tree/v1.26.0" }, "funding": [ { @@ -1536,20 +1816,20 @@ "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2022-05-24T11:49:31+00:00" }, { "name": "symfony/process", - "version": "v5.4.44", + "version": "v5.4.5", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "1b9fa82b5c62cd49da8c9e3952dd8531ada65096" + "reference": "95440409896f90a5f85db07a32b517ecec17fa4c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/1b9fa82b5c62cd49da8c9e3952dd8531ada65096", - "reference": "1b9fa82b5c62cd49da8c9e3952dd8531ada65096", + "url": "https://api.github.com/repos/symfony/process/zipball/95440409896f90a5f85db07a32b517ecec17fa4c", + "reference": "95440409896f90a5f85db07a32b517ecec17fa4c", "shasum": "" }, "require": { @@ -1582,7 +1862,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v5.4.44" + "source": "https://github.com/symfony/process/tree/v5.4.5" }, "funding": [ { @@ -1598,34 +1878,37 @@ "type": "tidelift" } ], - "time": "2024-09-17T12:46:43+00:00" + "time": "2022-01-30T18:16:22+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.5.0", + "version": "v2.5.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f" + "reference": "1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", - "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc", + "reference": "1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc", "shasum": "" }, "require": { - "php": ">=8.1", - "psr/container": "^1.1|^2.0", - "symfony/deprecation-contracts": "^2.5|^3" + "php": ">=7.2.5", + "psr/container": "^1.1", + "symfony/deprecation-contracts": "^2.1" }, "conflict": { "ext-psr": "<1.1|>=2" }, + "suggest": { + "symfony/service-implementation": "" + }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.5-dev" + "dev-main": "2.5-dev" }, "thanks": { "name": "symfony/contracts", @@ -1635,10 +1918,7 @@ "autoload": { "psr-4": { "Symfony\\Contracts\\Service\\": "" - }, - "exclude-from-classmap": [ - "/Test/" - ] + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1665,7 +1945,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/service-contracts/tree/v2.5.0" }, "funding": [ { @@ -1681,38 +1961,38 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2021-11-04T16:48:04+00:00" }, { "name": "symfony/string", - "version": "v6.4.12", + "version": "v5.4.3", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "f8a1ccebd0997e16112dfecfd74220b78e5b284b" + "reference": "92043b7d8383e48104e411bc9434b260dbeb5a10" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/f8a1ccebd0997e16112dfecfd74220b78e5b284b", - "reference": "f8a1ccebd0997e16112dfecfd74220b78e5b284b", + "url": "https://api.github.com/repos/symfony/string/zipball/92043b7d8383e48104e411bc9434b260dbeb5a10", + "reference": "92043b7d8383e48104e411bc9434b260dbeb5a10", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=7.2.5", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-intl-grapheme": "~1.0", "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0" + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php80": "~1.15" }, "conflict": { - "symfony/translation-contracts": "<2.5" + "symfony/translation-contracts": ">=3.0" }, "require-dev": { - "symfony/error-handler": "^5.4|^6.0|^7.0", - "symfony/http-client": "^5.4|^6.0|^7.0", - "symfony/intl": "^6.2|^7.0", - "symfony/translation-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^5.4|^6.0|^7.0" + "symfony/error-handler": "^4.4|^5.0|^6.0", + "symfony/http-client": "^4.4|^5.0|^6.0", + "symfony/translation-contracts": "^1.1|^2", + "symfony/var-exporter": "^4.4|^5.0|^6.0" }, "type": "library", "autoload": { @@ -1751,7 +2031,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.4.12" + "source": "https://github.com/symfony/string/tree/v5.4.3" }, "funding": [ { @@ -1767,20 +2047,20 @@ "type": "tidelift" } ], - "time": "2024-09-20T08:15:52+00:00" + "time": "2022-01-02T09:53:40+00:00" }, { "name": "symfony/yaml", - "version": "v5.4.44", + "version": "v5.4.3", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "7025b964f123bbf1896d7563db6ec7f1f63e918a" + "reference": "e80f87d2c9495966768310fc531b487ce64237a2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/7025b964f123bbf1896d7563db6ec7f1f63e918a", - "reference": "7025b964f123bbf1896d7563db6ec7f1f63e918a", + "url": "https://api.github.com/repos/symfony/yaml/zipball/e80f87d2c9495966768310fc531b487ce64237a2", + "reference": "e80f87d2c9495966768310fc531b487ce64237a2", "shasum": "" }, "require": { @@ -1826,7 +2106,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v5.4.44" + "source": "https://github.com/symfony/yaml/tree/v5.4.3" }, "funding": [ { @@ -1842,16 +2122,2777 @@ "type": "tidelift" } ], - "time": "2024-09-16T14:36:56+00:00" + "time": "2022-01-26T16:32:32+00:00" + } + ], + "packages-dev": [ + { + "name": "dealerdirect/phpcodesniffer-composer-installer", + "version": "v0.7.2", + "source": { + "type": "git", + "url": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer.git", + "reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db", + "reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0 || ^2.0", + "php": ">=5.3", + "squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0" + }, + "require-dev": { + "composer/composer": "*", + "php-parallel-lint/php-parallel-lint": "^1.3.1", + "phpcompatibility/php-compatibility": "^9.0" + }, + "type": "composer-plugin", + "extra": { + "class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" + }, + "autoload": { + "psr-4": { + "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Franck Nijhof", + "email": "franck.nijhof@dealerdirect.com", + "homepage": "http://www.frenck.nl", + "role": "Developer / IT Manager" + }, + { + "name": "Contributors", + "homepage": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer/graphs/contributors" + } + ], + "description": "PHP_CodeSniffer Standards Composer Installer Plugin", + "homepage": "http://www.dealerdirect.com", + "keywords": [ + "PHPCodeSniffer", + "PHP_CodeSniffer", + "code quality", + "codesniffer", + "composer", + "installer", + "phpcbf", + "phpcs", + "plugin", + "qa", + "quality", + "standard", + "standards", + "style guide", + "stylecheck", + "tests" + ], + "support": { + "issues": "https://github.com/dealerdirect/phpcodesniffer-composer-installer/issues", + "source": "https://github.com/dealerdirect/phpcodesniffer-composer-installer" + }, + "time": "2022-02-04T12:51:07+00:00" + }, + { + "name": "doctrine/instantiator", + "version": "1.4.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc", + "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9", + "ext-pdo": "*", + "ext-phar": "*", + "phpbench/phpbench": "^0.16 || ^1", + "phpstan/phpstan": "^1.4", + "phpstan/phpstan-phpunit": "^1", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "vimeo/psalm": "^4.22" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "https://ocramius.github.io/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", + "keywords": [ + "constructor", + "instantiate" + ], + "support": { + "issues": "https://github.com/doctrine/instantiator/issues", + "source": "https://github.com/doctrine/instantiator/tree/1.4.1" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", + "type": "tidelift" + } + ], + "time": "2022-03-03T08:28:38+00:00" + }, + { + "name": "facade/ignition-contracts", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/facade/ignition-contracts.git", + "reference": "3c921a1cdba35b68a7f0ccffc6dffc1995b18267" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/facade/ignition-contracts/zipball/3c921a1cdba35b68a7f0ccffc6dffc1995b18267", + "reference": "3c921a1cdba35b68a7f0ccffc6dffc1995b18267", + "shasum": "" + }, + "require": { + "php": "^7.3|^8.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^v2.15.8", + "phpunit/phpunit": "^9.3.11", + "vimeo/psalm": "^3.17.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Facade\\IgnitionContracts\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "homepage": "https://flareapp.io", + "role": "Developer" + } + ], + "description": "Solution contracts for Ignition", + "homepage": "https://github.com/facade/ignition-contracts", + "keywords": [ + "contracts", + "flare", + "ignition" + ], + "support": { + "issues": "https://github.com/facade/ignition-contracts/issues", + "source": "https://github.com/facade/ignition-contracts/tree/1.0.2" + }, + "time": "2020-10-16T08:27:54+00:00" + }, + { + "name": "filp/whoops", + "version": "2.14.5", + "source": { + "type": "git", + "url": "https://github.com/filp/whoops.git", + "reference": "a63e5e8f26ebbebf8ed3c5c691637325512eb0dc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/filp/whoops/zipball/a63e5e8f26ebbebf8ed3c5c691637325512eb0dc", + "reference": "a63e5e8f26ebbebf8ed3c5c691637325512eb0dc", + "shasum": "" + }, + "require": { + "php": "^5.5.9 || ^7.0 || ^8.0", + "psr/log": "^1.0.1 || ^2.0 || ^3.0" + }, + "require-dev": { + "mockery/mockery": "^0.9 || ^1.0", + "phpunit/phpunit": "^4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.8 || ^9.3.3", + "symfony/var-dumper": "^2.6 || ^3.0 || ^4.0 || ^5.0" + }, + "suggest": { + "symfony/var-dumper": "Pretty print complex values better with var-dumper available", + "whoops/soap": "Formats errors as SOAP responses" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Whoops\\": "src/Whoops/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Filipe Dobreira", + "homepage": "https://github.com/filp", + "role": "Developer" + } + ], + "description": "php error handling for cool kids", + "homepage": "https://filp.github.io/whoops/", + "keywords": [ + "error", + "exception", + "handling", + "library", + "throwable", + "whoops" + ], + "support": { + "issues": "https://github.com/filp/whoops/issues", + "source": "https://github.com/filp/whoops/tree/2.14.5" + }, + "funding": [ + { + "url": "https://github.com/denis-sokolov", + "type": "github" + } + ], + "time": "2022-01-07T12:00:00+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.11.0", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/14daed4296fae74d9e3201d2c4925d1acb7aa614", + "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3,<3.2.2" + }, + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + }, + "type": "library", + "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.11.0" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2022-03-03T13:19:32+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v4.13.2", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "210577fe3cf7badcc5814d99455df46564f3c077" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/210577fe3cf7badcc5814d99455df46564f3c077", + "reference": "210577fe3cf7badcc5814d99455df46564f3c077", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=7.0" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.9-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v4.13.2" + }, + "time": "2021-11-30T19:35:32+00:00" + }, + { + "name": "nunomaduro/collision", + "version": "v5.11.0", + "source": { + "type": "git", + "url": "https://github.com/nunomaduro/collision.git", + "reference": "8b610eef8582ccdc05d8f2ab23305e2d37049461" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/8b610eef8582ccdc05d8f2ab23305e2d37049461", + "reference": "8b610eef8582ccdc05d8f2ab23305e2d37049461", + "shasum": "" + }, + "require": { + "facade/ignition-contracts": "^1.0", + "filp/whoops": "^2.14.3", + "php": "^7.3 || ^8.0", + "symfony/console": "^5.0" + }, + "require-dev": { + "brianium/paratest": "^6.1", + "fideloper/proxy": "^4.4.1", + "fruitcake/laravel-cors": "^2.0.3", + "laravel/framework": "8.x-dev", + "nunomaduro/larastan": "^0.6.2", + "nunomaduro/mock-final-classes": "^1.0", + "orchestra/testbench": "^6.0", + "phpstan/phpstan": "^0.12.64", + "phpunit/phpunit": "^9.5.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "NunoMaduro\\Collision\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "Cli error handling for console/command-line PHP applications.", + "keywords": [ + "artisan", + "cli", + "command-line", + "console", + "error", + "handling", + "laravel", + "laravel-zero", + "php", + "symfony" + ], + "support": { + "issues": "https://github.com/nunomaduro/collision/issues", + "source": "https://github.com/nunomaduro/collision" + }, + "funding": [ + { + "url": "https://www.paypal.com/paypalme/enunomaduro", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + }, + { + "url": "https://www.patreon.com/nunomaduro", + "type": "patreon" + } + ], + "time": "2022-01-10T16:22:52+00:00" + }, + { + "name": "pestphp/pest", + "version": "v1.21.2", + "source": { + "type": "git", + "url": "https://github.com/pestphp/pest.git", + "reference": "63f009fadf9b37f611fda43928d03336475d5d9f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pestphp/pest/zipball/63f009fadf9b37f611fda43928d03336475d5d9f", + "reference": "63f009fadf9b37f611fda43928d03336475d5d9f", + "shasum": "" + }, + "require": { + "nunomaduro/collision": "^5.10.0|^6.0", + "pestphp/pest-plugin": "^1.0.0", + "php": "^7.3 || ^8.0", + "phpunit/phpunit": "^9.5.5" + }, + "require-dev": { + "illuminate/console": "^8.47.0", + "illuminate/support": "^8.47.0", + "laravel/dusk": "^6.15.0", + "pestphp/pest-dev-tools": "dev-master", + "pestphp/pest-plugin-parallel": "^1.0" + }, + "bin": [ + "bin/pest" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + }, + "pest": { + "plugins": [ + "Pest\\Plugins\\Coverage", + "Pest\\Plugins\\Init", + "Pest\\Plugins\\Version", + "Pest\\Plugins\\Environment" + ] + }, + "laravel": { + "providers": [ + "Pest\\Laravel\\PestServiceProvider" + ] + } + }, + "autoload": { + "files": [ + "src/Functions.php", + "src/Pest.php" + ], + "psr-4": { + "Pest\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "An elegant PHP Testing Framework.", + "keywords": [ + "framework", + "pest", + "php", + "test", + "testing", + "unit" + ], + "support": { + "issues": "https://github.com/pestphp/pest/issues", + "source": "https://github.com/pestphp/pest/tree/v1.21.2" + }, + "funding": [ + { + "url": "https://www.paypal.com/paypalme/enunomaduro", + "type": "custom" + }, + { + "url": "https://github.com/lukeraymonddowning", + "type": "github" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + }, + { + "url": "https://github.com/octoper", + "type": "github" + }, + { + "url": "https://github.com/olivernybroe", + "type": "github" + }, + { + "url": "https://github.com/owenvoke", + "type": "github" + }, + { + "url": "https://www.patreon.com/nunomaduro", + "type": "patreon" + } + ], + "time": "2022-03-05T19:34:40+00:00" + }, + { + "name": "pestphp/pest-plugin", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/pestphp/pest-plugin.git", + "reference": "fc8519de148699fe612d9c669be60554cd2db4fa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pestphp/pest-plugin/zipball/fc8519de148699fe612d9c669be60554cd2db4fa", + "reference": "fc8519de148699fe612d9c669be60554cd2db4fa", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.1 || ^2.0", + "php": "^7.3 || ^8.0" + }, + "conflict": { + "pestphp/pest": "<1.0" + }, + "require-dev": { + "composer/composer": "^1.10.19", + "pestphp/pest": "^1.0", + "pestphp/pest-dev-tools": "dev-master" + }, + "type": "composer-plugin", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + }, + "class": "Pest\\Plugin\\Manager" + }, + "autoload": { + "psr-4": { + "Pest\\Plugin\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "The Pest plugin manager", + "keywords": [ + "framework", + "manager", + "pest", + "php", + "plugin", + "test", + "testing", + "unit" + ], + "support": { + "source": "https://github.com/pestphp/pest-plugin/tree/v1.0.0" + }, + "funding": [ + { + "url": "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=66BYDWAT92N6L", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + }, + { + "url": "https://www.patreon.com/nunomaduro", + "type": "patreon" + } + ], + "time": "2021-01-03T15:53:42+00:00" + }, + { + "name": "phar-io/manifest", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.3" + }, + "time": "2021-07-20T11:28:43+00:00" + }, + { + "name": "phar-io/version", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" + }, + { + "name": "phpdocumentor/reflection-common", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-2.x": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", + "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" + }, + "time": "2020-06-27T09:03:43+00:00" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "5.3.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "622548b623e81ca6d78b721c5e029f4ce664f170" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170", + "reference": "622548b623e81ca6d78b721c5e029f4ce664f170", + "shasum": "" + }, + "require": { + "ext-filter": "*", + "php": "^7.2 || ^8.0", + "phpdocumentor/reflection-common": "^2.2", + "phpdocumentor/type-resolver": "^1.3", + "webmozart/assert": "^1.9.1" + }, + "require-dev": { + "mockery/mockery": "~1.3.2", + "psalm/phar": "^4.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + }, + { + "name": "Jaap van Otterdijk", + "email": "account@ijaap.nl" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.3.0" + }, + "time": "2021-10-19T17:43:47+00:00" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "1.6.1", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "77a32518733312af16a44300404e945338981de3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/77a32518733312af16a44300404e945338981de3", + "reference": "77a32518733312af16a44300404e945338981de3", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0", + "phpdocumentor/reflection-common": "^2.0" + }, + "require-dev": { + "ext-tokenizer": "*", + "psalm/phar": "^4.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-1.x": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", + "support": { + "issues": "https://github.com/phpDocumentor/TypeResolver/issues", + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.6.1" + }, + "time": "2022-03-15T21:29:03+00:00" + }, + { + "name": "phpspec/prophecy", + "version": "v1.16.0", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy.git", + "reference": "be8cac52a0827776ff9ccda8c381ac5b71aeb359" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/be8cac52a0827776ff9ccda8c381ac5b71aeb359", + "reference": "be8cac52a0827776ff9ccda8c381ac5b71aeb359", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.2", + "php": "^7.2 || 8.0.* || 8.1.* || 8.2.*", + "phpdocumentor/reflection-docblock": "^5.2", + "sebastian/comparator": "^3.0 || ^4.0", + "sebastian/recursion-context": "^3.0 || ^4.0" + }, + "require-dev": { + "phpspec/phpspec": "^6.0 || ^7.0", + "phpunit/phpunit": "^8.0 || ^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Prophecy\\": "src/Prophecy" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + }, + { + "name": "Marcello Duarte", + "email": "marcello.duarte@gmail.com" + } + ], + "description": "Highly opinionated mocking framework for PHP 5.3+", + "homepage": "https://github.com/phpspec/prophecy", + "keywords": [ + "Double", + "Dummy", + "fake", + "mock", + "spy", + "stub" + ], + "support": { + "issues": "https://github.com/phpspec/prophecy/issues", + "source": "https://github.com/phpspec/prophecy/tree/v1.16.0" + }, + "time": "2022-11-29T15:06:56+00:00" + }, + { + "name": "phpstan/phpdoc-parser", + "version": "1.4.2", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpdoc-parser.git", + "reference": "4cb3021a4e10ffe3d5f94a4c34cf4b3f6de2fa3d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/4cb3021a4e10ffe3d5f94a4c34cf4b3f6de2fa3d", + "reference": "4cb3021a4e10ffe3d5f94a4c34cf4b3f6de2fa3d", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^1.5", + "phpstan/phpstan-strict-rules": "^1.0", + "phpunit/phpunit": "^9.5", + "symfony/process": "^5.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "PHPStan\\PhpDocParser\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPDoc parser with support for nullable, intersection and generic types", + "support": { + "issues": "https://github.com/phpstan/phpdoc-parser/issues", + "source": "https://github.com/phpstan/phpdoc-parser/tree/1.4.2" + }, + "time": "2022-03-30T13:33:37+00:00" + }, + { + "name": "phpstan/phpstan", + "version": "1.4.10", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "898c479c39caa727bedf4311dd294a8f4e250e72" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/898c479c39caa727bedf4311dd294a8f4e250e72", + "reference": "898c479c39caa727bedf4311dd294a8f4e250e72", + "shasum": "" + }, + "require": { + "php": "^7.1|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "support": { + "issues": "https://github.com/phpstan/phpstan/issues", + "source": "https://github.com/phpstan/phpstan/tree/1.4.10" + }, + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" + }, + { + "url": "https://www.patreon.com/phpstan", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", + "type": "tidelift" + } + ], + "time": "2022-03-14T10:25:45+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "9.2.15", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "2e9da11878c4202f97915c1cb4bb1ca318a63f5f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2e9da11878c4202f97915c1cb4bb1ca318a63f5f", + "reference": "2e9da11878c4202f97915c1cb4bb1ca318a63f5f", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^4.13.0", + "php": ">=7.3", + "phpunit/php-file-iterator": "^3.0.3", + "phpunit/php-text-template": "^2.0.2", + "sebastian/code-unit-reverse-lookup": "^2.0.2", + "sebastian/complexity": "^2.0", + "sebastian/environment": "^5.1.2", + "sebastian/lines-of-code": "^1.0.3", + "sebastian/version": "^3.0.1", + "theseer/tokenizer": "^1.2.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-pcov": "*", + "ext-xdebug": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.15" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-03-07T09:28:20+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "3.0.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2021-12-02T12:48:52+00:00" + }, + { + "name": "phpunit/php-invoker", + "version": "3.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-pcntl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:58:55+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T05:33:50+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "5.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:16:10+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "9.5.20", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "12bc8879fb65aef2138b26fc633cb1e3620cffba" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/12bc8879fb65aef2138b26fc633cb1e3620cffba", + "reference": "12bc8879fb65aef2138b26fc633cb1e3620cffba", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.3.1", + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.10.1", + "phar-io/manifest": "^2.0.3", + "phar-io/version": "^3.0.2", + "php": ">=7.3", + "phpspec/prophecy": "^1.12.1", + "phpunit/php-code-coverage": "^9.2.13", + "phpunit/php-file-iterator": "^3.0.5", + "phpunit/php-invoker": "^3.1.1", + "phpunit/php-text-template": "^2.0.3", + "phpunit/php-timer": "^5.0.2", + "sebastian/cli-parser": "^1.0.1", + "sebastian/code-unit": "^1.0.6", + "sebastian/comparator": "^4.0.5", + "sebastian/diff": "^4.0.3", + "sebastian/environment": "^5.1.3", + "sebastian/exporter": "^4.0.3", + "sebastian/global-state": "^5.0.1", + "sebastian/object-enumerator": "^4.0.3", + "sebastian/resource-operations": "^3.0.3", + "sebastian/type": "^3.0", + "sebastian/version": "^3.0.2" + }, + "require-dev": { + "ext-pdo": "*", + "phpspec/prophecy-phpunit": "^2.0.1" + }, + "suggest": { + "ext-soap": "*", + "ext-xdebug": "*" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.5-dev" + } + }, + "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.20" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-04-01T12:37:26+00:00" + }, + { + "name": "psr/log", + "version": "1.1.4", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/1.1.4" + }, + "time": "2021-05-03T11:20:27+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", + "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:08:49+00:00" + }, + { + "name": "sebastian/code-unit", + "version": "1.0.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:08:54+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:30:19+00:00" + }, + { + "name": "sebastian/comparator", + "version": "4.0.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "55f4261989e546dc112258c7a75935a81a7ce382" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55f4261989e546dc112258c7a75935a81a7ce382", + "reference": "55f4261989e546dc112258c7a75935a81a7ce382", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/diff": "^4.0", + "sebastian/exporter": "^4.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.6" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T15:49:45+00:00" + }, + { + "name": "sebastian/complexity", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "739b35e53379900cc9ac327b2147867b8b6efd88" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88", + "reference": "739b35e53379900cc9ac327b2147867b8b6efd88", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.7", + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T15:52:27+00:00" + }, + { + "name": "sebastian/diff", + "version": "4.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d", + "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3", + "symfony/process": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "source": "https://github.com/sebastianbergmann/diff/tree/4.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:10:38+00:00" + }, + { + "name": "sebastian/environment", + "version": "5.1.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "388b6ced16caa751030f6a69e588299fa09200ac" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/388b6ced16caa751030f6a69e588299fa09200ac", + "reference": "388b6ced16caa751030f6a69e588299fa09200ac", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "source": "https://github.com/sebastianbergmann/environment/tree/5.1.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:52:38+00:00" + }, + { + "name": "sebastian/exporter", + "version": "4.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/65e8b7db476c5dd267e65eea9cab77584d3cfff9", + "reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "ext-mbstring": "*", + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2021-11-11T14:18:36+00:00" + }, + { + "name": "sebastian/global-state", + "version": "5.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2", + "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-02-14T08:28:10+00:00" + }, + { + "name": "sebastian/lines-of-code", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc", + "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.6", + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-28T06:42:11+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "4.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:12:34+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:14:26+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "4.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172", + "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:17:30+00:00" + }, + { + "name": "sebastian/resource-operations", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", + "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "support": { + "issues": "https://github.com/sebastianbergmann/resource-operations/issues", + "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:45:17+00:00" + }, + { + "name": "sebastian/type", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "b233b84bc4465aff7b57cf1c4bc75c86d00d6dad" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/b233b84bc4465aff7b57cf1c4bc75c86d00d6dad", + "reference": "b233b84bc4465aff7b57cf1c4bc75c86d00d6dad", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "source": "https://github.com/sebastianbergmann/type/tree/3.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-03-15T09:54:48+00:00" + }, + { + "name": "sebastian/version", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c6c1022351a901512170118436c764e473f6de8c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", + "reference": "c6c1022351a901512170118436c764e473f6de8c", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:39:44+00:00" + }, + { + "name": "slevomat/coding-standard", + "version": "7.1", + "source": { + "type": "git", + "url": "https://github.com/slevomat/coding-standard.git", + "reference": "b521bd358b5f7a7d69e9637fd139e036d8adeb6f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/b521bd358b5f7a7d69e9637fd139e036d8adeb6f", + "reference": "b521bd358b5f7a7d69e9637fd139e036d8adeb6f", + "shasum": "" + }, + "require": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7", + "php": "^7.2 || ^8.0", + "phpstan/phpdoc-parser": "^1.4.1", + "squizlabs/php_codesniffer": "^3.6.2" + }, + "require-dev": { + "phing/phing": "2.17.2", + "php-parallel-lint/php-parallel-lint": "1.3.2", + "phpstan/phpstan": "1.4.10|1.5.2", + "phpstan/phpstan-deprecation-rules": "1.0.0", + "phpstan/phpstan-phpunit": "1.0.0|1.1.0", + "phpstan/phpstan-strict-rules": "1.1.0", + "phpunit/phpunit": "7.5.20|8.5.21|9.5.19" + }, + "type": "phpcodesniffer-standard", + "extra": { + "branch-alias": { + "dev-master": "7.x-dev" + } + }, + "autoload": { + "psr-4": { + "SlevomatCodingStandard\\": "SlevomatCodingStandard" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.", + "support": { + "issues": "https://github.com/slevomat/coding-standard/issues", + "source": "https://github.com/slevomat/coding-standard/tree/7.1" + }, + "funding": [ + { + "url": "https://github.com/kukulich", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/slevomat/coding-standard", + "type": "tidelift" + } + ], + "time": "2022-03-29T12:44:16+00:00" + }, + { + "name": "squizlabs/php_codesniffer", + "version": "3.6.2", + "source": { + "type": "git", + "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", + "reference": "5e4e71592f69da17871dba6e80dd51bce74a351a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/5e4e71592f69da17871dba6e80dd51bce74a351a", + "reference": "5e4e71592f69da17871dba6e80dd51bce74a351a", + "shasum": "" + }, + "require": { + "ext-simplexml": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" + }, + "bin": [ + "bin/phpcs", + "bin/phpcbf" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Greg Sherwood", + "role": "lead" + } + ], + "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", + "keywords": [ + "phpcs", + "standards" + ], + "support": { + "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", + "source": "https://github.com/squizlabs/PHP_CodeSniffer", + "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" + }, + "time": "2021-12-12T21:44:58+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.2.1" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2021-07-28T10:34:58+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.10.0", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/6964c76c7804814a842473e0c8fd15bab0f18e25", + "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.13" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.10.0" + }, + "time": "2021-03-09T10:59:23+00:00" } ], - "packages-dev": [], "aliases": [], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, - "platform": {}, - "platform-dev": {}, - "plugin-api-version": "2.6.0" + "platform": { + "php": "^8.0|^7.3", + "ext-json": "*" + }, + "platform-dev": [], + "plugin-api-version": "2.3.0" } diff --git a/deps/vendor/composer/autoload_classmap.php b/deps/vendor/composer/autoload_classmap.php index ac6b3995c..8d72fe0f8 100644 --- a/deps/vendor/composer/autoload_classmap.php +++ b/deps/vendor/composer/autoload_classmap.php @@ -7,7 +7,6 @@ return array( 'Attribute' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Attribute.php', - 'CURLStringFile' => $vendorDir . '/symfony/polyfill-php81/Resources/stubs/CURLStringFile.php', 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php', 'JsonException' => $vendorDir . '/symfony/polyfill-php73/Resources/stubs/JsonException.php', 'Normalizer' => $vendorDir . '/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php', diff --git a/deps/vendor/composer/autoload_files.php b/deps/vendor/composer/autoload_files.php index 229ea9427..684caeb1d 100644 --- a/deps/vendor/composer/autoload_files.php +++ b/deps/vendor/composer/autoload_files.php @@ -7,12 +7,15 @@ return array( 'ad155f8f1cf0d418fe49e248db8c661b' => $vendorDir . '/react/promise/src/functions_include.php', + '972fda704d680a3a53c68e34e193cb22' => $vendorDir . '/react/promise-timer/src/functions_include.php', '6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php', + 'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php', '320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php', '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php', '8825ede83f2f289127722d4e842cf7e8' => $vendorDir . '/symfony/polyfill-intl-grapheme/bootstrap.php', 'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php', - 'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php', + 'cea474b4340aa9fa53661e887a21a316' => $vendorDir . '/react/promise-stream/src/functions_include.php', + 'ebf8799635f67b5d7248946fe2154f4a' => $vendorDir . '/ringcentral/psr7/src/functions_include.php', '0d59ee240a4cd96ddbb4ff164fccea4d' => $vendorDir . '/symfony/polyfill-php73/bootstrap.php', 'b6b991a57620e2fb6b2f66f03fe9ddc2' => $vendorDir . '/symfony/string/Resources/functions.php', '23c18046f52bef3eea034657bafda50f' => $vendorDir . '/symfony/polyfill-php81/bootstrap.php', diff --git a/deps/vendor/composer/autoload_namespaces.php b/deps/vendor/composer/autoload_namespaces.php index 15a2ff3ad..11948b105 100644 --- a/deps/vendor/composer/autoload_namespaces.php +++ b/deps/vendor/composer/autoload_namespaces.php @@ -6,4 +6,5 @@ $baseDir = dirname($vendorDir); return array( + 'Evenement' => array($vendorDir . '/evenement/evenement/src'), ); diff --git a/deps/vendor/composer/autoload_psr4.php b/deps/vendor/composer/autoload_psr4.php index 017eb9a1e..c0b719960 100644 --- a/deps/vendor/composer/autoload_psr4.php +++ b/deps/vendor/composer/autoload_psr4.php @@ -18,8 +18,11 @@ 'Symfony\\Component\\String\\' => array($vendorDir . '/symfony/string'), 'Symfony\\Component\\Process\\' => array($vendorDir . '/symfony/process'), 'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'), + 'RingCentral\\Psr7\\' => array($vendorDir . '/ringcentral/psr7/src'), 'React\\Stream\\' => array($vendorDir . '/react/stream/src'), 'React\\Socket\\' => array($vendorDir . '/react/socket/src'), + 'React\\Promise\\Timer\\' => array($vendorDir . '/react/promise-timer/src'), + 'React\\Promise\\Stream\\' => array($vendorDir . '/react/promise-stream/src'), 'React\\Promise\\' => array($vendorDir . '/react/promise/src'), 'React\\Http\\' => array($vendorDir . '/react/http/src'), 'React\\EventLoop\\' => array($vendorDir . '/react/event-loop/src'), @@ -29,5 +32,4 @@ 'Psr\\Container\\' => array($vendorDir . '/psr/container/src'), 'JsonSchema\\' => array($vendorDir . '/justinrainbow/json-schema/src/JsonSchema'), 'Fig\\Http\\Message\\' => array($vendorDir . '/fig/http-message-util/src'), - 'Evenement\\' => array($vendorDir . '/evenement/evenement/src'), ); diff --git a/deps/vendor/composer/autoload_real.php b/deps/vendor/composer/autoload_real.php index 2150168fe..5492b3fc9 100644 --- a/deps/vendor/composer/autoload_real.php +++ b/deps/vendor/composer/autoload_real.php @@ -22,8 +22,6 @@ public static function getLoader() return self::$loader; } - require __DIR__ . '/platform_check.php'; - spl_autoload_register(array('ComposerAutoloaderInit6e0324fc886fd55694e53338d30399bc', 'loadClassLoader'), true, true); self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__)); spl_autoload_unregister(array('ComposerAutoloaderInit6e0324fc886fd55694e53338d30399bc', 'loadClassLoader')); diff --git a/deps/vendor/composer/autoload_static.php b/deps/vendor/composer/autoload_static.php index 251afdde6..853e559e5 100644 --- a/deps/vendor/composer/autoload_static.php +++ b/deps/vendor/composer/autoload_static.php @@ -8,12 +8,15 @@ class ComposerStaticInit6e0324fc886fd55694e53338d30399bc { public static $files = array ( 'ad155f8f1cf0d418fe49e248db8c661b' => __DIR__ . '/..' . '/react/promise/src/functions_include.php', + '972fda704d680a3a53c68e34e193cb22' => __DIR__ . '/..' . '/react/promise-timer/src/functions_include.php', '6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php', + 'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php', '320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php', '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php', '8825ede83f2f289127722d4e842cf7e8' => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme/bootstrap.php', 'e69f7f6ee287b969198c3c9d6777bd38' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php', - 'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php', + 'cea474b4340aa9fa53661e887a21a316' => __DIR__ . '/..' . '/react/promise-stream/src/functions_include.php', + 'ebf8799635f67b5d7248946fe2154f4a' => __DIR__ . '/..' . '/ringcentral/psr7/src/functions_include.php', '0d59ee240a4cd96ddbb4ff164fccea4d' => __DIR__ . '/..' . '/symfony/polyfill-php73/bootstrap.php', 'b6b991a57620e2fb6b2f66f03fe9ddc2' => __DIR__ . '/..' . '/symfony/string/Resources/functions.php', '23c18046f52bef3eea034657bafda50f' => __DIR__ . '/..' . '/symfony/polyfill-php81/bootstrap.php', @@ -37,8 +40,11 @@ class ComposerStaticInit6e0324fc886fd55694e53338d30399bc ), 'R' => array ( + 'RingCentral\\Psr7\\' => 17, 'React\\Stream\\' => 13, 'React\\Socket\\' => 13, + 'React\\Promise\\Timer\\' => 20, + 'React\\Promise\\Stream\\' => 21, 'React\\Promise\\' => 14, 'React\\Http\\' => 11, 'React\\EventLoop\\' => 16, @@ -58,10 +64,6 @@ class ComposerStaticInit6e0324fc886fd55694e53338d30399bc array ( 'Fig\\Http\\Message\\' => 17, ), - 'E' => - array ( - 'Evenement\\' => 10, - ), ); public static $prefixDirsPsr4 = array ( @@ -113,6 +115,10 @@ class ComposerStaticInit6e0324fc886fd55694e53338d30399bc array ( 0 => __DIR__ . '/..' . '/symfony/console', ), + 'RingCentral\\Psr7\\' => + array ( + 0 => __DIR__ . '/..' . '/ringcentral/psr7/src', + ), 'React\\Stream\\' => array ( 0 => __DIR__ . '/..' . '/react/stream/src', @@ -121,6 +127,14 @@ class ComposerStaticInit6e0324fc886fd55694e53338d30399bc array ( 0 => __DIR__ . '/..' . '/react/socket/src', ), + 'React\\Promise\\Timer\\' => + array ( + 0 => __DIR__ . '/..' . '/react/promise-timer/src', + ), + 'React\\Promise\\Stream\\' => + array ( + 0 => __DIR__ . '/..' . '/react/promise-stream/src', + ), 'React\\Promise\\' => array ( 0 => __DIR__ . '/..' . '/react/promise/src', @@ -157,15 +171,20 @@ class ComposerStaticInit6e0324fc886fd55694e53338d30399bc array ( 0 => __DIR__ . '/..' . '/fig/http-message-util/src', ), - 'Evenement\\' => + ); + + public static $prefixesPsr0 = array ( + 'E' => array ( - 0 => __DIR__ . '/..' . '/evenement/evenement/src', + 'Evenement' => + array ( + 0 => __DIR__ . '/..' . '/evenement/evenement/src', + ), ), ); public static $classMap = array ( 'Attribute' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Attribute.php', - 'CURLStringFile' => __DIR__ . '/..' . '/symfony/polyfill-php81/Resources/stubs/CURLStringFile.php', 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', 'JsonException' => __DIR__ . '/..' . '/symfony/polyfill-php73/Resources/stubs/JsonException.php', 'Normalizer' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php', @@ -181,6 +200,7 @@ public static function getInitializer(ClassLoader $loader) return \Closure::bind(function () use ($loader) { $loader->prefixLengthsPsr4 = ComposerStaticInit6e0324fc886fd55694e53338d30399bc::$prefixLengthsPsr4; $loader->prefixDirsPsr4 = ComposerStaticInit6e0324fc886fd55694e53338d30399bc::$prefixDirsPsr4; + $loader->prefixesPsr0 = ComposerStaticInit6e0324fc886fd55694e53338d30399bc::$prefixesPsr0; $loader->classMap = ComposerStaticInit6e0324fc886fd55694e53338d30399bc::$classMap; }, null, ClassLoader::class); diff --git a/deps/vendor/composer/installed.json b/deps/vendor/composer/installed.json index a36713f46..379a5f682 100644 --- a/deps/vendor/composer/installed.json +++ b/deps/vendor/composer/installed.json @@ -2,31 +2,31 @@ "packages": [ { "name": "evenement/evenement", - "version": "v3.0.2", - "version_normalized": "3.0.2.0", + "version": "v3.0.1", + "version_normalized": "3.0.1.0", "source": { "type": "git", "url": "https://github.com/igorw/evenement.git", - "reference": "0a16b0d71ab13284339abb99d9d2bd813640efbc" + "reference": "531bfb9d15f8aa57454f5f0285b18bec903b8fb7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/igorw/evenement/zipball/0a16b0d71ab13284339abb99d9d2bd813640efbc", - "reference": "0a16b0d71ab13284339abb99d9d2bd813640efbc", + "url": "https://api.github.com/repos/igorw/evenement/zipball/531bfb9d15f8aa57454f5f0285b18bec903b8fb7", + "reference": "531bfb9d15f8aa57454f5f0285b18bec903b8fb7", "shasum": "" }, "require": { "php": ">=7.0" }, "require-dev": { - "phpunit/phpunit": "^9 || ^6" + "phpunit/phpunit": "^6.0" }, - "time": "2023-08-08T05:53:35+00:00", + "time": "2017-07-23T21:35:13+00:00", "type": "library", "installation-source": "dist", "autoload": { - "psr-4": { - "Evenement\\": "src/" + "psr-0": { + "Evenement": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -46,7 +46,7 @@ ], "support": { "issues": "https://github.com/igorw/evenement/issues", - "source": "https://github.com/igorw/evenement/tree/v3.0.2" + "source": "https://github.com/igorw/evenement/tree/master" }, "install-path": "../evenement/evenement" }, @@ -111,32 +111,37 @@ }, { "name": "justinrainbow/json-schema", - "version": "5.3.0", - "version_normalized": "5.3.0.0", + "version": "5.2.11", + "version_normalized": "5.2.11.0", "source": { "type": "git", - "url": "https://github.com/jsonrainbow/json-schema.git", - "reference": "feb2ca6dd1cebdaf1ed60a4c8de2e53ce11c4fd8" + "url": "https://github.com/justinrainbow/json-schema.git", + "reference": "2ab6744b7296ded80f8cc4f9509abbff393399aa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/feb2ca6dd1cebdaf1ed60a4c8de2e53ce11c4fd8", - "reference": "feb2ca6dd1cebdaf1ed60a4c8de2e53ce11c4fd8", + "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/2ab6744b7296ded80f8cc4f9509abbff393399aa", + "reference": "2ab6744b7296ded80f8cc4f9509abbff393399aa", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=5.3.3" }, "require-dev": { "friendsofphp/php-cs-fixer": "~2.2.20||~2.15.1", "json-schema/json-schema-test-suite": "1.2.0", "phpunit/phpunit": "^4.8.35" }, - "time": "2024-07-06T21:00:26+00:00", + "time": "2021-07-22T09:24:00+00:00", "bin": [ "bin/validate-json" ], "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0.x-dev" + } + }, "installation-source": "dist", "autoload": { "psr-4": { @@ -172,36 +177,31 @@ "schema" ], "support": { - "issues": "https://github.com/jsonrainbow/json-schema/issues", - "source": "https://github.com/jsonrainbow/json-schema/tree/5.3.0" + "issues": "https://github.com/justinrainbow/json-schema/issues", + "source": "https://github.com/justinrainbow/json-schema/tree/5.2.11" }, "install-path": "../justinrainbow/json-schema" }, { "name": "psr/container", - "version": "2.0.2", - "version_normalized": "2.0.2.0", + "version": "1.1.1", + "version_normalized": "1.1.1.0", "source": { "type": "git", "url": "https://github.com/php-fig/container.git", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "url": "https://api.github.com/repos/php-fig/container/zipball/8622567409010282b7aeebe4bb841fe98b58dcaf", + "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf", "shasum": "" }, "require": { - "php": ">=7.4.0" + "php": ">=7.2.0" }, - "time": "2021-11-05T16:47:00+00:00", + "time": "2021-03-05T17:36:06+00:00", "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, "installation-source": "dist", "autoload": { "psr-4": { @@ -229,33 +229,33 @@ ], "support": { "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/2.0.2" + "source": "https://github.com/php-fig/container/tree/1.1.1" }, "install-path": "../psr/container" }, { "name": "psr/http-message", - "version": "1.1", - "version_normalized": "1.1.0.0", + "version": "1.0.1", + "version_normalized": "1.0.1.0", "source": { "type": "git", "url": "https://github.com/php-fig/http-message.git", - "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba" + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/cb6ce4845ce34a8ad9e68117c10ee90a29919eba", - "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0" + "php": ">=5.3.0" }, - "time": "2023-04-04T09:50:52+00:00", + "time": "2016-08-06T14:39:51+00:00", "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1.x-dev" + "dev-master": "1.0.x-dev" } }, "installation-source": "dist", @@ -285,23 +285,23 @@ "response" ], "support": { - "source": "https://github.com/php-fig/http-message/tree/1.1" + "source": "https://github.com/php-fig/http-message/tree/master" }, "install-path": "../psr/http-message" }, { "name": "react/cache", - "version": "v1.2.0", - "version_normalized": "1.2.0.0", + "version": "v1.1.1", + "version_normalized": "1.1.1.0", "source": { "type": "git", "url": "https://github.com/reactphp/cache.git", - "reference": "d47c472b64aa5608225f47965a484b75c7817d5b" + "reference": "4bf736a2cccec7298bdf745db77585966fc2ca7e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/cache/zipball/d47c472b64aa5608225f47965a484b75c7817d5b", - "reference": "d47c472b64aa5608225f47965a484b75c7817d5b", + "url": "https://api.github.com/repos/reactphp/cache/zipball/4bf736a2cccec7298bdf745db77585966fc2ca7e", + "reference": "4bf736a2cccec7298bdf745db77585966fc2ca7e", "shasum": "" }, "require": { @@ -309,9 +309,9 @@ "react/promise": "^3.0 || ^2.0 || ^1.1" }, "require-dev": { - "phpunit/phpunit": "^9.5 || ^5.7 || ^4.8.35" + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35" }, - "time": "2022-11-30T15:59:55+00:00", + "time": "2021-02-02T06:47:52+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -354,48 +354,52 @@ ], "support": { "issues": "https://github.com/reactphp/cache/issues", - "source": "https://github.com/reactphp/cache/tree/v1.2.0" + "source": "https://github.com/reactphp/cache/tree/v1.1.1" }, "funding": [ { - "url": "https://opencollective.com/reactphp", - "type": "open_collective" + "url": "https://github.com/WyriHaximus", + "type": "github" + }, + { + "url": "https://github.com/clue", + "type": "github" } ], "install-path": "../react/cache" }, { "name": "react/dns", - "version": "v1.13.0", - "version_normalized": "1.13.0.0", + "version": "v1.9.0", + "version_normalized": "1.9.0.0", "source": { "type": "git", "url": "https://github.com/reactphp/dns.git", - "reference": "eb8ae001b5a455665c89c1df97f6fb682f8fb0f5" + "reference": "6d38296756fa644e6cb1bfe95eff0f9a4ed6edcb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/dns/zipball/eb8ae001b5a455665c89c1df97f6fb682f8fb0f5", - "reference": "eb8ae001b5a455665c89c1df97f6fb682f8fb0f5", + "url": "https://api.github.com/repos/reactphp/dns/zipball/6d38296756fa644e6cb1bfe95eff0f9a4ed6edcb", + "reference": "6d38296756fa644e6cb1bfe95eff0f9a4ed6edcb", "shasum": "" }, "require": { "php": ">=5.3.0", "react/cache": "^1.0 || ^0.6 || ^0.5", "react/event-loop": "^1.2", - "react/promise": "^3.2 || ^2.7 || ^1.2.1" + "react/promise": "^3.0 || ^2.7 || ^1.2.1", + "react/promise-timer": "^1.8" }, "require-dev": { - "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", - "react/async": "^4.3 || ^3 || ^2", - "react/promise-timer": "^1.11" + "clue/block-react": "^1.2", + "phpunit/phpunit": "^9.3 || ^4.8.35" }, - "time": "2024-06-13T14:18:03+00:00", + "time": "2021-12-20T08:46:54+00:00", "type": "library", "installation-source": "dist", "autoload": { "psr-4": { - "React\\Dns\\": "src/" + "React\\Dns\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -433,46 +437,52 @@ ], "support": { "issues": "https://github.com/reactphp/dns/issues", - "source": "https://github.com/reactphp/dns/tree/v1.13.0" + "source": "https://github.com/reactphp/dns/tree/v1.9.0" }, "funding": [ { - "url": "https://opencollective.com/reactphp", - "type": "open_collective" + "url": "https://github.com/WyriHaximus", + "type": "github" + }, + { + "url": "https://github.com/clue", + "type": "github" } ], "install-path": "../react/dns" }, { "name": "react/event-loop", - "version": "v1.5.0", - "version_normalized": "1.5.0.0", + "version": "v1.2.0", + "version_normalized": "1.2.0.0", "source": { "type": "git", "url": "https://github.com/reactphp/event-loop.git", - "reference": "bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354" + "reference": "be6dee480fc4692cec0504e65eb486e3be1aa6f2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/event-loop/zipball/bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354", - "reference": "bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354", + "url": "https://api.github.com/repos/reactphp/event-loop/zipball/be6dee480fc4692cec0504e65eb486e3be1aa6f2", + "reference": "be6dee480fc4692cec0504e65eb486e3be1aa6f2", "shasum": "" }, "require": { "php": ">=5.3.0" }, "require-dev": { - "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35" }, "suggest": { - "ext-pcntl": "For signal handling support when using the StreamSelectLoop" + "ext-event": "~1.0 for ExtEventLoop", + "ext-pcntl": "For signal handling support when using the StreamSelectLoop", + "ext-uv": "* for ExtUvLoop" }, - "time": "2023-11-13T13:48:05+00:00", + "time": "2021-07-11T12:31:24+00:00", "type": "library", "installation-source": "dist", "autoload": { "psr-4": { - "React\\EventLoop\\": "src/" + "React\\EventLoop\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -508,29 +518,33 @@ ], "support": { "issues": "https://github.com/reactphp/event-loop/issues", - "source": "https://github.com/reactphp/event-loop/tree/v1.5.0" + "source": "https://github.com/reactphp/event-loop/tree/v1.2.0" }, "funding": [ { - "url": "https://opencollective.com/reactphp", - "type": "open_collective" + "url": "https://github.com/WyriHaximus", + "type": "github" + }, + { + "url": "https://github.com/clue", + "type": "github" } ], "install-path": "../react/event-loop" }, { "name": "react/http", - "version": "v1.10.0", - "version_normalized": "1.10.0.0", + "version": "v1.6.0", + "version_normalized": "1.6.0.0", "source": { "type": "git", "url": "https://github.com/reactphp/http.git", - "reference": "8111281ee57f22b7194f5dba225e609ba7ce4d20" + "reference": "59961cc4a5b14481728f07c591546be18fa3a5c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/http/zipball/8111281ee57f22b7194f5dba225e609ba7ce4d20", - "reference": "8111281ee57f22b7194f5dba225e609ba7ce4d20", + "url": "https://api.github.com/repos/reactphp/http/zipball/59961cc4a5b14481728f07c591546be18fa3a5c7", + "reference": "59961cc4a5b14481728f07c591546be18fa3a5c7", "shasum": "" }, "require": { @@ -539,25 +553,25 @@ "php": ">=5.3.0", "psr/http-message": "^1.0", "react/event-loop": "^1.2", - "react/promise": "^3 || ^2.3 || ^1.2.1", - "react/socket": "^1.12", - "react/stream": "^1.2" + "react/promise": "^2.3 || ^1.2.1", + "react/promise-stream": "^1.1", + "react/socket": "^1.9", + "react/stream": "^1.2", + "ringcentral/psr7": "^1.2" }, "require-dev": { - "clue/http-proxy-react": "^1.8", - "clue/reactphp-ssh-proxy": "^1.4", - "clue/socks-react": "^1.4", - "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", - "react/async": "^4 || ^3 || ^2", - "react/promise-stream": "^1.4", - "react/promise-timer": "^1.9" - }, - "time": "2024-03-27T17:20:46+00:00", + "clue/block-react": "^1.5", + "clue/http-proxy-react": "^1.7", + "clue/reactphp-ssh-proxy": "^1.3", + "clue/socks-react": "^1.3", + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35" + }, + "time": "2022-02-03T13:17:37+00:00", "type": "library", "installation-source": "dist", "autoload": { "psr-4": { - "React\\Http\\": "src/" + "React\\Http\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -602,39 +616,42 @@ ], "support": { "issues": "https://github.com/reactphp/http/issues", - "source": "https://github.com/reactphp/http/tree/v1.10.0" + "source": "https://github.com/reactphp/http/tree/v1.6.0" }, "funding": [ { - "url": "https://opencollective.com/reactphp", - "type": "open_collective" + "url": "https://github.com/WyriHaximus", + "type": "github" + }, + { + "url": "https://github.com/clue", + "type": "github" } ], "install-path": "../react/http" }, { "name": "react/promise", - "version": "v3.2.0", - "version_normalized": "3.2.0.0", + "version": "v2.9.0", + "version_normalized": "2.9.0.0", "source": { "type": "git", "url": "https://github.com/reactphp/promise.git", - "reference": "8a164643313c71354582dc850b42b33fa12a4b63" + "reference": "234f8fd1023c9158e2314fa9d7d0e6a83db42910" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/promise/zipball/8a164643313c71354582dc850b42b33fa12a4b63", - "reference": "8a164643313c71354582dc850b42b33fa12a4b63", + "url": "https://api.github.com/repos/reactphp/promise/zipball/234f8fd1023c9158e2314fa9d7d0e6a83db42910", + "reference": "234f8fd1023c9158e2314fa9d7d0e6a83db42910", "shasum": "" }, "require": { - "php": ">=7.1.0" + "php": ">=5.4.0" }, "require-dev": { - "phpstan/phpstan": "1.10.39 || 1.4.10", - "phpunit/phpunit": "^9.6 || ^7.5" + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.36" }, - "time": "2024-05-24T10:39:05+00:00", + "time": "2022-02-11T10:27:51+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -678,51 +695,230 @@ ], "support": { "issues": "https://github.com/reactphp/promise/issues", - "source": "https://github.com/reactphp/promise/tree/v3.2.0" + "source": "https://github.com/reactphp/promise/tree/v2.9.0" }, "funding": [ { - "url": "https://opencollective.com/reactphp", - "type": "open_collective" + "url": "https://github.com/WyriHaximus", + "type": "github" + }, + { + "url": "https://github.com/clue", + "type": "github" } ], "install-path": "../react/promise" }, + { + "name": "react/promise-stream", + "version": "v1.3.0", + "version_normalized": "1.3.0.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/promise-stream.git", + "reference": "3ebd94fe0d8edbf44937948af28d02d5437e9949" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/promise-stream/zipball/3ebd94fe0d8edbf44937948af28d02d5437e9949", + "reference": "3ebd94fe0d8edbf44937948af28d02d5437e9949", + "shasum": "" + }, + "require": { + "php": ">=5.3", + "react/promise": "^2.1 || ^1.2", + "react/stream": "^1.0 || ^0.7 || ^0.6 || ^0.5 || ^0.4.6" + }, + "require-dev": { + "clue/block-react": "^1.0", + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35", + "react/event-loop": "^1.0 || ^0.5 || ^0.4 || ^0.3", + "react/promise-timer": "^1.0" + }, + "time": "2021-10-18T10:47:09+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "React\\Promise\\Stream\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "The missing link between Promise-land and Stream-land for ReactPHP", + "homepage": "https://github.com/reactphp/promise-stream", + "keywords": [ + "Buffer", + "async", + "promise", + "reactphp", + "stream", + "unwrap" + ], + "support": { + "issues": "https://github.com/reactphp/promise-stream/issues", + "source": "https://github.com/reactphp/promise-stream/tree/v1.3.0" + }, + "funding": [ + { + "url": "https://github.com/WyriHaximus", + "type": "github" + }, + { + "url": "https://github.com/clue", + "type": "github" + } + ], + "install-path": "../react/promise-stream" + }, + { + "name": "react/promise-timer", + "version": "v1.8.0", + "version_normalized": "1.8.0.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/promise-timer.git", + "reference": "0bbbcc79589e5bfdddba68a287f1cb805581a479" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/promise-timer/zipball/0bbbcc79589e5bfdddba68a287f1cb805581a479", + "reference": "0bbbcc79589e5bfdddba68a287f1cb805581a479", + "shasum": "" + }, + "require": { + "php": ">=5.3", + "react/event-loop": "^1.2", + "react/promise": "^3.0 || ^2.7.0 || ^1.2.1" + }, + "require-dev": { + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35" + }, + "time": "2021-12-06T11:08:48+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "React\\Promise\\Timer\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "A trivial implementation of timeouts for Promises, built on top of ReactPHP.", + "homepage": "https://github.com/reactphp/promise-timer", + "keywords": [ + "async", + "event-loop", + "promise", + "reactphp", + "timeout", + "timer" + ], + "support": { + "issues": "https://github.com/reactphp/promise-timer/issues", + "source": "https://github.com/reactphp/promise-timer/tree/v1.8.0" + }, + "funding": [ + { + "url": "https://github.com/WyriHaximus", + "type": "github" + }, + { + "url": "https://github.com/clue", + "type": "github" + } + ], + "install-path": "../react/promise-timer" + }, { "name": "react/socket", - "version": "v1.16.0", - "version_normalized": "1.16.0.0", + "version": "v1.11.0", + "version_normalized": "1.11.0.0", "source": { "type": "git", "url": "https://github.com/reactphp/socket.git", - "reference": "23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1" + "reference": "f474156aaab4f09041144fa8b57c7d70aed32a1c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/socket/zipball/23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1", - "reference": "23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1", + "url": "https://api.github.com/repos/reactphp/socket/zipball/f474156aaab4f09041144fa8b57c7d70aed32a1c", + "reference": "f474156aaab4f09041144fa8b57c7d70aed32a1c", "shasum": "" }, "require": { "evenement/evenement": "^3.0 || ^2.0 || ^1.0", "php": ">=5.3.0", - "react/dns": "^1.13", + "react/dns": "^1.8", "react/event-loop": "^1.2", - "react/promise": "^3.2 || ^2.6 || ^1.2.1", - "react/stream": "^1.4" + "react/promise": "^2.6.0 || ^1.2.1", + "react/promise-timer": "^1.8", + "react/stream": "^1.2" }, "require-dev": { - "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", - "react/async": "^4.3 || ^3.3 || ^2", - "react/promise-stream": "^1.4", - "react/promise-timer": "^1.11" + "clue/block-react": "^1.5", + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35", + "react/promise-stream": "^1.2" }, - "time": "2024-07-26T10:38:09+00:00", + "time": "2022-01-14T10:14:32+00:00", "type": "library", "installation-source": "dist", "autoload": { "psr-4": { - "React\\Socket\\": "src/" + "React\\Socket\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -761,29 +957,33 @@ ], "support": { "issues": "https://github.com/reactphp/socket/issues", - "source": "https://github.com/reactphp/socket/tree/v1.16.0" + "source": "https://github.com/reactphp/socket/tree/v1.11.0" }, "funding": [ { - "url": "https://opencollective.com/reactphp", - "type": "open_collective" + "url": "https://github.com/WyriHaximus", + "type": "github" + }, + { + "url": "https://github.com/clue", + "type": "github" } ], "install-path": "../react/socket" }, { "name": "react/stream", - "version": "v1.4.0", - "version_normalized": "1.4.0.0", + "version": "v1.2.0", + "version_normalized": "1.2.0.0", "source": { "type": "git", "url": "https://github.com/reactphp/stream.git", - "reference": "1e5b0acb8fe55143b5b426817155190eb6f5b18d" + "reference": "7a423506ee1903e89f1e08ec5f0ed430ff784ae9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/stream/zipball/1e5b0acb8fe55143b5b426817155190eb6f5b18d", - "reference": "1e5b0acb8fe55143b5b426817155190eb6f5b18d", + "url": "https://api.github.com/repos/reactphp/stream/zipball/7a423506ee1903e89f1e08ec5f0ed430ff784ae9", + "reference": "7a423506ee1903e89f1e08ec5f0ed430ff784ae9", "shasum": "" }, "require": { @@ -793,14 +993,14 @@ }, "require-dev": { "clue/stream-filter": "~1.2", - "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35" }, - "time": "2024-06-11T12:45:25+00:00", + "time": "2021-07-11T12:37:55+00:00", "type": "library", "installation-source": "dist", "autoload": { "psr-4": { - "React\\Stream\\": "src/" + "React\\Stream\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -842,29 +1042,97 @@ ], "support": { "issues": "https://github.com/reactphp/stream/issues", - "source": "https://github.com/reactphp/stream/tree/v1.4.0" + "source": "https://github.com/reactphp/stream/tree/v1.2.0" }, "funding": [ { - "url": "https://opencollective.com/reactphp", - "type": "open_collective" + "url": "https://github.com/WyriHaximus", + "type": "github" + }, + { + "url": "https://github.com/clue", + "type": "github" } ], "install-path": "../react/stream" }, + { + "name": "ringcentral/psr7", + "version": "1.3.0", + "version_normalized": "1.3.0.0", + "source": { + "type": "git", + "url": "https://github.com/ringcentral/psr7.git", + "reference": "360faaec4b563958b673fb52bbe94e37f14bc686" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ringcentral/psr7/zipball/360faaec4b563958b673fb52bbe94e37f14bc686", + "reference": "360faaec4b563958b673fb52bbe94e37f14bc686", + "shasum": "" + }, + "require": { + "php": ">=5.3", + "psr/http-message": "~1.0" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "time": "2018-05-29T20:21:04+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "RingCentral\\Psr7\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "PSR-7 message implementation", + "keywords": [ + "http", + "message", + "stream", + "uri" + ], + "support": { + "source": "https://github.com/ringcentral/psr7/tree/master" + }, + "install-path": "../ringcentral/psr7" + }, { "name": "symfony/console", - "version": "v5.4.44", - "version_normalized": "5.4.44.0", + "version": "v5.4.17", + "version_normalized": "5.4.17.0", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "5b5a0aa66e3296e303e22490f90f521551835a83" + "reference": "58422fdcb0e715ed05b385f70d3e8b5ed4bbd45f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/5b5a0aa66e3296e303e22490f90f521551835a83", - "reference": "5b5a0aa66e3296e303e22490f90f521551835a83", + "url": "https://api.github.com/repos/symfony/console/zipball/58422fdcb0e715ed05b385f70d3e8b5ed4bbd45f", + "reference": "58422fdcb0e715ed05b385f70d3e8b5ed4bbd45f", "shasum": "" }, "require": { @@ -902,7 +1170,7 @@ "symfony/lock": "", "symfony/process": "" }, - "time": "2024-09-20T07:56:40+00:00", + "time": "2022-12-28T14:15:31+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -931,12 +1199,12 @@ "homepage": "https://symfony.com", "keywords": [ "cli", - "command-line", + "command line", "console", "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v5.4.44" + "source": "https://github.com/symfony/console/tree/v5.4.17" }, "funding": [ { @@ -956,27 +1224,27 @@ }, { "name": "symfony/deprecation-contracts", - "version": "v3.5.0", - "version_normalized": "3.5.0.0", + "version": "v2.5.0", + "version_normalized": "2.5.0.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1" + "reference": "6f981ee24cf69ee7ce9736146d1c57c2780598a8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", - "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/6f981ee24cf69ee7ce9736146d1c57c2780598a8", + "reference": "6f981ee24cf69ee7ce9736146d1c57c2780598a8", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=7.1" }, - "time": "2024-04-18T09:32:20+00:00", + "time": "2021-07-12T14:48:14+00:00", "type": "library", "extra": { "branch-alias": { - "dev-main": "3.5-dev" + "dev-main": "2.5-dev" }, "thanks": { "name": "symfony/contracts", @@ -1006,7 +1274,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.0" }, "funding": [ { @@ -1026,21 +1294,21 @@ }, { "name": "symfony/polyfill-ctype", - "version": "v1.31.0", - "version_normalized": "1.31.0.0", + "version": "v1.25.0", + "version_normalized": "1.25.0.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" + "reference": "30885182c981ab175d4d034db0f6f469898070ab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", - "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/30885182c981ab175d4d034db0f6f469898070ab", + "reference": "30885182c981ab175d4d034db0f6f469898070ab", "shasum": "" }, "require": { - "php": ">=7.2" + "php": ">=7.1" }, "provide": { "ext-ctype": "*" @@ -1048,9 +1316,12 @@ "suggest": { "ext-ctype": "For best performance" }, - "time": "2024-09-09T11:45:10+00:00", + "time": "2021-10-20T20:35:02+00:00", "type": "library", "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -1088,7 +1359,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.25.0" }, "funding": [ { @@ -1108,28 +1379,31 @@ }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.31.0", - "version_normalized": "1.31.0.0", + "version": "v1.25.0", + "version_normalized": "1.25.0.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe" + "reference": "81b86b50cf841a64252b439e738e97f4a34e2783" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", - "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/81b86b50cf841a64252b439e738e97f4a34e2783", + "reference": "81b86b50cf841a64252b439e738e97f4a34e2783", "shasum": "" }, "require": { - "php": ">=7.2" + "php": ">=7.1" }, "suggest": { "ext-intl": "For best performance" }, - "time": "2024-09-09T11:45:10+00:00", + "time": "2021-11-23T21:10:46+00:00", "type": "library", "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -1169,7 +1443,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.25.0" }, "funding": [ { @@ -1189,28 +1463,31 @@ }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.31.0", - "version_normalized": "1.31.0.0", + "version": "v1.25.0", + "version_normalized": "1.25.0.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "3833d7255cc303546435cb650316bff708a1c75c" + "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", - "reference": "3833d7255cc303546435cb650316bff708a1c75c", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8590a5f561694770bdcd3f9b5c69dde6945028e8", + "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8", "shasum": "" }, "require": { - "php": ">=7.2" + "php": ">=7.1" }, "suggest": { "ext-intl": "For best performance" }, - "time": "2024-09-09T11:45:10+00:00", + "time": "2021-02-19T12:13:01+00:00", "type": "library", "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -1253,7 +1530,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.25.0" }, "funding": [ { @@ -1273,21 +1550,21 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "v1.31.0", - "version_normalized": "1.31.0.0", + "version": "v1.25.0", + "version_normalized": "1.25.0.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" + "reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", - "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/0abb51d2f102e00a4eefcf46ba7fec406d245825", + "reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825", "shasum": "" }, "require": { - "php": ">=7.2" + "php": ">=7.1" }, "provide": { "ext-mbstring": "*" @@ -1295,9 +1572,12 @@ "suggest": { "ext-mbstring": "For best performance" }, - "time": "2024-09-09T11:45:10+00:00", + "time": "2021-11-30T18:21:41+00:00", "type": "library", "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -1336,7 +1616,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.25.0" }, "funding": [ { @@ -1356,25 +1636,28 @@ }, { "name": "symfony/polyfill-php73", - "version": "v1.31.0", - "version_normalized": "1.31.0.0", + "version": "v1.25.0", + "version_normalized": "1.25.0.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb" + "reference": "cc5db0e22b3cb4111010e48785a97f670b350ca5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/0f68c03565dcaaf25a890667542e8bd75fe7e5bb", - "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/cc5db0e22b3cb4111010e48785a97f670b350ca5", + "reference": "cc5db0e22b3cb4111010e48785a97f670b350ca5", "shasum": "" }, "require": { - "php": ">=7.2" + "php": ">=7.1" }, - "time": "2024-09-09T11:45:10+00:00", + "time": "2021-06-05T21:20:04+00:00", "type": "library", "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -1415,7 +1698,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-php73/tree/v1.25.0" }, "funding": [ { @@ -1435,25 +1718,28 @@ }, { "name": "symfony/polyfill-php80", - "version": "v1.31.0", - "version_normalized": "1.31.0.0", + "version": "v1.25.0", + "version_normalized": "1.25.0.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8" + "reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", - "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/4407588e0d3f1f52efb65fbe92babe41f37fe50c", + "reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c", "shasum": "" }, "require": { - "php": ">=7.2" + "php": ">=7.1" }, - "time": "2024-09-09T11:45:10+00:00", + "time": "2022-03-04T08:16:47+00:00", "type": "library", "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -1498,7 +1784,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.25.0" }, "funding": [ { @@ -1518,25 +1804,28 @@ }, { "name": "symfony/polyfill-php81", - "version": "v1.31.0", - "version_normalized": "1.31.0.0", + "version": "v1.26.0", + "version_normalized": "1.26.0.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php81.git", - "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c" + "reference": "13f6d1271c663dc5ae9fb843a8f16521db7687a1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", - "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/13f6d1271c663dc5ae9fb843a8f16521db7687a1", + "reference": "13f6d1271c663dc5ae9fb843a8f16521db7687a1", "shasum": "" }, "require": { - "php": ">=7.2" + "php": ">=7.1" }, - "time": "2024-09-09T11:45:10+00:00", + "time": "2022-05-24T11:49:31+00:00", "type": "library", "extra": { + "branch-alias": { + "dev-main": "1.26-dev" + }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -1577,7 +1866,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-php81/tree/v1.26.0" }, "funding": [ { @@ -1597,24 +1886,24 @@ }, { "name": "symfony/process", - "version": "v5.4.44", - "version_normalized": "5.4.44.0", + "version": "v5.4.5", + "version_normalized": "5.4.5.0", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "1b9fa82b5c62cd49da8c9e3952dd8531ada65096" + "reference": "95440409896f90a5f85db07a32b517ecec17fa4c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/1b9fa82b5c62cd49da8c9e3952dd8531ada65096", - "reference": "1b9fa82b5c62cd49da8c9e3952dd8531ada65096", + "url": "https://api.github.com/repos/symfony/process/zipball/95440409896f90a5f85db07a32b517ecec17fa4c", + "reference": "95440409896f90a5f85db07a32b517ecec17fa4c", "shasum": "" }, "require": { "php": ">=7.2.5", "symfony/polyfill-php80": "^1.16" }, - "time": "2024-09-17T12:46:43+00:00", + "time": "2022-01-30T18:16:22+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -1642,7 +1931,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v5.4.44" + "source": "https://github.com/symfony/process/tree/v5.4.5" }, "funding": [ { @@ -1662,32 +1951,35 @@ }, { "name": "symfony/service-contracts", - "version": "v3.5.0", - "version_normalized": "3.5.0.0", + "version": "v2.5.0", + "version_normalized": "2.5.0.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f" + "reference": "1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", - "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc", + "reference": "1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc", "shasum": "" }, "require": { - "php": ">=8.1", - "psr/container": "^1.1|^2.0", - "symfony/deprecation-contracts": "^2.5|^3" + "php": ">=7.2.5", + "psr/container": "^1.1", + "symfony/deprecation-contracts": "^2.1" }, "conflict": { "ext-psr": "<1.1|>=2" }, - "time": "2024-04-18T09:32:20+00:00", + "suggest": { + "symfony/service-implementation": "" + }, + "time": "2021-11-04T16:48:04+00:00", "type": "library", "extra": { "branch-alias": { - "dev-main": "3.5-dev" + "dev-main": "2.5-dev" }, "thanks": { "name": "symfony/contracts", @@ -1698,10 +1990,7 @@ "autoload": { "psr-4": { "Symfony\\Contracts\\Service\\": "" - }, - "exclude-from-classmap": [ - "/Test/" - ] + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1728,7 +2017,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/service-contracts/tree/v2.5.0" }, "funding": [ { @@ -1748,37 +2037,37 @@ }, { "name": "symfony/string", - "version": "v6.4.12", - "version_normalized": "6.4.12.0", + "version": "v5.4.3", + "version_normalized": "5.4.3.0", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "f8a1ccebd0997e16112dfecfd74220b78e5b284b" + "reference": "92043b7d8383e48104e411bc9434b260dbeb5a10" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/f8a1ccebd0997e16112dfecfd74220b78e5b284b", - "reference": "f8a1ccebd0997e16112dfecfd74220b78e5b284b", + "url": "https://api.github.com/repos/symfony/string/zipball/92043b7d8383e48104e411bc9434b260dbeb5a10", + "reference": "92043b7d8383e48104e411bc9434b260dbeb5a10", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=7.2.5", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-intl-grapheme": "~1.0", "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0" + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php80": "~1.15" }, "conflict": { - "symfony/translation-contracts": "<2.5" + "symfony/translation-contracts": ">=3.0" }, "require-dev": { - "symfony/error-handler": "^5.4|^6.0|^7.0", - "symfony/http-client": "^5.4|^6.0|^7.0", - "symfony/intl": "^6.2|^7.0", - "symfony/translation-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^5.4|^6.0|^7.0" + "symfony/error-handler": "^4.4|^5.0|^6.0", + "symfony/http-client": "^4.4|^5.0|^6.0", + "symfony/translation-contracts": "^1.1|^2", + "symfony/var-exporter": "^4.4|^5.0|^6.0" }, - "time": "2024-09-20T08:15:52+00:00", + "time": "2022-01-02T09:53:40+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -1817,7 +2106,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.4.12" + "source": "https://github.com/symfony/string/tree/v5.4.3" }, "funding": [ { @@ -1837,17 +2126,17 @@ }, { "name": "symfony/yaml", - "version": "v5.4.44", - "version_normalized": "5.4.44.0", + "version": "v5.4.3", + "version_normalized": "5.4.3.0", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "7025b964f123bbf1896d7563db6ec7f1f63e918a" + "reference": "e80f87d2c9495966768310fc531b487ce64237a2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/7025b964f123bbf1896d7563db6ec7f1f63e918a", - "reference": "7025b964f123bbf1896d7563db6ec7f1f63e918a", + "url": "https://api.github.com/repos/symfony/yaml/zipball/e80f87d2c9495966768310fc531b487ce64237a2", + "reference": "e80f87d2c9495966768310fc531b487ce64237a2", "shasum": "" }, "require": { @@ -1864,7 +2153,7 @@ "suggest": { "symfony/console": "For validating YAML files using the lint command" }, - "time": "2024-09-16T14:36:56+00:00", + "time": "2022-01-26T16:32:32+00:00", "bin": [ "Resources/bin/yaml-lint" ], @@ -1895,7 +2184,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v5.4.44" + "source": "https://github.com/symfony/yaml/tree/v5.4.3" }, "funding": [ { @@ -1914,6 +2203,6 @@ "install-path": "../symfony/yaml" } ], - "dev": true, + "dev": false, "dev-package-names": [] } diff --git a/deps/vendor/composer/installed.php b/deps/vendor/composer/installed.php index ebbaca0b2..1ec93e724 100644 --- a/deps/vendor/composer/installed.php +++ b/deps/vendor/composer/installed.php @@ -3,26 +3,26 @@ 'name' => '__root__', 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => '27ffcc6ad17da6c8f059cfc108905fd8e2bb9291', + 'reference' => 'b29bfee344eadad849be1bc7b6b11751ee4924eb', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), - 'dev' => true, + 'dev' => false, ), 'versions' => array( '__root__' => array( 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => '27ffcc6ad17da6c8f059cfc108905fd8e2bb9291', + 'reference' => 'b29bfee344eadad849be1bc7b6b11751ee4924eb', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev_requirement' => false, ), 'evenement/evenement' => array( - 'pretty_version' => 'v3.0.2', - 'version' => '3.0.2.0', - 'reference' => '0a16b0d71ab13284339abb99d9d2bd813640efbc', + 'pretty_version' => 'v3.0.1', + 'version' => '3.0.1.0', + 'reference' => '531bfb9d15f8aa57454f5f0285b18bec903b8fb7', 'type' => 'library', 'install_path' => __DIR__ . '/../evenement/evenement', 'aliases' => array(), @@ -38,32 +38,38 @@ 'dev_requirement' => false, ), 'justinrainbow/json-schema' => array( - 'pretty_version' => '5.3.0', - 'version' => '5.3.0.0', - 'reference' => 'feb2ca6dd1cebdaf1ed60a4c8de2e53ce11c4fd8', + 'pretty_version' => '5.2.11', + 'version' => '5.2.11.0', + 'reference' => '2ab6744b7296ded80f8cc4f9509abbff393399aa', 'type' => 'library', 'install_path' => __DIR__ . '/../justinrainbow/json-schema', 'aliases' => array(), 'dev_requirement' => false, ), 'psr/container' => array( - 'pretty_version' => '2.0.2', - 'version' => '2.0.2.0', - 'reference' => 'c71ecc56dfe541dbd90c5360474fbc405f8d5963', + 'pretty_version' => '1.1.1', + 'version' => '1.1.1.0', + 'reference' => '8622567409010282b7aeebe4bb841fe98b58dcaf', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/container', 'aliases' => array(), 'dev_requirement' => false, ), 'psr/http-message' => array( - 'pretty_version' => '1.1', - 'version' => '1.1.0.0', - 'reference' => 'cb6ce4845ce34a8ad9e68117c10ee90a29919eba', + 'pretty_version' => '1.0.1', + 'version' => '1.0.1.0', + 'reference' => 'f6561bf28d520154e4b0ec72be95418abe6d9363', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/http-message', 'aliases' => array(), 'dev_requirement' => false, ), + 'psr/http-message-implementation' => array( + 'dev_requirement' => false, + 'provided' => array( + 0 => '1.0', + ), + ), 'psr/log-implementation' => array( 'dev_requirement' => false, 'provided' => array( @@ -71,180 +77,207 @@ ), ), 'react/cache' => array( - 'pretty_version' => 'v1.2.0', - 'version' => '1.2.0.0', - 'reference' => 'd47c472b64aa5608225f47965a484b75c7817d5b', + 'pretty_version' => 'v1.1.1', + 'version' => '1.1.1.0', + 'reference' => '4bf736a2cccec7298bdf745db77585966fc2ca7e', 'type' => 'library', 'install_path' => __DIR__ . '/../react/cache', 'aliases' => array(), 'dev_requirement' => false, ), 'react/dns' => array( - 'pretty_version' => 'v1.13.0', - 'version' => '1.13.0.0', - 'reference' => 'eb8ae001b5a455665c89c1df97f6fb682f8fb0f5', + 'pretty_version' => 'v1.9.0', + 'version' => '1.9.0.0', + 'reference' => '6d38296756fa644e6cb1bfe95eff0f9a4ed6edcb', 'type' => 'library', 'install_path' => __DIR__ . '/../react/dns', 'aliases' => array(), 'dev_requirement' => false, ), 'react/event-loop' => array( - 'pretty_version' => 'v1.5.0', - 'version' => '1.5.0.0', - 'reference' => 'bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354', + 'pretty_version' => 'v1.2.0', + 'version' => '1.2.0.0', + 'reference' => 'be6dee480fc4692cec0504e65eb486e3be1aa6f2', 'type' => 'library', 'install_path' => __DIR__ . '/../react/event-loop', 'aliases' => array(), 'dev_requirement' => false, ), 'react/http' => array( - 'pretty_version' => 'v1.10.0', - 'version' => '1.10.0.0', - 'reference' => '8111281ee57f22b7194f5dba225e609ba7ce4d20', + 'pretty_version' => 'v1.6.0', + 'version' => '1.6.0.0', + 'reference' => '59961cc4a5b14481728f07c591546be18fa3a5c7', 'type' => 'library', 'install_path' => __DIR__ . '/../react/http', 'aliases' => array(), 'dev_requirement' => false, ), 'react/promise' => array( - 'pretty_version' => 'v3.2.0', - 'version' => '3.2.0.0', - 'reference' => '8a164643313c71354582dc850b42b33fa12a4b63', + 'pretty_version' => 'v2.9.0', + 'version' => '2.9.0.0', + 'reference' => '234f8fd1023c9158e2314fa9d7d0e6a83db42910', 'type' => 'library', 'install_path' => __DIR__ . '/../react/promise', 'aliases' => array(), 'dev_requirement' => false, ), + 'react/promise-stream' => array( + 'pretty_version' => 'v1.3.0', + 'version' => '1.3.0.0', + 'reference' => '3ebd94fe0d8edbf44937948af28d02d5437e9949', + 'type' => 'library', + 'install_path' => __DIR__ . '/../react/promise-stream', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'react/promise-timer' => array( + 'pretty_version' => 'v1.8.0', + 'version' => '1.8.0.0', + 'reference' => '0bbbcc79589e5bfdddba68a287f1cb805581a479', + 'type' => 'library', + 'install_path' => __DIR__ . '/../react/promise-timer', + 'aliases' => array(), + 'dev_requirement' => false, + ), 'react/socket' => array( - 'pretty_version' => 'v1.16.0', - 'version' => '1.16.0.0', - 'reference' => '23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1', + 'pretty_version' => 'v1.11.0', + 'version' => '1.11.0.0', + 'reference' => 'f474156aaab4f09041144fa8b57c7d70aed32a1c', 'type' => 'library', 'install_path' => __DIR__ . '/../react/socket', 'aliases' => array(), 'dev_requirement' => false, ), 'react/stream' => array( - 'pretty_version' => 'v1.4.0', - 'version' => '1.4.0.0', - 'reference' => '1e5b0acb8fe55143b5b426817155190eb6f5b18d', + 'pretty_version' => 'v1.2.0', + 'version' => '1.2.0.0', + 'reference' => '7a423506ee1903e89f1e08ec5f0ed430ff784ae9', 'type' => 'library', 'install_path' => __DIR__ . '/../react/stream', 'aliases' => array(), 'dev_requirement' => false, ), + 'ringcentral/psr7' => array( + 'pretty_version' => '1.3.0', + 'version' => '1.3.0.0', + 'reference' => '360faaec4b563958b673fb52bbe94e37f14bc686', + 'type' => 'library', + 'install_path' => __DIR__ . '/../ringcentral/psr7', + 'aliases' => array(), + 'dev_requirement' => false, + ), 'symfony/console' => array( - 'pretty_version' => 'v5.4.44', - 'version' => '5.4.44.0', - 'reference' => '5b5a0aa66e3296e303e22490f90f521551835a83', + 'pretty_version' => 'v5.4.17', + 'version' => '5.4.17.0', + 'reference' => '58422fdcb0e715ed05b385f70d3e8b5ed4bbd45f', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/console', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/deprecation-contracts' => array( - 'pretty_version' => 'v3.5.0', - 'version' => '3.5.0.0', - 'reference' => '0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1', + 'pretty_version' => 'v2.5.0', + 'version' => '2.5.0.0', + 'reference' => '6f981ee24cf69ee7ce9736146d1c57c2780598a8', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/deprecation-contracts', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/polyfill-ctype' => array( - 'pretty_version' => 'v1.31.0', - 'version' => '1.31.0.0', - 'reference' => 'a3cc8b044a6ea513310cbd48ef7333b384945638', + 'pretty_version' => 'v1.25.0', + 'version' => '1.25.0.0', + 'reference' => '30885182c981ab175d4d034db0f6f469898070ab', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-ctype', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/polyfill-intl-grapheme' => array( - 'pretty_version' => 'v1.31.0', - 'version' => '1.31.0.0', - 'reference' => 'b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe', + 'pretty_version' => 'v1.25.0', + 'version' => '1.25.0.0', + 'reference' => '81b86b50cf841a64252b439e738e97f4a34e2783', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-intl-grapheme', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/polyfill-intl-normalizer' => array( - 'pretty_version' => 'v1.31.0', - 'version' => '1.31.0.0', - 'reference' => '3833d7255cc303546435cb650316bff708a1c75c', + 'pretty_version' => 'v1.25.0', + 'version' => '1.25.0.0', + 'reference' => '8590a5f561694770bdcd3f9b5c69dde6945028e8', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-intl-normalizer', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/polyfill-mbstring' => array( - 'pretty_version' => 'v1.31.0', - 'version' => '1.31.0.0', - 'reference' => '85181ba99b2345b0ef10ce42ecac37612d9fd341', + 'pretty_version' => 'v1.25.0', + 'version' => '1.25.0.0', + 'reference' => '0abb51d2f102e00a4eefcf46ba7fec406d245825', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-mbstring', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/polyfill-php73' => array( - 'pretty_version' => 'v1.31.0', - 'version' => '1.31.0.0', - 'reference' => '0f68c03565dcaaf25a890667542e8bd75fe7e5bb', + 'pretty_version' => 'v1.25.0', + 'version' => '1.25.0.0', + 'reference' => 'cc5db0e22b3cb4111010e48785a97f670b350ca5', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-php73', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/polyfill-php80' => array( - 'pretty_version' => 'v1.31.0', - 'version' => '1.31.0.0', - 'reference' => '60328e362d4c2c802a54fcbf04f9d3fb892b4cf8', + 'pretty_version' => 'v1.25.0', + 'version' => '1.25.0.0', + 'reference' => '4407588e0d3f1f52efb65fbe92babe41f37fe50c', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-php80', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/polyfill-php81' => array( - 'pretty_version' => 'v1.31.0', - 'version' => '1.31.0.0', - 'reference' => '4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c', + 'pretty_version' => 'v1.26.0', + 'version' => '1.26.0.0', + 'reference' => '13f6d1271c663dc5ae9fb843a8f16521db7687a1', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-php81', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/process' => array( - 'pretty_version' => 'v5.4.44', - 'version' => '5.4.44.0', - 'reference' => '1b9fa82b5c62cd49da8c9e3952dd8531ada65096', + 'pretty_version' => 'v5.4.5', + 'version' => '5.4.5.0', + 'reference' => '95440409896f90a5f85db07a32b517ecec17fa4c', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/process', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/service-contracts' => array( - 'pretty_version' => 'v3.5.0', - 'version' => '3.5.0.0', - 'reference' => 'bd1d9e59a81d8fa4acdcea3f617c581f7475a80f', + 'pretty_version' => 'v2.5.0', + 'version' => '2.5.0.0', + 'reference' => '1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/service-contracts', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/string' => array( - 'pretty_version' => 'v6.4.12', - 'version' => '6.4.12.0', - 'reference' => 'f8a1ccebd0997e16112dfecfd74220b78e5b284b', + 'pretty_version' => 'v5.4.3', + 'version' => '5.4.3.0', + 'reference' => '92043b7d8383e48104e411bc9434b260dbeb5a10', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/string', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/yaml' => array( - 'pretty_version' => 'v5.4.44', - 'version' => '5.4.44.0', - 'reference' => '7025b964f123bbf1896d7563db6ec7f1f63e918a', + 'pretty_version' => 'v5.4.3', + 'version' => '5.4.3.0', + 'reference' => 'e80f87d2c9495966768310fc531b487ce64237a2', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/yaml', 'aliases' => array(), diff --git a/deps/vendor/composer/platform_check.php b/deps/vendor/composer/platform_check.php deleted file mode 100644 index 4c3a5d68f..000000000 --- a/deps/vendor/composer/platform_check.php +++ /dev/null @@ -1,26 +0,0 @@ -= 80100)) { - $issues[] = 'Your Composer dependencies require a PHP version ">= 8.1.0". You are running ' . PHP_VERSION . '.'; -} - -if ($issues) { - if (!headers_sent()) { - header('HTTP/1.1 500 Internal Server Error'); - } - if (!ini_get('display_errors')) { - if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') { - fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL); - } elseif (!headers_sent()) { - echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL; - } - } - trigger_error( - 'Composer detected issues in your platform: ' . implode(' ', $issues), - E_USER_ERROR - ); -} diff --git a/deps/vendor/evenement/evenement/.gitattributes b/deps/vendor/evenement/evenement/.gitattributes deleted file mode 100644 index 8e493b8ce..000000000 --- a/deps/vendor/evenement/evenement/.gitattributes +++ /dev/null @@ -1,7 +0,0 @@ -/.github export-ignore -/doc export-ignore -/examples export-ignore -/tests export-ignore -/.gitignore export-ignore -/CHANGELOG.md export-ignore -/phpunit.xml.dist export-ignore diff --git a/deps/vendor/evenement/evenement/.gitignore b/deps/vendor/evenement/evenement/.gitignore new file mode 100644 index 000000000..987e2a253 --- /dev/null +++ b/deps/vendor/evenement/evenement/.gitignore @@ -0,0 +1,2 @@ +composer.lock +vendor diff --git a/deps/vendor/evenement/evenement/.travis.yml b/deps/vendor/evenement/evenement/.travis.yml new file mode 100644 index 000000000..65ba0ced9 --- /dev/null +++ b/deps/vendor/evenement/evenement/.travis.yml @@ -0,0 +1,24 @@ +language: php + +php: + - 7.0 + - 7.1 + - hhvm + - nightly + +matrix: + allow_failures: + - php: hhvm + - php: nightly + +before_script: + - wget http://getcomposer.org/composer.phar + - php composer.phar install + +script: + - ./vendor/bin/phpunit --coverage-text + - php -n examples/benchmark-emit-no-arguments.php + - php -n examples/benchmark-emit-one-argument.php + - php -n examples/benchmark-emit.php + - php -n examples/benchmark-emit-once.php + - php -n examples/benchmark-remove-listener-once.php diff --git a/deps/vendor/evenement/evenement/CHANGELOG.md b/deps/vendor/evenement/evenement/CHANGELOG.md new file mode 100644 index 000000000..568f2295a --- /dev/null +++ b/deps/vendor/evenement/evenement/CHANGELOG.md @@ -0,0 +1,35 @@ +CHANGELOG +========= + + +* v3.0.1 (2017-07-23) + + * Resolved regression introduced in once listeners in v3.0.0 [#49](https://github.com/igorw/evenement/pull/49) + +* v3.0.0 (2017-07-23) + + * Passing null as event name throw exception [#46](https://github.com/igorw/evenement/pull/46), and [#47](https://github.com/igorw/evenement/pull/47) + * Performance improvements [#39](https://github.com/igorw/evenement/pull/39), and [#45](https://github.com/igorw/evenement/pull/45) + * Remove once listeners [#44](https://github.com/igorw/evenement/pull/44), [#45](https://github.com/igorw/evenement/pull/45) + +* v2.1.0 (2017-07-17) + + * Chaining for "on" method [#30](https://github.com/igorw/evenement/pull/30) + * Unit tests (on Travis) improvements [#33](https://github.com/igorw/evenement/pull/33), [#36](https://github.com/igorw/evenement/pull/36), and [#37](https://github.com/igorw/evenement/pull/37) + * Benchmarks added [#35](https://github.com/igorw/evenement/pull/35), and [#40](https://github.com/igorw/evenement/pull/40) + * Minor performance improvements [#42](https://github.com/igorw/evenement/pull/42), and [#38](https://github.com/igorw/evenement/pull/38) + +* v2.0.0 (2012-11-02) + + * Require PHP >=5.4.0 + * Added EventEmitterTrait + * Removed EventEmitter2 + +* v1.1.0 (2017-07-17) + + * Chaining for "on" method [#29](https://github.com/igorw/evenement/pull/29) + * Minor performance improvements [#43](https://github.com/igorw/evenement/pull/43) + +* v1.0.0 (2012-05-30) + + * Inital stable release diff --git a/deps/vendor/evenement/evenement/README.md b/deps/vendor/evenement/evenement/README.md index 455dd22c2..94430119b 100644 --- a/deps/vendor/evenement/evenement/README.md +++ b/deps/vendor/evenement/evenement/README.md @@ -2,47 +2,66 @@ Événement is a very simple event dispatching library for PHP. -It has the same design goals as [Silex](https://silex.symfony.com/) and -[Pimple](https://github.com/silexphp/Pimple), to empower the user while staying concise +It has the same design goals as [Silex](http://silex-project.org) and +[Pimple](http://pimple-project.org), to empower the user while staying concise and simple. -It is very strongly inspired by the [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter) API found in +It is very strongly inspired by the EventEmitter API found in [node.js](http://nodejs.org). -![Continuous Integration](https://github.com/igorw/evenement/workflows/CI/badge.svg) -[![Latest Stable Version](https://poser.pugx.org/evenement/evenement/v/stable.png)](https://packagist.org/packages/evenement/evenement) -[![Total Downloads](https://poser.pugx.org/evenement/evenement/downloads.png)](https://packagist.org/packages/evenement/evenement/stats) -[![License](https://poser.pugx.org/evenement/evenement/license.png)](https://packagist.org/packages/evenement/evenement) +[![Build Status](https://secure.travis-ci.org/igorw/evenement.png?branch=master)](http://travis-ci.org/igorw/evenement) ## Fetch -The recommended way to install Événement is [through composer](http://getcomposer.org). By running the following command: +The recommended way to install Événement is [through composer](http://getcomposer.org). - $ composer require evenement/evenement +Just create a composer.json file for your project: -## Usage +```JSON +{ + "require": { + "evenement/evenement": "^3.0 || ^2.0" + } +} +``` -### Creating an Emitter +**Note:** The `3.x` version of Événement requires PHP 7 and the `2.x` version requires PHP 5.4. If you are +using PHP 5.3, please use the `1.x` version: + +```JSON +{ + "require": { + "evenement/evenement": "^1.0" + } +} +``` + +And run these two commands to install it: + + $ curl -s http://getcomposer.org/installer | php + $ php composer.phar install + +Now you can add the autoloader, and you will have access to the library: ```php on('user.created', function (User $user) use ($logger) { - $logger->log(sprintf("User '%s' was created.", $user->getLogin())); -}); +$emitter = new Evenement\EventEmitter(); ``` -### Removing Listeners +### Adding Listeners ```php removeListener('user.created', function (User $user) use ($logger) { +$emitter->on('user.created', function (User $user) use ($logger) { $logger->log(sprintf("User '%s' was created.", $user->getLogin())); }); ``` diff --git a/deps/vendor/evenement/evenement/composer.json b/deps/vendor/evenement/evenement/composer.json index 5444d93e2..cbb4827b6 100644 --- a/deps/vendor/evenement/evenement/composer.json +++ b/deps/vendor/evenement/evenement/composer.json @@ -13,17 +13,17 @@ "php": ">=7.0" }, "require-dev": { - "phpunit/phpunit": "^9 || ^6" + "phpunit/phpunit": "^6.0" }, "autoload": { - "psr-4": { - "Evenement\\": "src/" + "psr-0": { + "Evenement": "src" } }, "autoload-dev": { - "psr-4": { - "Evenement\\Tests\\": "tests/" + "psr-0": { + "Evenement": "tests" }, - "files": ["tests/functions.php"] + "files": ["tests/Evenement/Tests/functions.php"] } } diff --git a/deps/vendor/evenement/evenement/doc/00-intro.md b/deps/vendor/evenement/evenement/doc/00-intro.md new file mode 100644 index 000000000..6c28a2ab2 --- /dev/null +++ b/deps/vendor/evenement/evenement/doc/00-intro.md @@ -0,0 +1,28 @@ +# Introduction + +Événement is is French and means "event". The événement library aims to +provide a simple way of subscribing to events and notifying those subscribers +whenever an event occurs. + +The API that it exposes is almost a direct port of the EventEmitter API found +in node.js. It also includes an "EventEmitter". There are some minor +differences however. + +The EventEmitter is an implementation of the publish-subscribe pattern, which +is a generalized version of the observer pattern. The observer pattern +specifies an observable subject, which observers can register themselves to. +Once something interesting happens, the subject notifies its observers. + +Pub/sub takes the same idea but encapsulates the observation logic inside a +separate object which manages all of its subscribers or listeners. Subscribers +are bound to an event name, and will only receive notifications of the events +they subscribed to. + +**TLDR: What does evenement do, in short? It provides a mapping from event +names to a list of listener functions and triggers each listener for a given +event when it is emitted.** + +Why do we do this, you ask? To achieve decoupling. + +It allows you to design a system where the core will emit events, and modules +are able to subscribe to these events. And respond to them. diff --git a/deps/vendor/evenement/evenement/doc/01-api.md b/deps/vendor/evenement/evenement/doc/01-api.md new file mode 100644 index 000000000..17ba333ec --- /dev/null +++ b/deps/vendor/evenement/evenement/doc/01-api.md @@ -0,0 +1,91 @@ +# API + +The API that événement exposes is defined by the +`Evenement\EventEmitterInterface`. The interface is useful if you want to +define an interface that extends the emitter and implicitly defines certain +events to be emitted, or if you want to type hint an `EventEmitter` to be +passed to a method without coupling to the specific implementation. + +## on($event, callable $listener) + +Allows you to subscribe to an event. + +Example: + +```php +$emitter->on('user.created', function (User $user) use ($logger) { + $logger->log(sprintf("User '%s' was created.", $user->getLogin())); +}); +``` + +Since the listener can be any callable, you could also use an instance method +instead of the anonymous function: + +```php +$loggerSubscriber = new LoggerSubscriber($logger); +$emitter->on('user.created', array($loggerSubscriber, 'onUserCreated')); +``` + +This has the benefit that listener does not even need to know that the emitter +exists. + +You can also accept more than one parameter for the listener: + +```php +$emitter->on('numbers_added', function ($result, $a, $b) {}); +``` + +## once($event, callable $listener) + +Convenience method that adds a listener which is guaranteed to only be called +once. + +Example: + +```php +$conn->once('connected', function () use ($conn, $data) { + $conn->send($data); +}); +``` + +## emit($event, array $arguments = []) + +Emit an event, which will call all listeners. + +Example: + +```php +$conn->emit('data', [$data]); +``` + +The second argument to emit is an array of listener arguments. This is how you +specify more args: + +```php +$result = $a + $b; +$emitter->emit('numbers_added', [$result, $a, $b]); +``` + +## listeners($event) + +Allows you to inspect the listeners attached to an event. Particularly useful +to check if there are any listeners at all. + +Example: + +```php +$e = new \RuntimeException('Everything is broken!'); +if (0 === count($emitter->listeners('error'))) { + throw $e; +} +``` + +## removeListener($event, callable $listener) + +Remove a specific listener for a specific event. + +## removeAllListeners($event = null) + +Remove all listeners for a specific event or all listeners all together. This +is useful for long-running processes, where you want to remove listeners in +order to allow them to get garbage collected. diff --git a/deps/vendor/evenement/evenement/doc/02-plugin-system.md b/deps/vendor/evenement/evenement/doc/02-plugin-system.md new file mode 100644 index 000000000..6a0837193 --- /dev/null +++ b/deps/vendor/evenement/evenement/doc/02-plugin-system.md @@ -0,0 +1,155 @@ +# Example: Plugin system + +In this example I will show you how to create a generic plugin system with +événement where plugins can alter the behaviour of the app. The app is a blog. +Boring, I know. By using the EventEmitter it will be easy to extend this blog +with additional functionality without modifying the core system. + +The blog is quite basic. Users are able to create blog posts when they log in. +The users are stored in a static config file, so there is no sign up process. +Once logged in they get a "new post" link which gives them a form where they +can create a new blog post with plain HTML. That will store the post in a +document database. The index lists all blog post titles by date descending. +Clicking on the post title will take you to the full post. + +## Plugin structure + +The goal of the plugin system is to allow features to be added to the blog +without modifying any core files of the blog. + +The plugins are managed through a config file, `plugins.json`. This JSON file +contains a JSON-encoded list of class-names for plugin classes. This allows +you to enable and disable plugins in a central location. The initial +`plugins.json` is just an empty array: +```json +[] +``` + +A plugin class must implement the `PluginInterface`: +```php +interface PluginInterface +{ + function attachEvents(EventEmitterInterface $emitter); +} +``` + +The `attachEvents` method allows the plugin to attach any events to the +emitter. For example: +```php +class FooPlugin implements PluginInterface +{ + public function attachEvents(EventEmitterInterface $emitter) + { + $emitter->on('foo', function () { + echo 'bar!'; + }); + } +} +``` + +The blog system creates an emitter instance and loads the plugins: +```php +$emitter = new EventEmitter(); + +$pluginClasses = json_decode(file_get_contents('plugins.json'), true); +foreach ($pluginClasses as $pluginClass) { + $plugin = new $pluginClass(); + $pluginClass->attachEvents($emitter); +} +``` + +This is the base system. There are no plugins yet, and there are no events yet +either. That's because I don't know which extension points will be needed. I +will add them on demand. + +## Feature: Markdown + +Writing blog posts in HTML sucks! Wouldn't it be great if I could write them +in a nice format such as markdown, and have that be converted to HTML for me? + +This feature will need two extension points. I need to be able to mark posts +as markdown, and I need to be able to hook into the rendering of the post body +and convert it from markdown to HTML. So the blog needs two new events: +`post.create` and `post.render`. + +In the code that creates the post, I'll insert the `post.create` event: +```php +class PostEvent +{ + public $post; + + public function __construct(array $post) + { + $this->post = $post; + } +} + +$post = createPostFromRequest($_POST); + +$event = new PostEvent($post); +$emitter->emit('post.create', [$event]); +$post = $event->post; + +$db->save('post', $post); +``` + +This shows that you can wrap a value in an event object to make it mutable, +allowing listeners to change it. + +The same thing for the `post.render` event: +```php +public function renderPostBody(array $post) +{ + $emitter = $this->emitter; + + $event = new PostEvent($post); + $emitter->emit('post.render', [$event]); + $post = $event->post; + + return $post['body']; +} + +

+

+``` + +Ok, the events are in place. It's time to create the first plugin, woohoo! I +will call this the `MarkdownPlugin`, so here's `plugins.json`: +```json +[ + "MarkdownPlugin" +] +``` + +The `MarkdownPlugin` class will be autoloaded, so I don't have to worry about +including any files. I just have to worry about implementing the plugin class. +The `markdown` function represents a markdown to HTML converter. +```php +class MarkdownPlugin implements PluginInterface +{ + public function attachEvents(EventEmitterInterface $emitter) + { + $emitter->on('post.create', function (PostEvent $event) { + $event->post['format'] = 'markdown'; + }); + + $emitter->on('post.render', function (PostEvent $event) { + if (isset($event->post['format']) && 'markdown' === $event->post['format']) { + $event->post['body'] = markdown($event->post['body']); + } + }); + } +} +``` + +There you go, the blog now renders posts as markdown. But all of the previous +posts before the addition of the markdown plugin are still rendered correctly +as raw HTML. + +## Feature: Comments + +TODO + +## Feature: Comment spam control + +TODO diff --git a/deps/vendor/evenement/evenement/examples/benchmark-emit-no-arguments.php b/deps/vendor/evenement/evenement/examples/benchmark-emit-no-arguments.php new file mode 100644 index 000000000..53d7f4b22 --- /dev/null +++ b/deps/vendor/evenement/evenement/examples/benchmark-emit-no-arguments.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +const ITERATIONS = 10000000; + +use Evenement\EventEmitter; + +require __DIR__.'/../vendor/autoload.php'; + +$emitter = new EventEmitter(); + +$emitter->on('event', function () {}); + +$start = microtime(true); +for ($i = 0; $i < ITERATIONS; $i++) { + $emitter->emit('event'); +} +$time = microtime(true) - $start; + +echo 'Emitting ', number_format(ITERATIONS), ' events took: ', number_format($time, 2), 's', PHP_EOL; diff --git a/deps/vendor/evenement/evenement/examples/benchmark-emit-once.php b/deps/vendor/evenement/evenement/examples/benchmark-emit-once.php new file mode 100644 index 000000000..74f4d1755 --- /dev/null +++ b/deps/vendor/evenement/evenement/examples/benchmark-emit-once.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +ini_set('memory_limit', '512M'); + +const ITERATIONS = 100000; + +use Evenement\EventEmitter; + +require __DIR__.'/../vendor/autoload.php'; + +$emitter = new EventEmitter(); + +for ($i = 0; $i < ITERATIONS; $i++) { + $emitter->once('event', function ($a, $b, $c) {}); +} + +$start = microtime(true); +$emitter->emit('event', [1, 2, 3]); +$time = microtime(true) - $start; + +echo 'Emitting one event to ', number_format(ITERATIONS), ' once listeners took: ', number_format($time, 2), 's', PHP_EOL; diff --git a/deps/vendor/evenement/evenement/examples/benchmark-emit-one-argument.php b/deps/vendor/evenement/evenement/examples/benchmark-emit-one-argument.php new file mode 100644 index 000000000..39fc4ba09 --- /dev/null +++ b/deps/vendor/evenement/evenement/examples/benchmark-emit-one-argument.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +const ITERATIONS = 10000000; + +use Evenement\EventEmitter; + +require __DIR__.'/../vendor/autoload.php'; + +$emitter = new EventEmitter(); + +$emitter->on('event', function ($a) {}); + +$start = microtime(true); +for ($i = 0; $i < ITERATIONS; $i++) { + $emitter->emit('event', [1]); +} +$time = microtime(true) - $start; + +echo 'Emitting ', number_format(ITERATIONS), ' events took: ', number_format($time, 2), 's', PHP_EOL; diff --git a/deps/vendor/evenement/evenement/examples/benchmark-emit.php b/deps/vendor/evenement/evenement/examples/benchmark-emit.php new file mode 100644 index 000000000..3ab639e07 --- /dev/null +++ b/deps/vendor/evenement/evenement/examples/benchmark-emit.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +const ITERATIONS = 10000000; + +use Evenement\EventEmitter; + +require __DIR__.'/../vendor/autoload.php'; + +$emitter = new EventEmitter(); + +$emitter->on('event', function ($a, $b, $c) {}); + +$start = microtime(true); +for ($i = 0; $i < ITERATIONS; $i++) { + $emitter->emit('event', [1, 2, 3]); +} +$time = microtime(true) - $start; + +echo 'Emitting ', number_format(ITERATIONS), ' events took: ', number_format($time, 2), 's', PHP_EOL; diff --git a/deps/vendor/evenement/evenement/examples/benchmark-remove-listener-once.php b/deps/vendor/evenement/evenement/examples/benchmark-remove-listener-once.php new file mode 100644 index 000000000..414be3bd2 --- /dev/null +++ b/deps/vendor/evenement/evenement/examples/benchmark-remove-listener-once.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +ini_set('memory_limit', '512M'); + +const ITERATIONS = 100000; + +use Evenement\EventEmitter; + +require __DIR__.'/../vendor/autoload.php'; + +$emitter = new EventEmitter(); + +$listeners = []; +for ($i = 0; $i < ITERATIONS; $i++) { + $listeners[] = function ($a, $b, $c) {}; +} + +$start = microtime(true); +foreach ($listeners as $listener) { + $emitter->once('event', $listener); +} +$time = microtime(true) - $start; +echo 'Adding ', number_format(ITERATIONS), ' once listeners took: ', number_format($time, 2), 's', PHP_EOL; + +$start = microtime(true); +foreach ($listeners as $listener) { + $emitter->removeListener('event', $listener); +} +$time = microtime(true) - $start; +echo 'Removing ', number_format(ITERATIONS), ' once listeners took: ', number_format($time, 2), 's', PHP_EOL; diff --git a/deps/vendor/evenement/evenement/phpunit.xml.dist b/deps/vendor/evenement/evenement/phpunit.xml.dist new file mode 100644 index 000000000..70bc693a5 --- /dev/null +++ b/deps/vendor/evenement/evenement/phpunit.xml.dist @@ -0,0 +1,24 @@ + + + + + + ./tests/Evenement/ + + + + + + ./src/ + + + diff --git a/deps/vendor/evenement/evenement/src/EventEmitter.php b/deps/vendor/evenement/evenement/src/Evenement/EventEmitter.php similarity index 100% rename from deps/vendor/evenement/evenement/src/EventEmitter.php rename to deps/vendor/evenement/evenement/src/Evenement/EventEmitter.php diff --git a/deps/vendor/evenement/evenement/src/EventEmitterInterface.php b/deps/vendor/evenement/evenement/src/Evenement/EventEmitterInterface.php similarity index 100% rename from deps/vendor/evenement/evenement/src/EventEmitterInterface.php rename to deps/vendor/evenement/evenement/src/Evenement/EventEmitterInterface.php diff --git a/deps/vendor/evenement/evenement/src/EventEmitterTrait.php b/deps/vendor/evenement/evenement/src/Evenement/EventEmitterTrait.php similarity index 75% rename from deps/vendor/evenement/evenement/src/EventEmitterTrait.php rename to deps/vendor/evenement/evenement/src/Evenement/EventEmitterTrait.php index 150342960..a78e65ca5 100644 --- a/deps/vendor/evenement/evenement/src/EventEmitterTrait.php +++ b/deps/vendor/evenement/evenement/src/Evenement/EventEmitterTrait.php @@ -13,13 +13,6 @@ use InvalidArgumentException; -use function count; -use function array_keys; -use function array_merge; -use function array_search; -use function array_unique; -use function array_values; - trait EventEmitterTrait { protected $listeners = []; @@ -62,20 +55,20 @@ public function removeListener($event, callable $listener) } if (isset($this->listeners[$event])) { - $index = array_search($listener, $this->listeners[$event], true); + $index = \array_search($listener, $this->listeners[$event], true); if (false !== $index) { unset($this->listeners[$event][$index]); - if (count($this->listeners[$event]) === 0) { + if (\count($this->listeners[$event]) === 0) { unset($this->listeners[$event]); } } } if (isset($this->onceListeners[$event])) { - $index = array_search($listener, $this->onceListeners[$event], true); + $index = \array_search($listener, $this->onceListeners[$event], true); if (false !== $index) { unset($this->onceListeners[$event][$index]); - if (count($this->onceListeners[$event]) === 0) { + if (\count($this->onceListeners[$event]) === 0) { unset($this->onceListeners[$event]); } } @@ -101,14 +94,11 @@ public function listeners($event = null): array { if ($event === null) { $events = []; - $eventNames = array_unique( - array_merge( - array_keys($this->listeners), - array_keys($this->onceListeners) - ) + $eventNames = \array_unique( + \array_merge(\array_keys($this->listeners), \array_keys($this->onceListeners)) ); foreach ($eventNames as $eventName) { - $events[$eventName] = array_merge( + $events[$eventName] = \array_merge( isset($this->listeners[$eventName]) ? $this->listeners[$eventName] : [], isset($this->onceListeners[$eventName]) ? $this->onceListeners[$eventName] : [] ); @@ -116,7 +106,7 @@ public function listeners($event = null): array return $events; } - return array_merge( + return \array_merge( isset($this->listeners[$event]) ? $this->listeners[$event] : [], isset($this->onceListeners[$event]) ? $this->onceListeners[$event] : [] ); @@ -128,25 +118,16 @@ public function emit($event, array $arguments = []) throw new InvalidArgumentException('event name must not be null'); } - $listeners = []; if (isset($this->listeners[$event])) { - $listeners = array_values($this->listeners[$event]); - } - - $onceListeners = []; - if (isset($this->onceListeners[$event])) { - $onceListeners = array_values($this->onceListeners[$event]); - } - - if(empty($listeners) === false) { - foreach ($listeners as $listener) { + foreach ($this->listeners[$event] as $listener) { $listener(...$arguments); } } - if(empty($onceListeners) === false) { + if (isset($this->onceListeners[$event])) { + $listeners = $this->onceListeners[$event]; unset($this->onceListeners[$event]); - foreach ($onceListeners as $listener) { + foreach ($listeners as $listener) { $listener(...$arguments); } } diff --git a/deps/vendor/evenement/evenement/tests/Evenement/Tests/EventEmitterTest.php b/deps/vendor/evenement/evenement/tests/Evenement/Tests/EventEmitterTest.php new file mode 100644 index 000000000..28f3011d6 --- /dev/null +++ b/deps/vendor/evenement/evenement/tests/Evenement/Tests/EventEmitterTest.php @@ -0,0 +1,438 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Evenement\Tests; + +use Evenement\EventEmitter; +use InvalidArgumentException; +use PHPUnit\Framework\TestCase; + +class EventEmitterTest extends TestCase +{ + private $emitter; + + public function setUp() + { + $this->emitter = new EventEmitter(); + } + + public function testAddListenerWithLambda() + { + $this->emitter->on('foo', function () {}); + } + + public function testAddListenerWithMethod() + { + $listener = new Listener(); + $this->emitter->on('foo', [$listener, 'onFoo']); + } + + public function testAddListenerWithStaticMethod() + { + $this->emitter->on('bar', ['Evenement\Tests\Listener', 'onBar']); + } + + public function testAddListenerWithInvalidListener() + { + try { + $this->emitter->on('foo', 'not a callable'); + $this->fail(); + } catch (\Exception $e) { + } catch (\TypeError $e) { + } + } + + public function testOnce() + { + $listenerCalled = 0; + + $this->emitter->once('foo', function () use (&$listenerCalled) { + $listenerCalled++; + }); + + $this->assertSame(0, $listenerCalled); + + $this->emitter->emit('foo'); + + $this->assertSame(1, $listenerCalled); + + $this->emitter->emit('foo'); + + $this->assertSame(1, $listenerCalled); + } + + public function testOnceWithArguments() + { + $capturedArgs = []; + + $this->emitter->once('foo', function ($a, $b) use (&$capturedArgs) { + $capturedArgs = array($a, $b); + }); + + $this->emitter->emit('foo', array('a', 'b')); + + $this->assertSame(array('a', 'b'), $capturedArgs); + } + + public function testEmitWithoutArguments() + { + $listenerCalled = false; + + $this->emitter->on('foo', function () use (&$listenerCalled) { + $listenerCalled = true; + }); + + $this->assertSame(false, $listenerCalled); + $this->emitter->emit('foo'); + $this->assertSame(true, $listenerCalled); + } + + public function testEmitWithOneArgument() + { + $test = $this; + + $listenerCalled = false; + + $this->emitter->on('foo', function ($value) use (&$listenerCalled, $test) { + $listenerCalled = true; + + $test->assertSame('bar', $value); + }); + + $this->assertSame(false, $listenerCalled); + $this->emitter->emit('foo', ['bar']); + $this->assertSame(true, $listenerCalled); + } + + public function testEmitWithTwoArguments() + { + $test = $this; + + $listenerCalled = false; + + $this->emitter->on('foo', function ($arg1, $arg2) use (&$listenerCalled, $test) { + $listenerCalled = true; + + $test->assertSame('bar', $arg1); + $test->assertSame('baz', $arg2); + }); + + $this->assertSame(false, $listenerCalled); + $this->emitter->emit('foo', ['bar', 'baz']); + $this->assertSame(true, $listenerCalled); + } + + public function testEmitWithNoListeners() + { + $this->emitter->emit('foo'); + $this->emitter->emit('foo', ['bar']); + $this->emitter->emit('foo', ['bar', 'baz']); + } + + public function testEmitWithTwoListeners() + { + $listenersCalled = 0; + + $this->emitter->on('foo', function () use (&$listenersCalled) { + $listenersCalled++; + }); + + $this->emitter->on('foo', function () use (&$listenersCalled) { + $listenersCalled++; + }); + + $this->assertSame(0, $listenersCalled); + $this->emitter->emit('foo'); + $this->assertSame(2, $listenersCalled); + } + + public function testRemoveListenerMatching() + { + $listenersCalled = 0; + + $listener = function () use (&$listenersCalled) { + $listenersCalled++; + }; + + $this->emitter->on('foo', $listener); + $this->emitter->removeListener('foo', $listener); + + $this->assertSame(0, $listenersCalled); + $this->emitter->emit('foo'); + $this->assertSame(0, $listenersCalled); + } + + public function testRemoveListenerNotMatching() + { + $listenersCalled = 0; + + $listener = function () use (&$listenersCalled) { + $listenersCalled++; + }; + + $this->emitter->on('foo', $listener); + $this->emitter->removeListener('bar', $listener); + + $this->assertSame(0, $listenersCalled); + $this->emitter->emit('foo'); + $this->assertSame(1, $listenersCalled); + } + + public function testRemoveAllListenersMatching() + { + $listenersCalled = 0; + + $this->emitter->on('foo', function () use (&$listenersCalled) { + $listenersCalled++; + }); + + $this->emitter->removeAllListeners('foo'); + + $this->assertSame(0, $listenersCalled); + $this->emitter->emit('foo'); + $this->assertSame(0, $listenersCalled); + } + + public function testRemoveAllListenersNotMatching() + { + $listenersCalled = 0; + + $this->emitter->on('foo', function () use (&$listenersCalled) { + $listenersCalled++; + }); + + $this->emitter->removeAllListeners('bar'); + + $this->assertSame(0, $listenersCalled); + $this->emitter->emit('foo'); + $this->assertSame(1, $listenersCalled); + } + + public function testRemoveAllListenersWithoutArguments() + { + $listenersCalled = 0; + + $this->emitter->on('foo', function () use (&$listenersCalled) { + $listenersCalled++; + }); + + $this->emitter->on('bar', function () use (&$listenersCalled) { + $listenersCalled++; + }); + + $this->emitter->removeAllListeners(); + + $this->assertSame(0, $listenersCalled); + $this->emitter->emit('foo'); + $this->emitter->emit('bar'); + $this->assertSame(0, $listenersCalled); + } + + public function testCallablesClosure() + { + $calledWith = null; + + $this->emitter->on('foo', function ($data) use (&$calledWith) { + $calledWith = $data; + }); + + $this->emitter->emit('foo', ['bar']); + + self::assertSame('bar', $calledWith); + } + + public function testCallablesClass() + { + $listener = new Listener(); + $this->emitter->on('foo', [$listener, 'onFoo']); + + $this->emitter->emit('foo', ['bar']); + + self::assertSame(['bar'], $listener->getData()); + } + + + public function testCallablesClassInvoke() + { + $listener = new Listener(); + $this->emitter->on('foo', $listener); + + $this->emitter->emit('foo', ['bar']); + + self::assertSame(['bar'], $listener->getMagicData()); + } + + public function testCallablesStaticClass() + { + $this->emitter->on('foo', '\Evenement\Tests\Listener::onBar'); + + $this->emitter->emit('foo', ['bar']); + + self::assertSame(['bar'], Listener::getStaticData()); + } + + public function testCallablesFunction() + { + $this->emitter->on('foo', '\Evenement\Tests\setGlobalTestData'); + + $this->emitter->emit('foo', ['bar']); + + self::assertSame('bar', $GLOBALS['evenement-evenement-test-data']); + + unset($GLOBALS['evenement-evenement-test-data']); + } + + public function testListeners() + { + $onA = function () {}; + $onB = function () {}; + $onC = function () {}; + $onceA = function () {}; + $onceB = function () {}; + $onceC = function () {}; + + self::assertCount(0, $this->emitter->listeners('event')); + $this->emitter->on('event', $onA); + self::assertCount(1, $this->emitter->listeners('event')); + self::assertSame([$onA], $this->emitter->listeners('event')); + $this->emitter->once('event', $onceA); + self::assertCount(2, $this->emitter->listeners('event')); + self::assertSame([$onA, $onceA], $this->emitter->listeners('event')); + $this->emitter->once('event', $onceB); + self::assertCount(3, $this->emitter->listeners('event')); + self::assertSame([$onA, $onceA, $onceB], $this->emitter->listeners('event')); + $this->emitter->on('event', $onB); + self::assertCount(4, $this->emitter->listeners('event')); + self::assertSame([$onA, $onB, $onceA, $onceB], $this->emitter->listeners('event')); + $this->emitter->removeListener('event', $onceA); + self::assertCount(3, $this->emitter->listeners('event')); + self::assertSame([$onA, $onB, $onceB], $this->emitter->listeners('event')); + $this->emitter->once('event', $onceC); + self::assertCount(4, $this->emitter->listeners('event')); + self::assertSame([$onA, $onB, $onceB, $onceC], $this->emitter->listeners('event')); + $this->emitter->on('event', $onC); + self::assertCount(5, $this->emitter->listeners('event')); + self::assertSame([$onA, $onB, $onC, $onceB, $onceC], $this->emitter->listeners('event')); + $this->emitter->once('event', $onceA); + self::assertCount(6, $this->emitter->listeners('event')); + self::assertSame([$onA, $onB, $onC, $onceB, $onceC, $onceA], $this->emitter->listeners('event')); + $this->emitter->removeListener('event', $onB); + self::assertCount(5, $this->emitter->listeners('event')); + self::assertSame([$onA, $onC, $onceB, $onceC, $onceA], $this->emitter->listeners('event')); + $this->emitter->emit('event'); + self::assertCount(2, $this->emitter->listeners('event')); + self::assertSame([$onA, $onC], $this->emitter->listeners('event')); + } + + public function testOnceCallIsNotRemovedWhenWorkingOverOnceListeners() + { + $aCalled = false; + $aCallable = function () use (&$aCalled) { + $aCalled = true; + }; + $bCalled = false; + $bCallable = function () use (&$bCalled, $aCallable) { + $bCalled = true; + $this->emitter->once('event', $aCallable); + }; + $this->emitter->once('event', $bCallable); + + self::assertFalse($aCalled); + self::assertFalse($bCalled); + $this->emitter->emit('event'); + + self::assertFalse($aCalled); + self::assertTrue($bCalled); + $this->emitter->emit('event'); + + self::assertTrue($aCalled); + self::assertTrue($bCalled); + } + + public function testEventNameMustBeStringOn() + { + self::expectException(InvalidArgumentException::class); + self::expectExceptionMessage('event name must not be null'); + + $this->emitter->on(null, function () {}); + } + + public function testEventNameMustBeStringOnce() + { + self::expectException(InvalidArgumentException::class); + self::expectExceptionMessage('event name must not be null'); + + $this->emitter->once(null, function () {}); + } + + public function testEventNameMustBeStringRemoveListener() + { + self::expectException(InvalidArgumentException::class); + self::expectExceptionMessage('event name must not be null'); + + $this->emitter->removeListener(null, function () {}); + } + + public function testEventNameMustBeStringEmit() + { + self::expectException(InvalidArgumentException::class); + self::expectExceptionMessage('event name must not be null'); + + $this->emitter->emit(null); + } + + public function testListenersGetAll() + { + $a = function () {}; + $b = function () {}; + $c = function () {}; + $d = function () {}; + + $this->emitter->once('event2', $c); + $this->emitter->on('event', $a); + $this->emitter->once('event', $b); + $this->emitter->on('event', $c); + $this->emitter->once('event', $d); + + self::assertSame( + [ + 'event' => [ + $a, + $c, + $b, + $d, + ], + 'event2' => [ + $c, + ], + ], + $this->emitter->listeners() + ); + } + + public function testOnceNestedCallRegression() + { + $first = 0; + $second = 0; + + $this->emitter->once('event', function () use (&$first, &$second) { + $first++; + $this->emitter->once('event', function () use (&$second) { + $second++; + }); + $this->emitter->emit('event'); + }); + $this->emitter->emit('event'); + + self::assertSame(1, $first); + self::assertSame(1, $second); + } +} diff --git a/deps/vendor/evenement/evenement/tests/Evenement/Tests/Listener.php b/deps/vendor/evenement/evenement/tests/Evenement/Tests/Listener.php new file mode 100644 index 000000000..df1742465 --- /dev/null +++ b/deps/vendor/evenement/evenement/tests/Evenement/Tests/Listener.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Evenement\Tests; + +class Listener +{ + private $data = []; + + private $magicData = []; + + private static $staticData = []; + + public function onFoo($data) + { + $this->data[] = $data; + } + + public function __invoke($data) + { + $this->magicData[] = $data; + } + + public static function onBar($data) + { + self::$staticData[] = $data; + } + + public function getData() + { + return $this->data; + } + + public function getMagicData() + { + return $this->magicData; + } + + public static function getStaticData() + { + return self::$staticData; + } +} diff --git a/deps/vendor/evenement/evenement/tests/Evenement/Tests/functions.php b/deps/vendor/evenement/evenement/tests/Evenement/Tests/functions.php new file mode 100644 index 000000000..7f11f5ba9 --- /dev/null +++ b/deps/vendor/evenement/evenement/tests/Evenement/Tests/functions.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Evenement\Tests; + +function setGlobalTestData($data) +{ + $GLOBALS['evenement-evenement-test-data'] = $data; +} diff --git a/deps/vendor/justinrainbow/json-schema/.php_cs.dist b/deps/vendor/justinrainbow/json-schema/.php_cs.dist new file mode 100644 index 000000000..a9e7e4ed1 --- /dev/null +++ b/deps/vendor/justinrainbow/json-schema/.php_cs.dist @@ -0,0 +1,34 @@ +in(__DIR__); + +/* Based on ^2.1 of php-cs-fixer */ +$config + ->setRules(array( + // default + '@PSR2' => true, + '@Symfony' => true, + // additionally + 'array_syntax' => array('syntax' => 'long'), + 'binary_operator_spaces' => false, + 'concat_space' => array('spacing' => 'one'), + 'no_useless_else' => true, + 'no_useless_return' => true, + 'ordered_imports' => true, + 'phpdoc_no_package' => false, + 'phpdoc_order' => true, + 'phpdoc_summary' => false, + 'pre_increment' => false, + 'increment_style' => false, + 'simplified_null_return' => false, + 'trailing_comma_in_multiline_array' => false, + 'yoda_style' => false, + 'phpdoc_types_order' => array('null_adjustment' => 'none', 'sort_algorithm' => 'none'), + 'no_superfluous_phpdoc_tags' => false, + )) + ->setFinder($finder) +; + +return $config; diff --git a/deps/vendor/justinrainbow/json-schema/composer.json b/deps/vendor/justinrainbow/json-schema/composer.json index 8c322670e..fcacd40c3 100644 --- a/deps/vendor/justinrainbow/json-schema/composer.json +++ b/deps/vendor/justinrainbow/json-schema/composer.json @@ -27,13 +27,18 @@ } ], "require": { - "php": ">=7.1" + "php": ">=5.3.3" }, "require-dev": { "friendsofphp/php-cs-fixer": "~2.2.20||~2.15.1", "json-schema/json-schema-test-suite": "1.2.0", "phpunit/phpunit": "^4.8.35" }, + "extra": { + "branch-alias": { + "dev-master": "5.0.x-dev" + } + }, "autoload": { "psr-4": { "JsonSchema\\": "src/JsonSchema/" @@ -62,10 +67,10 @@ "bin/validate-json" ], "scripts": { - "coverage": "@php phpunit --coverage-text", - "style-check": "@php php-cs-fixer fix --dry-run --verbose --diff", - "style-fix": "@php php-cs-fixer fix --verbose", - "test": "@php phpunit", - "testOnly": "@php phpunit --colors --filter" + "coverage": "phpunit --coverage-text", + "style-check": "php-cs-fixer fix --dry-run --verbose --diff", + "style-fix": "php-cs-fixer fix --verbose", + "test": "phpunit", + "testOnly": "phpunit --colors --filter" } } diff --git a/deps/vendor/justinrainbow/json-schema/demo/README.md b/deps/vendor/justinrainbow/json-schema/demo/README.md new file mode 100644 index 000000000..0309ee89f --- /dev/null +++ b/deps/vendor/justinrainbow/json-schema/demo/README.md @@ -0,0 +1,14 @@ +## JsonSchema\Validator Demo + +This demo script uses the example from the root README.md and provides sample JSON files for testing `JsonSchema\Validator`. + +To change or replace the JSON schema document, please edit `/path/to/json-schema/demo/schema.json`. + +To change or replace the JSON document that is validated, please edit `/path/to/json-schema/demo/data.json`. + +To run the demo, change the path in the following example and run it in your terminal. + +``` +cd /path/to/json-schema/demo +php demo.php // The supplied JSON validates against the schema. +``` diff --git a/deps/vendor/justinrainbow/json-schema/demo/data.json b/deps/vendor/justinrainbow/json-schema/demo/data.json new file mode 100644 index 000000000..69591b710 --- /dev/null +++ b/deps/vendor/justinrainbow/json-schema/demo/data.json @@ -0,0 +1,3 @@ +{ + "foo":"bar" +} diff --git a/deps/vendor/justinrainbow/json-schema/demo/demo.php b/deps/vendor/justinrainbow/json-schema/demo/demo.php new file mode 100644 index 000000000..98b518a7b --- /dev/null +++ b/deps/vendor/justinrainbow/json-schema/demo/demo.php @@ -0,0 +1,18 @@ +check($data, (object) array('$ref' => 'file://' . realpath('schema.json'))); + +if ($validator->isValid()) { + echo "The supplied JSON validates against the schema.\n"; +} else { + echo "JSON does not validate. Violations:\n"; + foreach ($validator->getErrors() as $error) { + echo sprintf("[%s] %s\n", $error['property'], $error['message']); + } +} diff --git a/deps/vendor/justinrainbow/json-schema/demo/schema.json b/deps/vendor/justinrainbow/json-schema/demo/schema.json new file mode 100644 index 000000000..e6307dc1c --- /dev/null +++ b/deps/vendor/justinrainbow/json-schema/demo/schema.json @@ -0,0 +1,3 @@ +{ + "type": "object" +} diff --git a/deps/vendor/justinrainbow/json-schema/phpunit.xml.dist b/deps/vendor/justinrainbow/json-schema/phpunit.xml.dist new file mode 100644 index 000000000..0136d8edc --- /dev/null +++ b/deps/vendor/justinrainbow/json-schema/phpunit.xml.dist @@ -0,0 +1,26 @@ + + + + + + tests + + + + + + ./src/JsonSchema/ + + + diff --git a/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/BaseConstraint.php b/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/BaseConstraint.php index 9a4ea1e5a..63968213e 100644 --- a/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/BaseConstraint.php +++ b/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/BaseConstraint.php @@ -38,12 +38,12 @@ class BaseConstraint /** * @param Factory $factory */ - public function __construct(?Factory $factory = null) + public function __construct(Factory $factory = null) { $this->factory = $factory ?: new Factory(); } - public function addError(?JsonPointer $path, $message, $constraint = '', ?array $more = null) + public function addError(JsonPointer $path = null, $message, $constraint = '', array $more = null) { $error = array( 'property' => $this->convertJsonPointerIntoPropertyPath($path ?: new JsonPointer('')), diff --git a/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/CollectionConstraint.php b/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/CollectionConstraint.php index a5ddd35b8..d1384b884 100644 --- a/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/CollectionConstraint.php +++ b/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/CollectionConstraint.php @@ -22,7 +22,7 @@ class CollectionConstraint extends Constraint /** * {@inheritdoc} */ - public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null) + public function check(&$value, $schema = null, JsonPointer $path = null, $i = null) { // Verify minItems if (isset($schema->minItems) && count($value) < $schema->minItems) { @@ -61,7 +61,7 @@ public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = n * @param JsonPointer|null $path * @param string $i */ - protected function validateItems(&$value, $schema = null, ?JsonPointer $path = null, $i = null) + protected function validateItems(&$value, $schema = null, JsonPointer $path = null, $i = null) { if (is_object($schema->items)) { // just one type definition for the whole array diff --git a/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php b/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php index 5aaa718c2..c61b89ad2 100644 --- a/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php +++ b/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php @@ -39,7 +39,7 @@ abstract class Constraint extends BaseConstraint implements ConstraintInterface * * @return JsonPointer; */ - protected function incrementPath(?JsonPointer $path, $i) + protected function incrementPath(JsonPointer $path = null, $i) { $path = $path ?: new JsonPointer(''); @@ -65,7 +65,7 @@ protected function incrementPath(?JsonPointer $path, $i) * @param JsonPointer|null $path * @param mixed $i */ - protected function checkArray(&$value, $schema = null, ?JsonPointer $path = null, $i = null) + protected function checkArray(&$value, $schema = null, JsonPointer $path = null, $i = null) { $validator = $this->factory->createInstanceFor('collection'); $validator->check($value, $schema, $path, $i); @@ -83,7 +83,7 @@ protected function checkArray(&$value, $schema = null, ?JsonPointer $path = null * @param mixed $additionalProperties * @param mixed $patternProperties */ - protected function checkObject(&$value, $schema = null, ?JsonPointer $path = null, $properties = null, + protected function checkObject(&$value, $schema = null, JsonPointer $path = null, $properties = null, $additionalProperties = null, $patternProperties = null, $appliedDefaults = array()) { $validator = $this->factory->createInstanceFor('object'); @@ -100,7 +100,7 @@ protected function checkObject(&$value, $schema = null, ?JsonPointer $path = nul * @param JsonPointer|null $path * @param mixed $i */ - protected function checkType(&$value, $schema = null, ?JsonPointer $path = null, $i = null) + protected function checkType(&$value, $schema = null, JsonPointer $path = null, $i = null) { $validator = $this->factory->createInstanceFor('type'); $validator->check($value, $schema, $path, $i); @@ -116,7 +116,7 @@ protected function checkType(&$value, $schema = null, ?JsonPointer $path = null, * @param JsonPointer|null $path * @param mixed $i */ - protected function checkUndefined(&$value, $schema = null, ?JsonPointer $path = null, $i = null, $fromDefault = false) + protected function checkUndefined(&$value, $schema = null, JsonPointer $path = null, $i = null, $fromDefault = false) { $validator = $this->factory->createInstanceFor('undefined'); @@ -133,7 +133,7 @@ protected function checkUndefined(&$value, $schema = null, ?JsonPointer $path = * @param JsonPointer|null $path * @param mixed $i */ - protected function checkString($value, $schema = null, ?JsonPointer $path = null, $i = null) + protected function checkString($value, $schema = null, JsonPointer $path = null, $i = null) { $validator = $this->factory->createInstanceFor('string'); $validator->check($value, $schema, $path, $i); @@ -149,7 +149,7 @@ protected function checkString($value, $schema = null, ?JsonPointer $path = null * @param JsonPointer $path * @param mixed $i */ - protected function checkNumber($value, $schema = null, ?JsonPointer $path = null, $i = null) + protected function checkNumber($value, $schema = null, JsonPointer $path = null, $i = null) { $validator = $this->factory->createInstanceFor('number'); $validator->check($value, $schema, $path, $i); @@ -165,7 +165,7 @@ protected function checkNumber($value, $schema = null, ?JsonPointer $path = null * @param JsonPointer|null $path * @param mixed $i */ - protected function checkEnum($value, $schema = null, ?JsonPointer $path = null, $i = null) + protected function checkEnum($value, $schema = null, JsonPointer $path = null, $i = null) { $validator = $this->factory->createInstanceFor('enum'); $validator->check($value, $schema, $path, $i); @@ -181,7 +181,7 @@ protected function checkEnum($value, $schema = null, ?JsonPointer $path = null, * @param JsonPointer|null $path * @param mixed $i */ - protected function checkFormat($value, $schema = null, ?JsonPointer $path = null, $i = null) + protected function checkFormat($value, $schema = null, JsonPointer $path = null, $i = null) { $validator = $this->factory->createInstanceFor('format'); $validator->check($value, $schema, $path, $i); diff --git a/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ConstraintInterface.php b/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ConstraintInterface.php index a5a235ad4..442268e68 100644 --- a/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ConstraintInterface.php +++ b/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ConstraintInterface.php @@ -40,7 +40,7 @@ public function addErrors(array $errors); * @param string $constraint the constraint/rule that is broken, e.g.: 'minLength' * @param array $more more array elements to add to the error */ - public function addError(?JsonPointer $path, $message, $constraint='', ?array $more = null); + public function addError(JsonPointer $path = null, $message, $constraint='', array $more = null); /** * checks if the validator has not raised errors @@ -61,5 +61,5 @@ public function isValid(); * * @throws \JsonSchema\Exception\ExceptionInterface */ - public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null); + public function check(&$value, $schema = null, JsonPointer $path = null, $i = null); } diff --git a/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/EnumConstraint.php b/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/EnumConstraint.php index da61c135b..0fd2b6a0a 100644 --- a/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/EnumConstraint.php +++ b/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/EnumConstraint.php @@ -22,7 +22,7 @@ class EnumConstraint extends Constraint /** * {@inheritdoc} */ - public function check(&$element, $schema = null, ?JsonPointer $path = null, $i = null) + public function check(&$element, $schema = null, JsonPointer $path = null, $i = null) { // Only validate enum if the attribute exists if ($element instanceof UndefinedConstraint && (!isset($schema->required) || !$schema->required)) { diff --git a/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Factory.php b/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Factory.php index 840854b30..4e771c19c 100644 --- a/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Factory.php +++ b/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Factory.php @@ -74,8 +74,8 @@ class Factory * @param int $checkMode */ public function __construct( - ?SchemaStorageInterface $schemaStorage = null, - ?UriRetrieverInterface $uriRetriever = null, + SchemaStorageInterface $schemaStorage = null, + UriRetrieverInterface $uriRetriever = null, $checkMode = Constraint::CHECK_MODE_NORMAL ) { // set provided config options diff --git a/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/FormatConstraint.php b/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/FormatConstraint.php index 29843e6c9..578cdb14d 100644 --- a/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/FormatConstraint.php +++ b/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/FormatConstraint.php @@ -24,7 +24,7 @@ class FormatConstraint extends Constraint /** * {@inheritdoc} */ - public function check(&$element, $schema = null, ?JsonPointer $path = null, $i = null) + public function check(&$element, $schema = null, JsonPointer $path = null, $i = null) { if (!isset($schema->format) || $this->factory->getConfig(self::CHECK_MODE_DISABLE_FORMAT)) { return; diff --git a/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/NumberConstraint.php b/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/NumberConstraint.php index b2ade8e21..d4c31a469 100644 --- a/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/NumberConstraint.php +++ b/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/NumberConstraint.php @@ -22,7 +22,7 @@ class NumberConstraint extends Constraint /** * {@inheritdoc} */ - public function check(&$element, $schema = null, ?JsonPointer $path = null, $i = null) + public function check(&$element, $schema = null, JsonPointer $path = null, $i = null) { // Verify minimum if (isset($schema->exclusiveMinimum)) { diff --git a/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ObjectConstraint.php b/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ObjectConstraint.php index e99c44bcc..0010d2941 100644 --- a/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ObjectConstraint.php +++ b/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ObjectConstraint.php @@ -27,7 +27,7 @@ class ObjectConstraint extends Constraint /** * {@inheritdoc} */ - public function check(&$element, $schema = null, ?JsonPointer $path = null, $properties = null, + public function check(&$element, $schema = null, JsonPointer $path = null, $properties = null, $additionalProp = null, $patternProperties = null, $appliedDefaults = array()) { if ($element instanceof UndefinedConstraint) { @@ -51,7 +51,7 @@ public function check(&$element, $schema = null, ?JsonPointer $path = null, $pro $this->validateElement($element, $matches, $schema, $path, $properties, $additionalProp); } - public function validatePatternProperties($element, ?JsonPointer $path, $patternProperties) + public function validatePatternProperties($element, JsonPointer $path = null, $patternProperties) { $try = array('/', '#', '+', '~', '%'); $matches = array(); @@ -90,7 +90,7 @@ public function validatePatternProperties($element, ?JsonPointer $path, $pattern * @param \StdClass $properties Properties * @param mixed $additionalProp Additional properties */ - public function validateElement($element, $matches, $schema = null, ?JsonPointer $path = null, + public function validateElement($element, $matches, $schema = null, JsonPointer $path = null, $properties = null, $additionalProp = null) { $this->validateMinMaxConstraint($element, $schema, $path); @@ -132,7 +132,7 @@ public function validateElement($element, $matches, $schema = null, ?JsonPointer * @param \stdClass $properties Property definitions * @param JsonPointer|null $path Path? */ - public function validateProperties(&$element, $properties = null, ?JsonPointer $path = null) + public function validateProperties(&$element, $properties = null, JsonPointer $path = null) { $undefinedConstraint = $this->factory->createInstanceFor('undefined'); @@ -174,7 +174,7 @@ protected function &getProperty(&$element, $property, $fallback = null) * @param \stdClass $objectDefinition ObjectConstraint definition * @param JsonPointer|null $path Path to test? */ - protected function validateMinMaxConstraint($element, $objectDefinition, ?JsonPointer $path = null) + protected function validateMinMaxConstraint($element, $objectDefinition, JsonPointer $path = null) { // Verify minimum number of properties if (isset($objectDefinition->minProperties) && !is_object($objectDefinition->minProperties)) { diff --git a/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/SchemaConstraint.php b/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/SchemaConstraint.php index 74979eb03..db665ad38 100644 --- a/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/SchemaConstraint.php +++ b/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/SchemaConstraint.php @@ -28,7 +28,7 @@ class SchemaConstraint extends Constraint /** * {@inheritdoc} */ - public function check(&$element, $schema = null, ?JsonPointer $path = null, $i = null) + public function check(&$element, $schema = null, JsonPointer $path = null, $i = null) { if ($schema !== null) { // passed schema diff --git a/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/StringConstraint.php b/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/StringConstraint.php index d6189ce0e..c66af1ed6 100644 --- a/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/StringConstraint.php +++ b/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/StringConstraint.php @@ -22,7 +22,7 @@ class StringConstraint extends Constraint /** * {@inheritdoc} */ - public function check(&$element, $schema = null, ?JsonPointer $path = null, $i = null) + public function check(&$element, $schema = null, JsonPointer $path = null, $i = null) { // Verify maxLength if (isset($schema->maxLength) && $this->strlen($element) > $schema->maxLength) { diff --git a/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeConstraint.php b/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeConstraint.php index 9940fd58d..0ef328431 100644 --- a/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeConstraint.php +++ b/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeConstraint.php @@ -39,7 +39,7 @@ class TypeConstraint extends Constraint /** * {@inheritdoc} */ - public function check(&$value = null, $schema = null, ?JsonPointer $path = null, $i = null) + public function check(&$value = null, $schema = null, JsonPointer $path = null, $i = null) { $type = isset($schema->type) ? $schema->type : null; $isValid = false; @@ -134,7 +134,7 @@ protected function implodeWith(array $elements, $delimiter = ', ', $listEnd = fa */ protected function validateTypeNameWording($type) { - if (!array_key_exists($type, self::$wording)) { + if (!isset(self::$wording[$type])) { throw new StandardUnexpectedValueException( sprintf( 'No wording for %s available, expected wordings are: [%s]', diff --git a/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/UndefinedConstraint.php b/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/UndefinedConstraint.php index 26e45f785..8effd4ba2 100644 --- a/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/UndefinedConstraint.php +++ b/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/UndefinedConstraint.php @@ -20,7 +20,6 @@ * @author Robert Schönthal * @author Bruno Prieto Reis */ -#[\AllowDynamicProperties] class UndefinedConstraint extends Constraint { /** @@ -31,7 +30,7 @@ class UndefinedConstraint extends Constraint /** * {@inheritdoc} */ - public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null, $fromDefault = false) + public function check(&$value, $schema = null, JsonPointer $path = null, $i = null, $fromDefault = false) { if (is_null($schema) || !is_object($schema)) { return; diff --git a/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Exception/JsonDecodingException.php b/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Exception/JsonDecodingException.php index 7641f61bf..c77198284 100644 --- a/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Exception/JsonDecodingException.php +++ b/deps/vendor/justinrainbow/json-schema/src/JsonSchema/Exception/JsonDecodingException.php @@ -14,7 +14,7 @@ */ class JsonDecodingException extends RuntimeException { - public function __construct($code = JSON_ERROR_NONE, ?\Exception $previous = null) + public function __construct($code = JSON_ERROR_NONE, \Exception $previous = null) { switch ($code) { case JSON_ERROR_DEPTH: diff --git a/deps/vendor/justinrainbow/json-schema/src/JsonSchema/SchemaStorage.php b/deps/vendor/justinrainbow/json-schema/src/JsonSchema/SchemaStorage.php index 36ba34947..31da6685f 100644 --- a/deps/vendor/justinrainbow/json-schema/src/JsonSchema/SchemaStorage.php +++ b/deps/vendor/justinrainbow/json-schema/src/JsonSchema/SchemaStorage.php @@ -17,8 +17,8 @@ class SchemaStorage implements SchemaStorageInterface protected $schemas = array(); public function __construct( - ?UriRetrieverInterface $uriRetriever = null, - ?UriResolverInterface $uriResolver = null + UriRetrieverInterface $uriRetriever = null, + UriResolverInterface $uriResolver = null ) { $this->uriRetriever = $uriRetriever ?: new UriRetriever(); $this->uriResolver = $uriResolver ?: new UriResolver(); diff --git a/deps/vendor/psr/container/composer.json b/deps/vendor/psr/container/composer.json index baf6cd1a0..3797a2538 100644 --- a/deps/vendor/psr/container/composer.json +++ b/deps/vendor/psr/container/composer.json @@ -12,16 +12,11 @@ } ], "require": { - "php": ">=7.4.0" + "php": ">=7.2.0" }, "autoload": { "psr-4": { "Psr\\Container\\": "src/" } - }, - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } } } diff --git a/deps/vendor/psr/container/src/ContainerExceptionInterface.php b/deps/vendor/psr/container/src/ContainerExceptionInterface.php index 0f213f2fe..cf10b8b4f 100644 --- a/deps/vendor/psr/container/src/ContainerExceptionInterface.php +++ b/deps/vendor/psr/container/src/ContainerExceptionInterface.php @@ -2,11 +2,9 @@ namespace Psr\Container; -use Throwable; - /** * Base interface representing a generic exception in a container. */ -interface ContainerExceptionInterface extends Throwable +interface ContainerExceptionInterface { } diff --git a/deps/vendor/psr/container/src/ContainerInterface.php b/deps/vendor/psr/container/src/ContainerInterface.php index b2cad4015..cf8e7fd33 100644 --- a/deps/vendor/psr/container/src/ContainerInterface.php +++ b/deps/vendor/psr/container/src/ContainerInterface.php @@ -32,5 +32,5 @@ public function get(string $id); * * @return bool */ - public function has(string $id): bool; + public function has(string $id); } diff --git a/deps/vendor/psr/http-message/README.md b/deps/vendor/psr/http-message/README.md index 2668be6c3..28185338f 100644 --- a/deps/vendor/psr/http-message/README.md +++ b/deps/vendor/psr/http-message/README.md @@ -10,7 +10,4 @@ interface that describes a HTTP message. See the specification for more details. Usage ----- -Before reading the usage guide we recommend reading the PSR-7 interfaces method list: - -* [`PSR-7 Interfaces Method List`](docs/PSR7-Interfaces.md) -* [`PSR-7 Usage Guide`](docs/PSR7-Usage.md) \ No newline at end of file +We'll certainly need some stuff in here. \ No newline at end of file diff --git a/deps/vendor/psr/http-message/composer.json b/deps/vendor/psr/http-message/composer.json index 56e8c0a6d..b0d2937a0 100644 --- a/deps/vendor/psr/http-message/composer.json +++ b/deps/vendor/psr/http-message/composer.json @@ -11,7 +11,7 @@ } ], "require": { - "php": "^7.2 || ^8.0" + "php": ">=5.3.0" }, "autoload": { "psr-4": { @@ -20,7 +20,7 @@ }, "extra": { "branch-alias": { - "dev-master": "1.1.x-dev" + "dev-master": "1.0.x-dev" } } } diff --git a/deps/vendor/psr/http-message/docs/PSR7-Interfaces.md b/deps/vendor/psr/http-message/docs/PSR7-Interfaces.md deleted file mode 100644 index 3a7e7dda6..000000000 --- a/deps/vendor/psr/http-message/docs/PSR7-Interfaces.md +++ /dev/null @@ -1,130 +0,0 @@ -# Interfaces - -The purpose of this list is to help in finding the methods when working with PSR-7. This can be considered as a cheatsheet for PSR-7 interfaces. - -The interfaces defined in PSR-7 are the following: - -| Class Name | Description | -|---|---| -| [Psr\Http\Message\MessageInterface](http://www.php-fig.org/psr/psr-7/#psrhttpmessagemessageinterface) | Representation of a HTTP message | -| [Psr\Http\Message\RequestInterface](http://www.php-fig.org/psr/psr-7/#psrhttpmessagerequestinterface) | Representation of an outgoing, client-side request. | -| [Psr\Http\Message\ServerRequestInterface](http://www.php-fig.org/psr/psr-7/#psrhttpmessageserverrequestinterface) | Representation of an incoming, server-side HTTP request. | -| [Psr\Http\Message\ResponseInterface](http://www.php-fig.org/psr/psr-7/#psrhttpmessageresponseinterface) | Representation of an outgoing, server-side response. | -| [Psr\Http\Message\StreamInterface](http://www.php-fig.org/psr/psr-7/#psrhttpmessagestreaminterface) | Describes a data stream | -| [Psr\Http\Message\UriInterface](http://www.php-fig.org/psr/psr-7/#psrhttpmessageuriinterface) | Value object representing a URI. | -| [Psr\Http\Message\UploadedFileInterface](http://www.php-fig.org/psr/psr-7/#psrhttpmessageuploadedfileinterface) | Value object representing a file uploaded through an HTTP request. | - -## `Psr\Http\Message\MessageInterface` Methods - -| Method Name | Description | Notes | -|------------------------------------| ----------- | ----- | -| `getProtocolVersion()` | Retrieve HTTP protocol version | 1.0 or 1.1 | -| `withProtocolVersion($version)` | Returns new message instance with given HTTP protocol version | | -| `getHeaders()` | Retrieve all HTTP Headers | [Request Header List](https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Request_fields), [Response Header List](https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Response_fields) | -| `hasHeader($name)` | Checks if HTTP Header with given name exists | | -| `getHeader($name)` | Retrieves a array with the values for a single header | | -| `getHeaderLine($name)` | Retrieves a comma-separated string of the values for a single header | | -| `withHeader($name, $value)` | Returns new message instance with given HTTP Header | if the header existed in the original instance, replaces the header value from the original message with the value provided when creating the new instance. | -| `withAddedHeader($name, $value)` | Returns new message instance with appended value to given header | If header already exists value will be appended, if not a new header will be created | -| `withoutHeader($name)` | Removes HTTP Header with given name| | -| `getBody()` | Retrieves the HTTP Message Body | Returns object implementing `StreamInterface`| -| `withBody(StreamInterface $body)` | Returns new message instance with given HTTP Message Body | | - - -## `Psr\Http\Message\RequestInterface` Methods - -Same methods as `Psr\Http\Message\MessageInterface` + the following methods: - -| Method Name | Description | Notes | -|------------------------------------| ----------- | ----- | -| `getRequestTarget()` | Retrieves the message's request target | origin-form, absolute-form, authority-form, asterisk-form ([RFC7230](https://www.rfc-editor.org/rfc/rfc7230.txt)) | -| `withRequestTarget($requestTarget)` | Return a new message instance with the specific request-target | | -| `getMethod()` | Retrieves the HTTP method of the request. | GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE (defined in [RFC7231](https://tools.ietf.org/html/rfc7231)), PATCH (defined in [RFC5789](https://tools.ietf.org/html/rfc5789)) | -| `withMethod($method)` | Returns a new message instance with the provided HTTP method | | -| `getUri()` | Retrieves the URI instance | | -| `withUri(UriInterface $uri, $preserveHost = false)` | Returns a new message instance with the provided URI | | - - -## `Psr\Http\Message\ServerRequestInterface` Methods - -Same methods as `Psr\Http\Message\RequestInterface` + the following methods: - -| Method Name | Description | Notes | -|------------------------------------| ----------- | ----- | -| `getServerParams() ` | Retrieve server parameters | Typically derived from `$_SERVER` | -| `getCookieParams()` | Retrieves cookies sent by the client to the server. | Typically derived from `$_COOKIES` | -| `withCookieParams(array $cookies)` | Returns a new request instance with the specified cookies | | -| `withQueryParams(array $query)` | Returns a new request instance with the specified query string arguments | | -| `getUploadedFiles()` | Retrieve normalized file upload data | | -| `withUploadedFiles(array $uploadedFiles)` | Returns a new request instance with the specified uploaded files | | -| `getParsedBody()` | Retrieve any parameters provided in the request body | | -| `withParsedBody($data)` | Returns a new request instance with the specified body parameters | | -| `getAttributes()` | Retrieve attributes derived from the request | | -| `getAttribute($name, $default = null)` | Retrieve a single derived request attribute | | -| `withAttribute($name, $value)` | Returns a new request instance with the specified derived request attribute | | -| `withoutAttribute($name)` | Returns a new request instance that without the specified derived request attribute | | - -## `Psr\Http\Message\ResponseInterface` Methods: - -Same methods as `Psr\Http\Message\MessageInterface` + the following methods: - -| Method Name | Description | Notes | -|------------------------------------| ----------- | ----- | -| `getStatusCode()` | Gets the response status code. | | -| `withStatus($code, $reasonPhrase = '')` | Returns a new response instance with the specified status code and, optionally, reason phrase. | | -| `getReasonPhrase()` | Gets the response reason phrase associated with the status code. | | - -## `Psr\Http\Message\StreamInterface` Methods - -| Method Name | Description | Notes | -|------------------------------------| ----------- | ----- | -| `__toString()` | Reads all data from the stream into a string, from the beginning to end. | | -| `close()` | Closes the stream and any underlying resources. | | -| `detach()` | Separates any underlying resources from the stream. | | -| `getSize()` | Get the size of the stream if known. | | -| `eof()` | Returns true if the stream is at the end of the stream.| | -| `isSeekable()` | Returns whether or not the stream is seekable. | | -| `seek($offset, $whence = SEEK_SET)` | Seek to a position in the stream. | | -| `rewind()` | Seek to the beginning of the stream. | | -| `isWritable()` | Returns whether or not the stream is writable. | | -| `write($string)` | Write data to the stream. | | -| `isReadable()` | Returns whether or not the stream is readable. | | -| `read($length)` | Read data from the stream. | | -| `getContents()` | Returns the remaining contents in a string | | -| `getMetadata($key = null)()` | Get stream metadata as an associative array or retrieve a specific key. | | - -## `Psr\Http\Message\UriInterface` Methods - -| Method Name | Description | Notes | -|------------------------------------| ----------- | ----- | -| `getScheme()` | Retrieve the scheme component of the URI. | | -| `getAuthority()` | Retrieve the authority component of the URI. | | -| `getUserInfo()` | Retrieve the user information component of the URI. | | -| `getHost()` | Retrieve the host component of the URI. | | -| `getPort()` | Retrieve the port component of the URI. | | -| `getPath()` | Retrieve the path component of the URI. | | -| `getQuery()` | Retrieve the query string of the URI. | | -| `getFragment()` | Retrieve the fragment component of the URI. | | -| `withScheme($scheme)` | Return an instance with the specified scheme. | | -| `withUserInfo($user, $password = null)` | Return an instance with the specified user information. | | -| `withHost($host)` | Return an instance with the specified host. | | -| `withPort($port)` | Return an instance with the specified port. | | -| `withPath($path)` | Return an instance with the specified path. | | -| `withQuery($query)` | Return an instance with the specified query string. | | -| `withFragment($fragment)` | Return an instance with the specified URI fragment. | | -| `__toString()` | Return the string representation as a URI reference. | | - -## `Psr\Http\Message\UploadedFileInterface` Methods - -| Method Name | Description | Notes | -|------------------------------------| ----------- | ----- | -| `getStream()` | Retrieve a stream representing the uploaded file. | | -| `moveTo($targetPath)` | Move the uploaded file to a new location. | | -| `getSize()` | Retrieve the file size. | | -| `getError()` | Retrieve the error associated with the uploaded file. | | -| `getClientFilename()` | Retrieve the filename sent by the client. | | -| `getClientMediaType()` | Retrieve the media type sent by the client. | | - -> `RequestInterface`, `ServerRequestInterface`, `ResponseInterface` extend `MessageInterface` because the `Request` and the `Response` are `HTTP Messages`. -> When using `ServerRequestInterface`, both `RequestInterface` and `Psr\Http\Message\MessageInterface` methods are considered. - diff --git a/deps/vendor/psr/http-message/docs/PSR7-Usage.md b/deps/vendor/psr/http-message/docs/PSR7-Usage.md deleted file mode 100644 index b6d048a34..000000000 --- a/deps/vendor/psr/http-message/docs/PSR7-Usage.md +++ /dev/null @@ -1,159 +0,0 @@ -### PSR-7 Usage - -All PSR-7 applications comply with these interfaces -They were created to establish a standard between middleware implementations. - -> `RequestInterface`, `ServerRequestInterface`, `ResponseInterface` extend `MessageInterface` because the `Request` and the `Response` are `HTTP Messages`. -> When using `ServerRequestInterface`, both `RequestInterface` and `Psr\Http\Message\MessageInterface` methods are considered. - - -The following examples will illustrate how basic operations are done in PSR-7. - -##### Examples - - -For this examples to work (at least) a PSR-7 implementation package is required. (eg: zendframework/zend-diactoros, guzzlehttp/psr7, slim/slim, etc) -All PSR-7 implementations should have the same behaviour. - -The following will be assumed: -`$request` is an object of `Psr\Http\Message\RequestInterface` and - -`$response` is an object implementing `Psr\Http\Message\RequestInterface` - - -### Working with HTTP Headers - -#### Adding headers to response: - -```php -$response->withHeader('My-Custom-Header', 'My Custom Message'); -``` - -#### Appending values to headers - -```php -$response->withAddedHeader('My-Custom-Header', 'The second message'); -``` - -#### Checking if header exists: - -```php -$request->hasHeader('My-Custom-Header'); // will return false -$response->hasHeader('My-Custom-Header'); // will return true -``` - -> Note: My-Custom-Header was only added in the Response - -#### Getting comma-separated values from a header (also applies to request) - -```php -// getting value from request headers -$request->getHeaderLine('Content-Type'); // will return: "text/html; charset=UTF-8" -// getting value from response headers -$response->getHeaderLine('My-Custom-Header'); // will return: "My Custom Message; The second message" -``` - -#### Getting array of value from a header (also applies to request) -```php -// getting value from request headers -$request->getHeader('Content-Type'); // will return: ["text/html", "charset=UTF-8"] -// getting value from response headers -$response->getHeader('My-Custom-Header'); // will return: ["My Custom Message", "The second message"] -``` - -#### Removing headers from HTTP Messages -```php -// removing a header from Request, removing deprecated "Content-MD5" header -$request->withoutHeader('Content-MD5'); - -// removing a header from Response -// effect: the browser won't know the size of the stream -// the browser will download the stream till it ends -$response->withoutHeader('Content-Length'); -``` - -### Working with HTTP Message Body - -When working with the PSR-7 there are two methods of implementation: -#### 1. Getting the body separately - -> This method makes the body handling easier to understand and is useful when repeatedly calling body methods. (You only call `getBody()` once). Using this method mistakes like `$response->write()` are also prevented. - -```php -$body = $response->getBody(); -// operations on body, eg. read, write, seek -// ... -// replacing the old body -$response->withBody($body); -// this last statement is optional as we working with objects -// in this case the "new" body is same with the "old" one -// the $body variable has the same value as the one in $request, only the reference is passed -``` - -#### 2. Working directly on response - -> This method is useful when only performing few operations as the `$request->getBody()` statement fragment is required - -```php -$response->getBody()->write('hello'); -``` - -### Getting the body contents - -The following snippet gets the contents of a stream contents. -> Note: Streams must be rewinded, if content was written into streams, it will be ignored when calling `getContents()` because the stream pointer is set to the last character, which is `\0` - meaning end of stream. -```php -$body = $response->getBody(); -$body->rewind(); // or $body->seek(0); -$bodyText = $body->getContents(); -``` -> Note: If `$body->seek(1)` is called before `$body->getContents()`, the first character will be ommited as the starting pointer is set to `1`, not `0`. This is why using `$body->rewind()` is recommended. - -### Append to body - -```php -$response->getBody()->write('Hello'); // writing directly -$body = $request->getBody(); // which is a `StreamInterface` -$body->write('xxxxx'); -``` - -### Prepend to body -Prepending is different when it comes to streams. The content must be copied before writing the content to be prepended. -The following example will explain the behaviour of streams. - -```php -// assuming our response is initially empty -$body = $repsonse->getBody(); -// writing the string "abcd" -$body->write('abcd'); - -// seeking to start of stream -$body->seek(0); -// writing 'ef' -$body->write('ef'); // at this point the stream contains "efcd" -``` - -#### Prepending by rewriting separately - -```php -// assuming our response body stream only contains: "abcd" -$body = $response->getBody(); -$body->rewind(); -$contents = $body->getContents(); // abcd -// seeking the stream to beginning -$body->rewind(); -$body->write('ef'); // stream contains "efcd" -$body->write($contents); // stream contains "efabcd" -``` - -> Note: `getContents()` seeks the stream while reading it, therefore if the second `rewind()` method call was not present the stream would have resulted in `abcdefabcd` because the `write()` method appends to stream if not preceeded by `rewind()` or `seek(0)`. - -#### Prepending by using contents as a string -```php -$body = $response->getBody(); -$body->rewind(); -$contents = $body->getContents(); // efabcd -$contents = 'ef'.$contents; -$body->rewind(); -$body->write($contents); -``` diff --git a/deps/vendor/psr/http-message/src/MessageInterface.php b/deps/vendor/psr/http-message/src/MessageInterface.php index 8cdb4ed63..dd46e5ec8 100644 --- a/deps/vendor/psr/http-message/src/MessageInterface.php +++ b/deps/vendor/psr/http-message/src/MessageInterface.php @@ -1,7 +1,5 @@ =5.3.0", "react/promise": "^3.0 || ^2.0 || ^1.1" }, - "require-dev": { - "phpunit/phpunit": "^9.5 || ^5.7 || ^4.8.35" - }, "autoload": { - "psr-4": { - "React\\Cache\\": "src/" - } + "psr-4": { "React\\Cache\\": "src/" } }, "autoload-dev": { - "psr-4": { - "React\\Tests\\Cache\\": "tests/" - } + "psr-4": { "React\\Tests\\Cache\\": "tests/" } + }, + "require-dev": { + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35" } } diff --git a/deps/vendor/react/dns/CHANGELOG.md b/deps/vendor/react/dns/CHANGELOG.md index bc1055fc0..9aaa004dc 100644 --- a/deps/vendor/react/dns/CHANGELOG.md +++ b/deps/vendor/react/dns/CHANGELOG.md @@ -1,46 +1,5 @@ # Changelog -## 1.13.0 (2024-06-13) - -* Feature: Improve PHP 8.4+ support by avoiding implicitly nullable type declarations. - (#224 by @WyriHaximus) - -## 1.12.0 (2023-11-29) - -* Feature: Full PHP 8.3 compatibility. - (#217 by @sergiy-petrov) - -* Update test environment and avoid unhandled promise rejections. - (#215, #216 and #218 by @clue) - -## 1.11.0 (2023-06-02) - -* Feature: Include timeout logic to avoid dependency on reactphp/promise-timer. - (#213 by @clue) - -* Improve test suite and project setup and report failed assertions. - (#210 by @clue, #212 by @WyriHaximus and #209 and #211 by @SimonFrings) - -## 1.10.0 (2022-09-08) - -* Feature: Full support for PHP 8.2 release. - (#201 by @clue and #207 by @WyriHaximus) - -* Feature: Optimize forward compatibility with Promise v3, avoid hitting autoloader. - (#202 by @clue) - -* Feature / Fix: Improve error reporting when custom error handler is used. - (#197 by @clue) - -* Fix: Fix invalid references in exception stack trace. - (#191 by @clue) - -* Minor documentation improvements. - (#195 by @SimonFrings and #203 by @nhedger) - -* Improve test suite, update to use default loop and new reactphp/async package. - (#204, #205 and #206 by @clue and #196 by @SimonFrings) - ## 1.9.0 (2021-12-20) * Feature: Full support for PHP 8.1 release and prepare PHP 8.2 compatibility diff --git a/deps/vendor/react/dns/README.md b/deps/vendor/react/dns/README.md index 9f83a944d..92eac9720 100644 --- a/deps/vendor/react/dns/README.md +++ b/deps/vendor/react/dns/README.md @@ -1,7 +1,6 @@ # DNS -[![CI status](https://github.com/reactphp/dns/actions/workflows/ci.yml/badge.svg)](https://github.com/reactphp/dns/actions) -[![installs on Packagist](https://img.shields.io/packagist/dt/react/dns?color=blue&label=installs%20on%20Packagist)](https://packagist.org/packages/react/dns) +[![CI status](https://github.com/reactphp/dns/workflows/CI/badge.svg)](https://github.com/reactphp/dns/actions) Async DNS resolver for [ReactPHP](https://reactphp.org/). @@ -115,7 +114,7 @@ See also the wiki for possible [cache implementations](https://github.com/reactp ### resolve() -The `resolve(string $domain): PromiseInterface` method can be used to +The `resolve(string $domain): PromiseInterface` method can be used to resolve the given $domain name to a single IPv4 address (type `A` query). ```php @@ -151,7 +150,7 @@ $promise->cancel(); ### resolveAll() -The `resolveAll(string $host, int $type): PromiseInterface` method can be used to +The `resolveAll(string $host, int $type): PromiseInterface` method can be used to resolve all record values for the given $domain name and query $type. ```php @@ -410,7 +409,7 @@ This project follows [SemVer](https://semver.org/). This will install the latest supported version: ```bash -composer require react/dns:^1.13 +$ composer require react/dns:^1.9 ``` See also the [CHANGELOG](CHANGELOG.md) for details about version upgrades. @@ -426,13 +425,13 @@ To run the test suite, you first need to clone this repo and then install all dependencies [through Composer](https://getcomposer.org/): ```bash -composer install +$ composer install ``` To run the test suite, go to the project root and run: ```bash -vendor/bin/phpunit +$ vendor/bin/phpunit ``` The test suite also contains a number of functional integration tests that rely @@ -440,7 +439,7 @@ on a stable internet connection. If you do not want to run these, they can simply be skipped like this: ```bash -vendor/bin/phpunit --exclude-group internet +$ vendor/bin/phpunit --exclude-group internet ``` ## License diff --git a/deps/vendor/react/dns/composer.json b/deps/vendor/react/dns/composer.json index 4fe5c0da2..0126343f0 100644 --- a/deps/vendor/react/dns/composer.json +++ b/deps/vendor/react/dns/composer.json @@ -29,21 +29,17 @@ "php": ">=5.3.0", "react/cache": "^1.0 || ^0.6 || ^0.5", "react/event-loop": "^1.2", - "react/promise": "^3.2 || ^2.7 || ^1.2.1" + "react/promise": "^3.0 || ^2.7 || ^1.2.1", + "react/promise-timer": "^1.8" }, "require-dev": { - "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", - "react/async": "^4.3 || ^3 || ^2", - "react/promise-timer": "^1.11" + "clue/block-react": "^1.2", + "phpunit/phpunit": "^9.3 || ^4.8.35" }, "autoload": { - "psr-4": { - "React\\Dns\\": "src/" - } + "psr-4": { "React\\Dns\\": "src" } }, "autoload-dev": { - "psr-4": { - "React\\Tests\\Dns\\": "tests/" - } + "psr-4": { "React\\Tests\\Dns\\": "tests" } } } diff --git a/deps/vendor/react/dns/src/Query/ExecutorInterface.php b/deps/vendor/react/dns/src/Query/ExecutorInterface.php index 0bc3945f1..b356dc62f 100644 --- a/deps/vendor/react/dns/src/Query/ExecutorInterface.php +++ b/deps/vendor/react/dns/src/Query/ExecutorInterface.php @@ -36,7 +36,7 @@ interface ExecutorInterface * ``` * * @param Query $query - * @return \React\Promise\PromiseInterface<\React\Dns\Model\Message> + * @return \React\Promise\PromiseInterface<\React\Dns\Model\Message,\Exception> * resolves with response message on success or rejects with an Exception on error */ public function query(Query $query); diff --git a/deps/vendor/react/dns/src/Query/RetryExecutor.php b/deps/vendor/react/dns/src/Query/RetryExecutor.php index 880609b22..7efcacc8c 100644 --- a/deps/vendor/react/dns/src/Query/RetryExecutor.php +++ b/deps/vendor/react/dns/src/Query/RetryExecutor.php @@ -2,6 +2,7 @@ namespace React\Dns\Query; +use React\Promise\CancellablePromiseInterface; use React\Promise\Deferred; use React\Promise\PromiseInterface; @@ -24,7 +25,7 @@ public function query(Query $query) public function tryQuery(Query $query, $retries) { $deferred = new Deferred(function () use (&$promise) { - if ($promise instanceof PromiseInterface && \method_exists($promise, 'cancel')) { + if ($promise instanceof CancellablePromiseInterface || (!\interface_exists('React\Promise\CancellablePromiseInterface') && \method_exists($promise, 'cancel'))) { $promise->cancel(); } }); @@ -55,11 +56,11 @@ public function tryQuery(Query $query, $retries) // Exception trace arguments are not available on some PHP 7.4 installs // @codeCoverageIgnoreStart - foreach ($trace as $ti => $one) { + foreach ($trace as &$one) { if (isset($one['args'])) { - foreach ($one['args'] as $ai => $arg) { + foreach ($one['args'] as &$arg) { if ($arg instanceof \Closure) { - $trace[$ti]['args'][$ai] = 'Object(' . \get_class($arg) . ')'; + $arg = 'Object(' . \get_class($arg) . ')'; } } } diff --git a/deps/vendor/react/dns/src/Query/TcpTransportExecutor.php b/deps/vendor/react/dns/src/Query/TcpTransportExecutor.php index 669fd012f..6644e16ad 100644 --- a/deps/vendor/react/dns/src/Query/TcpTransportExecutor.php +++ b/deps/vendor/react/dns/src/Query/TcpTransportExecutor.php @@ -134,7 +134,7 @@ class TcpTransportExecutor implements ExecutorInterface * @param string $nameserver * @param ?LoopInterface $loop */ - public function __construct($nameserver, $loop = null) + public function __construct($nameserver, LoopInterface $loop = null) { if (\strpos($nameserver, '[') === false && \substr_count($nameserver, ':') >= 2 && \strpos($nameserver, '://') === false) { // several colons, but not enclosed in square brackets => enclose IPv6 address in square brackets @@ -146,10 +146,6 @@ public function __construct($nameserver, $loop = null) throw new \InvalidArgumentException('Invalid nameserver address given'); } - if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1 - throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface'); - } - $this->nameserver = 'tcp://' . $parts['host'] . ':' . (isset($parts['port']) ? $parts['port'] : 53); $this->loop = $loop ?: Loop::get(); $this->parser = new Parser(); @@ -250,24 +246,13 @@ public function handleWritable() $this->loop->addReadStream($this->socket, array($this, 'handleRead')); } - $errno = 0; - $errstr = ''; - \set_error_handler(function ($_, $error) use (&$errno, &$errstr) { - // Match errstr from PHP's warning message. - // fwrite(): Send of 327712 bytes failed with errno=32 Broken pipe - \preg_match('/errno=(\d+) (.+)/', $error, $m); - $errno = isset($m[1]) ? (int) $m[1] : 0; - $errstr = isset($m[2]) ? $m[2] : $error; - }); - - $written = \fwrite($this->socket, $this->writeBuffer); - - \restore_error_handler(); - + $written = @\fwrite($this->socket, $this->writeBuffer); if ($written === false || $written === 0) { + $error = \error_get_last(); + \preg_match('/errno=(\d+) (.+)/', $error['message'], $m); $this->closeError( - 'Unable to send query to DNS server ' . $this->nameserver . ' (' . $errstr . ')', - $errno + 'Unable to send query to DNS server ' . $this->nameserver . ' (' . (isset($m[2]) ? $m[2] : $error['message']) . ')', + isset($m[1]) ? (int) $m[1] : 0 ); return; } diff --git a/deps/vendor/react/dns/src/Query/TimeoutExecutor.php b/deps/vendor/react/dns/src/Query/TimeoutExecutor.php index b61fea6da..15c8c22a8 100644 --- a/deps/vendor/react/dns/src/Query/TimeoutExecutor.php +++ b/deps/vendor/react/dns/src/Query/TimeoutExecutor.php @@ -4,7 +4,7 @@ use React\EventLoop\Loop; use React\EventLoop\LoopInterface; -use React\Promise\Promise; +use React\Promise\Timer; final class TimeoutExecutor implements ExecutorInterface { @@ -12,17 +12,8 @@ final class TimeoutExecutor implements ExecutorInterface private $loop; private $timeout; - /** - * @param ExecutorInterface $executor - * @param float $timeout - * @param ?LoopInterface $loop - */ - public function __construct(ExecutorInterface $executor, $timeout, $loop = null) + public function __construct(ExecutorInterface $executor, $timeout, LoopInterface $loop = null) { - if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1 - throw new \InvalidArgumentException('Argument #3 ($loop) expected null|React\EventLoop\LoopInterface'); - } - $this->executor = $executor; $this->loop = $loop ?: Loop::get(); $this->timeout = $timeout; @@ -30,49 +21,11 @@ public function __construct(ExecutorInterface $executor, $timeout, $loop = null) public function query(Query $query) { - $promise = $this->executor->query($query); - - $loop = $this->loop; - $time = $this->timeout; - return new Promise(function ($resolve, $reject) use ($loop, $time, $promise, $query) { - $timer = null; - $promise = $promise->then(function ($v) use (&$timer, $loop, $resolve) { - if ($timer) { - $loop->cancelTimer($timer); - } - $timer = false; - $resolve($v); - }, function ($v) use (&$timer, $loop, $reject) { - if ($timer) { - $loop->cancelTimer($timer); - } - $timer = false; - $reject($v); - }); - - // promise already resolved => no need to start timer - if ($timer === false) { - return; + return Timer\timeout($this->executor->query($query), $this->timeout, $this->loop)->then(null, function ($e) use ($query) { + if ($e instanceof Timer\TimeoutException) { + $e = new TimeoutException(sprintf("DNS query for %s timed out", $query->describe()), 0, $e); } - - // start timeout timer which will cancel the pending promise - $timer = $loop->addTimer($time, function () use ($time, &$promise, $reject, $query) { - $reject(new TimeoutException( - 'DNS query for ' . $query->describe() . ' timed out' - )); - - // Cancel pending query to clean up any underlying resources and references. - // Avoid garbage references in call stack by passing pending promise by reference. - assert(\method_exists($promise, 'cancel')); - $promise->cancel(); - $promise = null; - }); - }, function () use (&$promise) { - // Cancelling this promise will cancel the pending query, thus triggering the rejection logic above. - // Avoid garbage references in call stack by passing pending promise by reference. - assert(\method_exists($promise, 'cancel')); - $promise->cancel(); - $promise = null; + throw $e; }); } } diff --git a/deps/vendor/react/dns/src/Query/UdpTransportExecutor.php b/deps/vendor/react/dns/src/Query/UdpTransportExecutor.php index a8cbfafa2..4c995a86d 100644 --- a/deps/vendor/react/dns/src/Query/UdpTransportExecutor.php +++ b/deps/vendor/react/dns/src/Query/UdpTransportExecutor.php @@ -98,7 +98,7 @@ final class UdpTransportExecutor implements ExecutorInterface * @param string $nameserver * @param ?LoopInterface $loop */ - public function __construct($nameserver, $loop = null) + public function __construct($nameserver, LoopInterface $loop = null) { if (\strpos($nameserver, '[') === false && \substr_count($nameserver, ':') >= 2 && \strpos($nameserver, '://') === false) { // several colons, but not enclosed in square brackets => enclose IPv6 address in square brackets @@ -110,10 +110,6 @@ public function __construct($nameserver, $loop = null) throw new \InvalidArgumentException('Invalid nameserver address given'); } - if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1 - throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface'); - } - $this->nameserver = 'udp://' . $parts['host'] . ':' . (isset($parts['port']) ? $parts['port'] : 53); $this->loop = $loop ?: Loop::get(); $this->parser = new Parser(); @@ -133,8 +129,6 @@ public function query(Query $query) } // UDP connections are instant, so try connection without a loop or timeout - $errno = 0; - $errstr = ''; $socket = @\stream_socket_client($this->nameserver, $errno, $errstr, 0); if ($socket === false) { return \React\Promise\reject(new \RuntimeException( @@ -145,25 +139,18 @@ public function query(Query $query) // set socket to non-blocking and immediately try to send (fill write buffer) \stream_set_blocking($socket, false); + $written = @\fwrite($socket, $queryData); - \set_error_handler(function ($_, $error) use (&$errno, &$errstr) { + if ($written !== \strlen($queryData)) { // Write may potentially fail, but most common errors are already caught by connection check above. // Among others, macOS is known to report here when trying to send to broadcast address. // This can also be reproduced by writing data exceeding `stream_set_chunk_size()` to a server refusing UDP data. // fwrite(): send of 8192 bytes failed with errno=111 Connection refused - \preg_match('/errno=(\d+) (.+)/', $error, $m); - $errno = isset($m[1]) ? (int) $m[1] : 0; - $errstr = isset($m[2]) ? $m[2] : $error; - }); - - $written = \fwrite($socket, $queryData); - - \restore_error_handler(); - - if ($written !== \strlen($queryData)) { + $error = \error_get_last(); + \preg_match('/errno=(\d+) (.+)/', $error['message'], $m); return \React\Promise\reject(new \RuntimeException( - 'DNS query for ' . $query->describe() . ' failed: Unable to send query to DNS server ' . $this->nameserver . ' (' . $errstr . ')', - $errno + 'DNS query for ' . $query->describe() . ' failed: Unable to send query to DNS server ' . $this->nameserver . ' (' . (isset($m[2]) ? $m[2] : $error['message']) . ')', + isset($m[1]) ? (int) $m[1] : 0 )); } diff --git a/deps/vendor/react/dns/src/Resolver/Factory.php b/deps/vendor/react/dns/src/Resolver/Factory.php index 52658951c..5fe608cb5 100644 --- a/deps/vendor/react/dns/src/Resolver/Factory.php +++ b/deps/vendor/react/dns/src/Resolver/Factory.php @@ -36,12 +36,8 @@ final class Factory * @throws \InvalidArgumentException for invalid DNS server address * @throws \UnderflowException when given DNS Config object has an empty list of nameservers */ - public function create($config, $loop = null) + public function create($config, LoopInterface $loop = null) { - if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1 - throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface'); - } - $executor = $this->decorateHostsFileExecutor($this->createExecutor($config, $loop ?: Loop::get())); return new Resolver($executor); @@ -63,16 +59,8 @@ public function create($config, $loop = null) * @throws \InvalidArgumentException for invalid DNS server address * @throws \UnderflowException when given DNS Config object has an empty list of nameservers */ - public function createCached($config, $loop = null, $cache = null) + public function createCached($config, LoopInterface $loop = null, CacheInterface $cache = null) { - if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1 - throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface'); - } - - if ($cache !== null && !$cache instanceof CacheInterface) { // manual type check to support legacy PHP < 7.1 - throw new \InvalidArgumentException('Argument #3 ($cache) expected null|React\Cache\CacheInterface'); - } - // default to keeping maximum of 256 responses in cache unless explicitly given if (!($cache instanceof CacheInterface)) { $cache = new ArrayCache(256); diff --git a/deps/vendor/react/dns/src/Resolver/ResolverInterface.php b/deps/vendor/react/dns/src/Resolver/ResolverInterface.php index 555a1cb13..fe937dc7a 100644 --- a/deps/vendor/react/dns/src/Resolver/ResolverInterface.php +++ b/deps/vendor/react/dns/src/Resolver/ResolverInterface.php @@ -39,7 +39,7 @@ interface ResolverInterface * ``` * * @param string $domain - * @return \React\Promise\PromiseInterface + * @return \React\Promise\PromiseInterface * resolves with a single IP address on success or rejects with an Exception on error. */ public function resolve($domain); @@ -87,7 +87,7 @@ public function resolve($domain); * ``` * * @param string $domain - * @return \React\Promise\PromiseInterface + * @return \React\Promise\PromiseInterface * Resolves with all record values on success or rejects with an Exception on error. */ public function resolveAll($domain, $type); diff --git a/deps/vendor/react/event-loop/CHANGELOG.md b/deps/vendor/react/event-loop/CHANGELOG.md index e634b12ea..bd9e69d43 100644 --- a/deps/vendor/react/event-loop/CHANGELOG.md +++ b/deps/vendor/react/event-loop/CHANGELOG.md @@ -1,47 +1,5 @@ # Changelog -## 1.5.0 (2023-11-13) - -* Feature: Improve performance by using `spl_object_id()` on PHP 7.2+. - (#267 by @samsonasik) - -* Feature: Full PHP 8.3 compatibility. - (#269 by @clue) - -* Update tests for `ext-uv` on PHP 8+ and legacy PHP. - (#270 by @clue and #268 by @SimonFrings) - -## 1.4.0 (2023-05-05) - -* Feature: Improve performance of `Loop` by avoiding unneeded method calls. - (#266 by @clue) - -* Feature: Support checking `EINTR` constant from `ext-pcntl` without `ext-sockets`. - (#265 by @clue) - -* Minor documentation improvements. - (#254 by @nhedger) - -* Improve test suite, run tests on PHP 8.2 and report failed assertions. - (#258 by @WyriHaximus, #264 by @clue and #251, #261 and #262 by @SimonFrings) - -## 1.3.0 (2022-03-17) - -* Feature: Improve default `StreamSelectLoop` to report any warnings for invalid streams. - (#245 by @clue) - -* Feature: Improve performance of `StreamSelectLoop` when no timers are scheduled. - (#246 by @clue) - -* Fix: Fix periodic timer with zero interval for `ExtEvLoop` and legacy `ExtLibevLoop`. - (#243 by @lucasnetau) - -* Minor documentation improvements, update PHP version references. - (#240, #248 and #250 by @SimonFrings, #241 by @dbu and #249 by @clue) - -* Improve test suite and test against PHP 8.1. - (#238 by @WyriHaximus and #242 by @clue) - ## 1.2.0 (2021-07-11) A major new feature release, see [**release announcement**](https://clue.engineering/2021/announcing-reactphp-default-loop). diff --git a/deps/vendor/react/event-loop/README.md b/deps/vendor/react/event-loop/README.md index 88a3e18b8..b89ad5750 100644 --- a/deps/vendor/react/event-loop/README.md +++ b/deps/vendor/react/event-loop/README.md @@ -1,7 +1,6 @@ -# EventLoop +# EventLoop Component -[![CI status](https://github.com/reactphp/event-loop/actions/workflows/ci.yml/badge.svg)](https://github.com/reactphp/event-loop/actions) -[![installs on Packagist](https://img.shields.io/packagist/dt/react/event-loop?color=blue&label=installs%20on%20Packagist)](https://packagist.org/packages/react/event-loop) +[![CI status](https://github.com/reactphp/event-loop/workflows/CI/badge.svg)](https://github.com/reactphp/event-loop/actions) [ReactPHP](https://reactphp.org/)'s core reactor event loop that libraries can use for evented I/O. @@ -10,7 +9,7 @@ same event loop. This component provides a common `LoopInterface` that any library can target. This allows them to be used in the same loop, with one single [`run()`](#run) call that is controlled by the user. -**Table of contents** +**Table of Contents** * [Quickstart example](#quickstart-example) * [Usage](#usage) @@ -84,8 +83,8 @@ See also the [examples](examples). ## Usage -Typical applications would use the [`Loop` class](#loop) to use the default -event loop like this: +As of `v1.2.0`, typical applications would use the [`Loop` object](#loop) +to use the currently active event loop like this: ```php use React\EventLoop\Loop; @@ -124,14 +123,14 @@ In both cases, the program would perform the exact same steps. 1. The event loop instance is created at the beginning of the program. This is implicitly done the first time you call the [`Loop` class](#loop) or - explicitly when using the deprecated [`Factory::create()` method](#create) + explicitly when using the deprecated [`Factory::create() method`](#create) (or manually instantiating any of the [loop implementations](#loop-implementations)). 2. The event loop is used directly or passed as an instance to library and application code. In this example, a periodic timer is registered with the event loop which simply outputs `Tick` every fraction of a second until another timer stops the periodic timer after a second. 3. The event loop is run at the end of the program. This is automatically done - when using the [`Loop` class](#loop) or explicitly with a single [`run()`](#run) + when using [`Loop` class](#loop) or explicitly with a single [`run()`](#run) call at the end of the program. As of `v1.2.0`, we highly recommend using the [`Loop` class](#loop). @@ -340,7 +339,7 @@ All of the event loops support these features: For most consumers of this package, the underlying event loop implementation is an implementation detail. -You should use the [`Loop` class](#loop) to automatically create a new instance. +You should use the [`Factory`](#factory) to automatically create a new instance. Advanced! If you explicitly need a certain event loop implementation, you can manually instantiate one of the following classes. @@ -352,14 +351,13 @@ event loop implementation first or they will throw a `BadMethodCallException` on A `stream_select()` based event loop. This uses the [`stream_select()`](https://www.php.net/manual/en/function.stream-select.php) -function and is the only implementation that works out of the box with PHP. +function and is the only implementation which works out of the box with PHP. -This event loop works out of the box on PHP 5.3 through PHP 8+ and HHVM. +This event loop works out of the box on PHP 5.3 through PHP 7+ and HHVM. This means that no installation is required and this library works on all platforms and supported PHP versions. -Accordingly, the [`Loop` class](#loop) and the deprecated [`Factory`](#factory) -will use this event loop by default if you do not install any of the event loop -extensions listed below. +Accordingly, the [`Factory`](#factory) will use this event loop by default if +you do not install any of the event loop extensions listed below. Under the hood, it does a simple `select` system call. This system call is limited to the maximum file descriptor number of @@ -398,7 +396,7 @@ This uses the [`event` PECL extension](https://pecl.php.net/package/event), that provides an interface to `libevent` library. `libevent` itself supports a number of system-specific backends (epoll, kqueue). -This loop is known to work with PHP 5.4 through PHP 8+. +This loop is known to work with PHP 5.4 through PHP 7+. #### ExtEvLoop @@ -409,7 +407,7 @@ that provides an interface to `libev` library. `libev` itself supports a number of system-specific backends (epoll, kqueue). -This loop is known to work with PHP 5.4 through PHP 8+. +This loop is known to work with PHP 5.4 through PHP 7+. #### ExtUvLoop @@ -435,8 +433,8 @@ This event loop does only work with PHP 5. An [unofficial update](https://github.com/php/pecl-event-libevent/pull/2) for PHP 7 does exist, but it is known to cause regular crashes due to `SEGFAULT`s. To reiterate: Using this event loop on PHP 7 is not recommended. -Accordingly, neither the [`Loop` class](#loop) nor the deprecated -[`Factory` class](#factory) will try to use this event loop on PHP 7. +Accordingly, the [`Factory`](#factory) will not try to use this event loop on +PHP 7. This event loop is known to trigger a readable listener only if the stream *becomes* readable (edge-triggered) and may not trigger if the @@ -470,7 +468,7 @@ run the event loop until there are no more tasks to perform. For many applications, this method is the only directly visible invocation on the event loop. -As a rule of thumb, it is usually recommended to attach everything to the +As a rule of thumb, it is usally recommended to attach everything to the same loop instance and then run the loop once at the bottom end of the application. @@ -488,7 +486,7 @@ run it will result in the application exiting without actually waiting for any of the attached listeners. This method MUST NOT be called while the loop is already running. -This method MAY be called more than once after it has explicitly been +This method MAY be called more than once after it has explicity been [`stop()`ped](#stop) or after it automatically stopped because it previously did no longer have anything to do. @@ -517,21 +515,18 @@ on a loop instance that has already been stopped has no effect. The `addTimer(float $interval, callable $callback): TimerInterface` method can be used to enqueue a callback to be invoked once after the given interval. -The second parameter MUST be a timer callback function that accepts -the timer instance as its only parameter. -If you don't use the timer instance inside your timer callback function -you MAY use a function which has no parameters at all. +The timer callback function MUST be able to accept a single parameter, +the timer instance as also returned by this method or you MAY use a +function which has no parameters at all. The timer callback function MUST NOT throw an `Exception`. The return value of the timer callback function will be ignored and has no effect, so for performance reasons you're recommended to not return any excessive data structures. -This method returns a timer instance. The same timer instance will also be -passed into the timer callback function as described above. -You can invoke [`cancelTimer`](#canceltimer) to cancel a pending timer. Unlike [`addPeriodicTimer()`](#addperiodictimer), this method will ensure the callback will be invoked only once after the given interval. +You can invoke [`cancelTimer`](#canceltimer) to cancel a pending timer. ```php $loop->addTimer(0.8, function () { @@ -586,21 +581,18 @@ See also [event loop implementations](#loop-implementations) for more details. The `addPeriodicTimer(float $interval, callable $callback): TimerInterface` method can be used to enqueue a callback to be invoked repeatedly after the given interval. -The second parameter MUST be a timer callback function that accepts -the timer instance as its only parameter. -If you don't use the timer instance inside your timer callback function -you MAY use a function which has no parameters at all. +The timer callback function MUST be able to accept a single parameter, +the timer instance as also returned by this method or you MAY use a +function which has no parameters at all. The timer callback function MUST NOT throw an `Exception`. The return value of the timer callback function will be ignored and has no effect, so for performance reasons you're recommended to not return any excessive data structures. -This method returns a timer instance. The same timer instance will also be -passed into the timer callback function as described above. -Unlike [`addTimer()`](#addtimer), this method will ensure the callback -will be invoked infinitely after the given interval or until you invoke -[`cancelTimer`](#canceltimer). +Unlike [`addTimer()`](#addtimer), this method will ensure the the +callback will be invoked infinitely after the given interval or until you +invoke [`cancelTimer`](#canceltimer). ```php $timer = $loop->addPeriodicTimer(0.1, function () { @@ -728,10 +720,9 @@ register a listener to be notified when a signal has been caught by this process This is useful to catch user interrupt signals or shutdown signals from tools like `supervisor` or `systemd`. -The second parameter MUST be a listener callback function that accepts -the signal as its only parameter. -If you don't use the signal inside your listener callback function -you MAY use a function which has no parameters at all. +The listener callback function MUST be able to accept a single parameter, +the signal added by this method or you MAY use a function which +has no parameters at all. The listener callback function MUST NOT throw an `Exception`. The return value of the listener callback function will be ignored and has @@ -746,14 +737,14 @@ $loop->addSignal(SIGINT, function (int $signal) { See also [example #4](examples). -Signaling is only available on Unix-like platforms, Windows isn't +Signaling is only available on Unix-like platform, Windows isn't supported due to operating system limitations. This method may throw a `BadMethodCallException` if signals aren't supported on this platform, for example when required extensions are missing. **Note: A listener can only be added once to the same signal, any -attempts to add it more than once will be ignored.** +attempts to add it more then once will be ignored.** #### removeSignal() @@ -784,10 +775,9 @@ react to this event with a single listener and then dispatch from this listener. This method MAY throw an `Exception` if the given resource type is not supported by this loop implementation. -The second parameter MUST be a listener callback function that accepts -the stream resource as its only parameter. -If you don't use the stream resource inside your listener callback function -you MAY use a function which has no parameters at all. +The listener callback function MUST be able to accept a single parameter, +the stream resource added by this method or you MAY use a function which +has no parameters at all. The listener callback function MUST NOT throw an `Exception`. The return value of the listener callback function will be ignored and has @@ -837,10 +827,9 @@ react to this event with a single listener and then dispatch from this listener. This method MAY throw an `Exception` if the given resource type is not supported by this loop implementation. -The second parameter MUST be a listener callback function that accepts -the stream resource as its only parameter. -If you don't use the stream resource inside your listener callback function -you MAY use a function which has no parameters at all. +The listener callback function MUST be able to accept a single parameter, +the stream resource added by this method or you MAY use a function which +has no parameters at all. The listener callback function MUST NOT throw an `Exception`. The return value of the listener callback function will be ignored and has @@ -882,14 +871,14 @@ to remove a stream that was never added or is invalid has no effect. ## Install -The recommended way to install this library is [through Composer](https://getcomposer.org/). +The recommended way to install this library is [through Composer](https://getcomposer.org). [New to Composer?](https://getcomposer.org/doc/00-intro.md) This project follows [SemVer](https://semver.org/). This will install the latest supported version: ```bash -composer require react/event-loop:^1.5 +$ composer require react/event-loop:^1.2 ``` See also the [CHANGELOG](CHANGELOG.md) for details about version upgrades. @@ -897,7 +886,7 @@ See also the [CHANGELOG](CHANGELOG.md) for details about version upgrades. This project aims to run on any platform and thus does not require any PHP extensions and supports running on legacy PHP 5.3 through current PHP 8+ and HHVM. -It's *highly recommended to use the latest supported PHP version* for this project. +It's *highly recommended to use PHP 7+* for this project. Installing any of the event loop extensions is suggested, but entirely optional. See also [event loop implementations](#loop-implementations) for more details. @@ -905,16 +894,16 @@ See also [event loop implementations](#loop-implementations) for more details. ## Tests To run the test suite, you first need to clone this repo and then install all -dependencies [through Composer](https://getcomposer.org/): +dependencies [through Composer](https://getcomposer.org): ```bash -composer install +$ composer install ``` To run the test suite, go to the project root and run: ```bash -vendor/bin/phpunit +$ php vendor/bin/phpunit ``` ## License diff --git a/deps/vendor/react/event-loop/composer.json b/deps/vendor/react/event-loop/composer.json index 25a41fe17..d9b032e1f 100644 --- a/deps/vendor/react/event-loop/composer.json +++ b/deps/vendor/react/event-loop/composer.json @@ -29,19 +29,21 @@ "php": ">=5.3.0" }, "require-dev": { - "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35" }, "suggest": { - "ext-pcntl": "For signal handling support when using the StreamSelectLoop" + "ext-event": "~1.0 for ExtEventLoop", + "ext-pcntl": "For signal handling support when using the StreamSelectLoop", + "ext-uv": "* for ExtUvLoop" }, "autoload": { "psr-4": { - "React\\EventLoop\\": "src/" + "React\\EventLoop\\": "src" } }, "autoload-dev": { "psr-4": { - "React\\Tests\\EventLoop\\": "tests/" + "React\\Tests\\EventLoop\\": "tests" } } } diff --git a/deps/vendor/react/event-loop/src/ExtEvLoop.php b/deps/vendor/react/event-loop/src/ExtEvLoop.php index a3fcec682..7fcc29aff 100644 --- a/deps/vendor/react/event-loop/src/ExtEvLoop.php +++ b/deps/vendor/react/event-loop/src/ExtEvLoop.php @@ -16,7 +16,7 @@ * that provides an interface to `libev` library. * `libev` itself supports a number of system-specific backends (epoll, kqueue). * - * This loop is known to work with PHP 5.4 through PHP 8+. + * This loop is known to work with PHP 5.4 through PHP 7+. * * @see http://php.net/manual/en/book.ev.php * @see https://bitbucket.org/osmanov/pecl-ev/overview @@ -162,7 +162,7 @@ public function addPeriodicTimer($interval, $callback) \call_user_func($timer->getCallback(), $timer); }; - $event = $this->loop->timer($timer->getInterval(), $timer->getInterval(), $callback); + $event = $this->loop->timer($interval, $interval, $callback); $this->timers->attach($timer, $event); return $timer; diff --git a/deps/vendor/react/event-loop/src/ExtEventLoop.php b/deps/vendor/react/event-loop/src/ExtEventLoop.php index b162a4029..7ce500106 100644 --- a/deps/vendor/react/event-loop/src/ExtEventLoop.php +++ b/deps/vendor/react/event-loop/src/ExtEventLoop.php @@ -16,7 +16,7 @@ * that provides an interface to `libevent` library. * `libevent` itself supports a number of system-specific backends (epoll, kqueue). * - * This loop is known to work with PHP 5.4 through PHP 8+. + * This loop is known to work with PHP 5.4 through PHP 7+. * * @link https://pecl.php.net/package/event */ diff --git a/deps/vendor/react/event-loop/src/ExtLibevLoop.php b/deps/vendor/react/event-loop/src/ExtLibevLoop.php index c303fdd5c..2cf1ad54a 100644 --- a/deps/vendor/react/event-loop/src/ExtLibevLoop.php +++ b/deps/vendor/react/event-loop/src/ExtLibevLoop.php @@ -132,7 +132,7 @@ public function addPeriodicTimer($interval, $callback) \call_user_func($timer->getCallback(), $timer); }; - $event = new TimerEvent($callback, $timer->getInterval(), $timer->getInterval()); + $event = new TimerEvent($callback, $interval, $interval); $this->timerEvents->attach($timer, $event); $this->loop->add($event); diff --git a/deps/vendor/react/event-loop/src/ExtLibeventLoop.php b/deps/vendor/react/event-loop/src/ExtLibeventLoop.php index 099293a4f..2ea7ffa5d 100644 --- a/deps/vendor/react/event-loop/src/ExtLibeventLoop.php +++ b/deps/vendor/react/event-loop/src/ExtLibeventLoop.php @@ -20,8 +20,8 @@ * An [unofficial update](https://github.com/php/pecl-event-libevent/pull/2) for * PHP 7 does exist, but it is known to cause regular crashes due to `SEGFAULT`s. * To reiterate: Using this event loop on PHP 7 is not recommended. - * Accordingly, neither the [`Loop` class](#loop) nor the deprecated - * [`Factory` class](#factory) will try to use this event loop on PHP 7. + * Accordingly, the [`Factory`](#factory) will not try to use this event loop on + * PHP 7. * * This event loop is known to trigger a readable listener only if * the stream *becomes* readable (edge-triggered) and may not trigger if the diff --git a/deps/vendor/react/event-loop/src/Loop.php b/deps/vendor/react/event-loop/src/Loop.php index f74b9ef26..fd5d81c8a 100644 --- a/deps/vendor/react/event-loop/src/Loop.php +++ b/deps/vendor/react/event-loop/src/Loop.php @@ -8,7 +8,7 @@ final class Loop { /** - * @var ?LoopInterface + * @var LoopInterface */ private static $instance; @@ -83,11 +83,7 @@ public static function set(LoopInterface $loop) */ public static function addReadStream($stream, $listener) { - // create loop instance on demand (legacy PHP < 7 doesn't like ternaries in method calls) - if (self::$instance === null) { - self::get(); - } - self::$instance->addReadStream($stream, $listener); + self::get()->addReadStream($stream, $listener); } /** @@ -101,11 +97,7 @@ public static function addReadStream($stream, $listener) */ public static function addWriteStream($stream, $listener) { - // create loop instance on demand (legacy PHP < 7 doesn't like ternaries in method calls) - if (self::$instance === null) { - self::get(); - } - self::$instance->addWriteStream($stream, $listener); + self::get()->addWriteStream($stream, $listener); } /** @@ -117,9 +109,7 @@ public static function addWriteStream($stream, $listener) */ public static function removeReadStream($stream) { - if (self::$instance !== null) { - self::$instance->removeReadStream($stream); - } + self::get()->removeReadStream($stream); } /** @@ -131,9 +121,7 @@ public static function removeReadStream($stream) */ public static function removeWriteStream($stream) { - if (self::$instance !== null) { - self::$instance->removeWriteStream($stream); - } + self::get()->removeWriteStream($stream); } /** @@ -146,11 +134,7 @@ public static function removeWriteStream($stream) */ public static function addTimer($interval, $callback) { - // create loop instance on demand (legacy PHP < 7 doesn't like ternaries in method calls) - if (self::$instance === null) { - self::get(); - } - return self::$instance->addTimer($interval, $callback); + return self::get()->addTimer($interval, $callback); } /** @@ -163,11 +147,7 @@ public static function addTimer($interval, $callback) */ public static function addPeriodicTimer($interval, $callback) { - // create loop instance on demand (legacy PHP < 7 doesn't like ternaries in method calls) - if (self::$instance === null) { - self::get(); - } - return self::$instance->addPeriodicTimer($interval, $callback); + return self::get()->addPeriodicTimer($interval, $callback); } /** @@ -179,9 +159,7 @@ public static function addPeriodicTimer($interval, $callback) */ public static function cancelTimer(TimerInterface $timer) { - if (self::$instance !== null) { - self::$instance->cancelTimer($timer); - } + return self::get()->cancelTimer($timer); } /** @@ -193,12 +171,7 @@ public static function cancelTimer(TimerInterface $timer) */ public static function futureTick($listener) { - // create loop instance on demand (legacy PHP < 7 doesn't like ternaries in method calls) - if (self::$instance === null) { - self::get(); - } - - self::$instance->futureTick($listener); + self::get()->futureTick($listener); } /** @@ -211,12 +184,7 @@ public static function futureTick($listener) */ public static function addSignal($signal, $listener) { - // create loop instance on demand (legacy PHP < 7 doesn't like ternaries in method calls) - if (self::$instance === null) { - self::get(); - } - - self::$instance->addSignal($signal, $listener); + self::get()->addSignal($signal, $listener); } /** @@ -229,9 +197,7 @@ public static function addSignal($signal, $listener) */ public static function removeSignal($signal, $listener) { - if (self::$instance !== null) { - self::$instance->removeSignal($signal, $listener); - } + self::get()->removeSignal($signal, $listener); } /** @@ -242,12 +208,7 @@ public static function removeSignal($signal, $listener) */ public static function run() { - // create loop instance on demand (legacy PHP < 7 doesn't like ternaries in method calls) - if (self::$instance === null) { - self::get(); - } - - self::$instance->run(); + self::get()->run(); } /** @@ -259,8 +220,6 @@ public static function run() public static function stop() { self::$stopped = true; - if (self::$instance !== null) { - self::$instance->stop(); - } + self::get()->stop(); } } diff --git a/deps/vendor/react/event-loop/src/LoopInterface.php b/deps/vendor/react/event-loop/src/LoopInterface.php index 9266f7188..8146757a7 100644 --- a/deps/vendor/react/event-loop/src/LoopInterface.php +++ b/deps/vendor/react/event-loop/src/LoopInterface.php @@ -20,10 +20,9 @@ interface LoopInterface * listener. This method MAY throw an `Exception` if the given resource type * is not supported by this loop implementation. * - * The second parameter MUST be a listener callback function that accepts - * the stream resource as its only parameter. - * If you don't use the stream resource inside your listener callback function - * you MAY use a function which has no parameters at all. + * The listener callback function MUST be able to accept a single parameter, + * the stream resource added by this method or you MAY use a function which + * has no parameters at all. * * The listener callback function MUST NOT throw an `Exception`. * The return value of the listener callback function will be ignored and has @@ -70,10 +69,9 @@ public function addReadStream($stream, $listener); * listener. This method MAY throw an `Exception` if the given resource type * is not supported by this loop implementation. * - * The second parameter MUST be a listener callback function that accepts - * the stream resource as its only parameter. - * If you don't use the stream resource inside your listener callback function - * you MAY use a function which has no parameters at all. + * The listener callback function MUST be able to accept a single parameter, + * the stream resource added by this method or you MAY use a function which + * has no parameters at all. * * The listener callback function MUST NOT throw an `Exception`. * The return value of the listener callback function will be ignored and has @@ -135,21 +133,18 @@ public function removeWriteStream($stream); /** * Enqueue a callback to be invoked once after the given interval. * - * The second parameter MUST be a timer callback function that accepts - * the timer instance as its only parameter. - * If you don't use the timer instance inside your timer callback function - * you MAY use a function which has no parameters at all. + * The timer callback function MUST be able to accept a single parameter, + * the timer instance as also returned by this method or you MAY use a + * function which has no parameters at all. * * The timer callback function MUST NOT throw an `Exception`. * The return value of the timer callback function will be ignored and has * no effect, so for performance reasons you're recommended to not return * any excessive data structures. * - * This method returns a timer instance. The same timer instance will also be - * passed into the timer callback function as described above. - * You can invoke [`cancelTimer`](#canceltimer) to cancel a pending timer. * Unlike [`addPeriodicTimer()`](#addperiodictimer), this method will ensure * the callback will be invoked only once after the given interval. + * You can invoke [`cancelTimer`](#canceltimer) to cancel a pending timer. * * ```php * $loop->addTimer(0.8, function () { @@ -209,21 +204,18 @@ public function addTimer($interval, $callback); /** * Enqueue a callback to be invoked repeatedly after the given interval. * - * The second parameter MUST be a timer callback function that accepts - * the timer instance as its only parameter. - * If you don't use the timer instance inside your timer callback function - * you MAY use a function which has no parameters at all. + * The timer callback function MUST be able to accept a single parameter, + * the timer instance as also returned by this method or you MAY use a + * function which has no parameters at all. * * The timer callback function MUST NOT throw an `Exception`. * The return value of the timer callback function will be ignored and has * no effect, so for performance reasons you're recommended to not return * any excessive data structures. * - * This method returns a timer instance. The same timer instance will also be - * passed into the timer callback function as described above. - * Unlike [`addTimer()`](#addtimer), this method will ensure the callback - * will be invoked infinitely after the given interval or until you invoke - * [`cancelTimer`](#canceltimer). + * Unlike [`addTimer()`](#addtimer), this method will ensure the the + * callback will be invoked infinitely after the given interval or until you + * invoke [`cancelTimer`](#canceltimer). * * ```php * $timer = $loop->addPeriodicTimer(0.1, function () { @@ -364,10 +356,9 @@ public function futureTick($listener); * This is useful to catch user interrupt signals or shutdown signals from * tools like `supervisor` or `systemd`. * - * The second parameter MUST be a listener callback function that accepts - * the signal as its only parameter. - * If you don't use the signal inside your listener callback function - * you MAY use a function which has no parameters at all. + * The listener callback function MUST be able to accept a single parameter, + * the signal added by this method or you MAY use a function which + * has no parameters at all. * * The listener callback function MUST NOT throw an `Exception`. * The return value of the listener callback function will be ignored and has @@ -382,14 +373,14 @@ public function futureTick($listener); * * See also [example #4](examples). * - * Signaling is only available on Unix-like platforms, Windows isn't + * Signaling is only available on Unix-like platform, Windows isn't * supported due to operating system limitations. * This method may throw a `BadMethodCallException` if signals aren't * supported on this platform, for example when required extensions are * missing. * * **Note: A listener can only be added once to the same signal, any - * attempts to add it more than once will be ignored.** + * attempts to add it more then once will be ignored.** * * @param int $signal * @param callable $listener @@ -422,7 +413,7 @@ public function removeSignal($signal, $listener); * * For many applications, this method is the only directly visible * invocation on the event loop. - * As a rule of thumb, it is usually recommended to attach everything to the + * As a rule of thumb, it is usally recommended to attach everything to the * same loop instance and then run the loop once at the bottom end of the * application. * @@ -440,7 +431,7 @@ public function removeSignal($signal, $listener); * for any of the attached listeners. * * This method MUST NOT be called while the loop is already running. - * This method MAY be called more than once after it has explicitly been + * This method MAY be called more than once after it has explicity been * [`stop()`ped](#stop) or after it automatically stopped because it * previously did no longer have anything to do. * diff --git a/deps/vendor/react/event-loop/src/StreamSelectLoop.php b/deps/vendor/react/event-loop/src/StreamSelectLoop.php index 1686fd740..b89d80005 100644 --- a/deps/vendor/react/event-loop/src/StreamSelectLoop.php +++ b/deps/vendor/react/event-loop/src/StreamSelectLoop.php @@ -10,14 +10,13 @@ * A `stream_select()` based event loop. * * This uses the [`stream_select()`](https://www.php.net/manual/en/function.stream-select.php) - * function and is the only implementation that works out of the box with PHP. + * function and is the only implementation which works out of the box with PHP. * - * This event loop works out of the box on PHP 5.4 through PHP 8+ and HHVM. + * This event loop works out of the box on PHP 5.4 through PHP 7+ and HHVM. * This means that no installation is required and this library works on all * platforms and supported PHP versions. - * Accordingly, the [`Loop` class](#loop) and the deprecated [`Factory`](#factory) - * will use this event loop by default if you do not install any of the event loop - * extensions listed below. + * Accordingly, the [`Factory`](#factory) will use this event loop by default if + * you do not install any of the event loop extensions listed below. * * Under the hood, it does a simple `select` system call. * This system call is limited to the maximum file descriptor number of @@ -287,29 +286,8 @@ private function streamSelect(array &$read, array &$write, $timeout) } } - /** @var ?callable $previous */ - $previous = \set_error_handler(function ($errno, $errstr) use (&$previous) { - // suppress warnings that occur when `stream_select()` is interrupted by a signal - // PHP defines `EINTR` through `ext-sockets` or `ext-pcntl`, otherwise use common default (Linux & Mac) - $eintr = \defined('SOCKET_EINTR') ? \SOCKET_EINTR : (\defined('PCNTL_EINTR') ? \PCNTL_EINTR : 4); - if ($errno === \E_WARNING && \strpos($errstr, '[' . $eintr .']: ') !== false) { - return; - } - - // forward any other error to registered error handler or print warning - return ($previous !== null) ? \call_user_func_array($previous, \func_get_args()) : false; - }); - - try { - $ret = \stream_select($read, $write, $except, $timeout === null ? null : 0, $timeout); - \restore_error_handler(); - } catch (\Throwable $e) { // @codeCoverageIgnoreStart - \restore_error_handler(); - throw $e; - } catch (\Exception $e) { - \restore_error_handler(); - throw $e; - } // @codeCoverageIgnoreEnd + // suppress warnings that occur, when stream_select is interrupted by a signal + $ret = @\stream_select($read, $write, $except, $timeout === null ? null : 0, $timeout); if ($except) { $write = \array_merge($write, $except); diff --git a/deps/vendor/react/event-loop/src/Timer/Timers.php b/deps/vendor/react/event-loop/src/Timer/Timers.php index 53c46d03b..70adc1324 100644 --- a/deps/vendor/react/event-loop/src/Timer/Timers.php +++ b/deps/vendor/react/event-loop/src/Timer/Timers.php @@ -38,7 +38,7 @@ public function getTime() public function add(TimerInterface $timer) { - $id = \PHP_VERSION_ID < 70200 ? \spl_object_hash($timer) : \spl_object_id($timer); + $id = \spl_object_hash($timer); $this->timers[$id] = $timer; $this->schedule[$id] = $timer->getInterval() + $this->updateTime(); $this->sorted = false; @@ -46,13 +46,12 @@ public function add(TimerInterface $timer) public function contains(TimerInterface $timer) { - $id = \PHP_VERSION_ID < 70200 ? \spl_object_hash($timer) : \spl_object_id($timer); - return isset($this->timers[$id]); + return isset($this->timers[\spl_object_hash($timer)]); } public function cancel(TimerInterface $timer) { - $id = \PHP_VERSION_ID < 70200 ? \spl_object_hash($timer) : \spl_object_id($timer); + $id = \spl_object_hash($timer); unset($this->timers[$id], $this->schedule[$id]); } @@ -74,11 +73,6 @@ public function isEmpty() public function tick() { - // hot path: skip timers if nothing is scheduled - if (!$this->schedule) { - return; - } - // ensure timers are sorted so we can execute in order if (!$this->sorted) { $this->sorted = true; diff --git a/deps/vendor/react/http/CHANGELOG.md b/deps/vendor/react/http/CHANGELOG.md index f69779c6e..41079cdbe 100644 --- a/deps/vendor/react/http/CHANGELOG.md +++ b/deps/vendor/react/http/CHANGELOG.md @@ -1,112 +1,5 @@ # Changelog -## 1.10.0 (2024-03-27) - -* Feature: Add new PSR-7 implementation and remove dated RingCentral PSR-7 dependency. - (#518, #519, #520 and #522 by @clue) - - This changeset allows us to maintain our own PSR-7 implementation and reduce - dependencies on external projects. It also improves performance slightly and - does not otherwise affect our public API. If you want to explicitly install - the old RingCentral PSR-7 dependency, you can still install it like this: - - ```bash - composer require ringcentral/psr7 - ``` - -* Feature: Add new `Uri` class for new PSR-7 implementation. - (#521 by @clue) - -* Feature: Validate outgoing HTTP message headers and reject invalid messages. - (#523 by @clue) - -* Feature: Full PHP 8.3 compatibility. - (#508 by @clue) - -* Fix: Fix HTTP client to omit `Transfer-Encoding: chunked` when streaming empty request body. - (#516 by @clue) - -* Fix: Ensure connection close handler is cleaned up for each request. - (#515 by @WyriHaximus) - -* Update test suite and avoid unhandled promise rejections. - (#501 and #502 by @clue) - -## 1.9.0 (2023-04-26) - -This is a **SECURITY** and feature release for the 1.x series of ReactPHP's HTTP component. - -* Security fix: This release fixes a medium severity security issue in ReactPHP's HTTP server component - that affects all versions between `v0.8.0` and `v1.8.0`. All users are encouraged to upgrade immediately. - (CVE-2023-26044 reported and fixed by @WyriHaximus) - -* Feature: Support HTTP keep-alive for HTTP client (reusing persistent connections). - (#481, #484, #486 and #495 by @clue) - - This feature offers significant performance improvements when sending many - requests to the same host as it avoids recreating the underlying TCP/IP - connection and repeating the TLS handshake for secure HTTPS requests. - - ```php - $browser = new React\Http\Browser(); - - // Up to 300% faster! HTTP keep-alive is enabled by default - $response = React\Async\await($browser->get('https://httpbingo.org/redirect/6')); - assert($response instanceof Psr\Http\Message\ResponseInterface); - ``` - -* Feature: Add `Request` class to represent outgoing HTTP request message. - (#480 by @clue) - -* Feature: Preserve request method and body for `307 Temporary Redirect` and `308 Permanent Redirect`. - (#442 by @dinooo13) - -* Feature: Include buffer logic to avoid dependency on reactphp/promise-stream. - (#482 by @clue) - -* Improve test suite and project setup and report failed assertions. - (#478 by @clue, #487 and #491 by @WyriHaximus and #475 and #479 by @SimonFrings) - -## 1.8.0 (2022-09-29) - -* Feature: Support for default request headers. - (#461 by @51imyy) - - ```php - $browser = new React\Http\Browser(); - $browser = $browser->withHeader('User-Agent', 'ACME'); - - $browser->get($url)->then(…); - ``` - -* Feature: Forward compatibility with upcoming Promise v3. - (#460 by @clue) - -## 1.7.0 (2022-08-23) - -This is a **SECURITY** and feature release for the 1.x series of ReactPHP's HTTP component. - -* Security fix: This release fixes a medium severity security issue in ReactPHP's HTTP server component - that affects all versions between `v0.7.0` and `v1.6.0`. All users are encouraged to upgrade immediately. - Special thanks to Marco Squarcina (TU Wien) for reporting this and working with us to coordinate this release. - (CVE-2022-36032 reported by @lavish and fixed by @clue) - -* Feature: Improve HTTP server performance by ~20%, reuse syscall values for clock time and socket addresses. - (#457 and #467 by @clue) - -* Feature: Full PHP 8.2+ compatibility, refactor internal `Transaction` to avoid assigning dynamic properties. - (#459 by @clue and #466 by @WyriHaximus) - -* Feature / Fix: Allow explicit `Content-Length` response header on `HEAD` requests. - (#444 by @mrsimonbennett) - -* Minor documentation improvements. - (#452 by @clue, #458 by @nhedger, #448 by @jorrit and #446 by @SimonFrings) - -* Improve test suite, update to use new reactphp/async package instead of clue/reactphp-block, - skip memory tests when lowering memory limit fails and fix legacy HHVM build. - (#464 and #440 by @clue and #450 by @SimonFrings) - ## 1.6.0 (2022-02-03) * Feature: Add factory methods for common HTML/JSON/plaintext/XML response types. @@ -117,6 +10,7 @@ This is a **SECURITY** and feature release for the 1.x series of ReactPHP's HTTP $response = React\Http\Response\json(['message' => 'Hello wörld!']); $response = React\Http\Response\plaintext("Hello wörld!\n"); $response = React\Http\Response\xml("Hello wörld!\n"); + $response = React\Http\Response\redirect('https://reactphp.org/'); ``` * Feature: Expose all status code constants via `Response` class. diff --git a/deps/vendor/react/http/README.md b/deps/vendor/react/http/README.md index d05506427..8e58aebca 100644 --- a/deps/vendor/react/http/README.md +++ b/deps/vendor/react/http/README.md @@ -1,7 +1,6 @@ # HTTP -[![CI status](https://github.com/reactphp/http/actions/workflows/ci.yml/badge.svg)](https://github.com/reactphp/http/actions) -[![installs on Packagist](https://img.shields.io/packagist/dt/react/http?color=blue&label=installs%20on%20Packagist)](https://packagist.org/packages/react/http) +[![CI status](https://github.com/reactphp/http/workflows/CI/badge.svg)](https://github.com/reactphp/http/actions) Event-driven, streaming HTTP client and server implementation for [ReactPHP](https://reactphp.org/). @@ -69,17 +68,13 @@ multiple concurrent HTTP requests without blocking. * [withBase()](#withbase) * [withProtocolVersion()](#withprotocolversion) * [withResponseBuffer()](#withresponsebuffer) - * [withHeader()](#withheader) - * [withoutHeader()](#withoutheader) * [React\Http\Message](#reacthttpmessage) * [Response](#response) * [html()](#html) * [json()](#json) * [plaintext()](#plaintext) * [xml()](#xml) - * [Request](#request-1) * [ServerRequest](#serverrequest) - * [Uri](#uri) * [ResponseException](#responseexception) * [React\Http\Middleware](#reacthttpmiddleware) * [StreamingRequestMiddleware](#streamingrequestmiddleware) @@ -344,10 +339,9 @@ $browser->get($url, $headers)->then(function (Psr\Http\Message\ResponseInterface Any redirected requests will follow the semantics of the original request and will include the same request headers as the original request except for those listed below. -If the original request is a temporary (307) or a permanent (308) redirect, request -body and headers will be passed to the redirected request. Otherwise, the request -body will never be passed to the redirected request. Accordingly, each redirected -request will remove any `Content-Length` and `Content-Type` request headers. +If the original request contained a request body, this request body will never +be passed to the redirected request. Accordingly, each redirected request will +remove any `Content-Length` and `Content-Type` request headers. If the original request used HTTP authentication with an `Authorization` request header, this request header will only be passed as part of the redirected @@ -378,42 +372,38 @@ See also [`withFollowRedirects()`](#withfollowredirects) for more details. As stated above, this library provides you a powerful, async API by default. -You can also integrate this into your traditional, blocking environment by using -[reactphp/async](https://github.com/reactphp/async). This allows you to simply -await async HTTP requests like this: +If, however, you want to integrate this into your traditional, blocking environment, +you should look into also using [clue/reactphp-block](https://github.com/clue/reactphp-block). + +The resulting blocking code could look something like this: ```php -use function React\Async\await; +use Clue\React\Block; $browser = new React\Http\Browser(); $promise = $browser->get('http://example.com/'); try { - $response = await($promise); + $response = Block\await($promise, Loop::get()); // response successfully received } catch (Exception $e) { - // an error occurred while performing the request + // an error occured while performing the request } ``` Similarly, you can also process multiple requests concurrently and await an array of `Response` objects: ```php -use function React\Async\await; -use function React\Promise\all; - $promises = array( $browser->get('http://example.com/'), $browser->get('http://www.example.org/'), ); -$responses = await(all($promises)); +$responses = Block\awaitAll($promises, Loop::get()); ``` -This is made possible thanks to fibers available in PHP 8.1+ and our -compatibility API that also works on all supported PHP versions. -Please refer to [reactphp/async](https://github.com/reactphp/async#readme) for more details. +Please refer to [clue/reactphp-block](https://github.com/clue/reactphp-block#readme) for more details. Keep in mind the above remark about buffering the whole response message in memory. As an alternative, you may also see one of the following chapters for the @@ -1309,7 +1299,7 @@ get all cookies sent with the current request. ```php $http = new React\Http\HttpServer(function (Psr\Http\Message\ServerRequestInterface $request) { - $key = 'greeting'; + $key = 'react\php'; if (isset($request->getCookieParams()[$key])) { $body = "Your cookie value is: " . $request->getCookieParams()[$key] . "\n"; @@ -1321,7 +1311,7 @@ $http = new React\Http\HttpServer(function (Psr\Http\Message\ServerRequestInterf return React\Http\Message\Response::plaintext( "Your cookie has been set.\n" - )->withHeader('Set-Cookie', $key . '=' . urlencode('Hello world!')); + )->withHeader('Set-Cookie', urlencode($key) . '=' . urlencode('test;more')); }); ``` @@ -1435,23 +1425,15 @@ may only support strings. $http = new React\Http\HttpServer(function (Psr\Http\Message\ServerRequestInterface $request) { $stream = new ThroughStream(); - // send some data every once in a while with periodic timer $timer = Loop::addPeriodicTimer(0.5, function () use ($stream) { $stream->write(microtime(true) . PHP_EOL); }); - // end stream after a few seconds - $timeout = Loop::addTimer(5.0, function() use ($stream, $timer) { + Loop::addTimer(5, function() use ($timer, $stream) { Loop::cancelTimer($timer); $stream->end(); }); - // stop timer if stream is closed (such as when connection is closed) - $stream->on('close', function () use ($timer, $timeout) { - Loop::cancelTimer($timer); - Loop::cancelTimer($timeout); - }); - return new React\Http\Message\Response( React\Http\Message\Response::STATUS_OK, array( @@ -2390,36 +2372,6 @@ Notice that the [`Browser`](#browser) is an immutable object, i.e. this method actually returns a *new* [`Browser`](#browser) instance with the given setting applied. -#### withHeader() - -The `withHeader(string $header, string $value): Browser` method can be used to -add a request header for all following requests. - -```php -$browser = $browser->withHeader('User-Agent', 'ACME'); - -$browser->get($url)->then(…); -``` - -Note that the new header will overwrite any headers previously set with -the same name (case-insensitive). Following requests will use these headers -by default unless they are explicitly set for any requests. - -#### withoutHeader() - -The `withoutHeader(string $header): Browser` method can be used to -remove any default request headers previously set via -the [`withHeader()` method](#withheader). - -```php -$browser = $browser->withoutHeader('User-Agent'); - -$browser->get($url)->then(…); -``` - -Note that this method only affects the headers which were set with the -method `withHeader(string $header, string $value): Browser` - ### React\Http\Message #### Response @@ -2449,7 +2401,8 @@ constants with the `STATUS_*` prefix. For instance, the `200 OK` and `404 Not Found` status codes can used as `Response::STATUS_OK` and `Response::STATUS_NOT_FOUND` respectively. -> Internally, this implementation builds on top of a base class which is +> Internally, this implementation builds on top of an existing incoming + response message and only adds required streaming support. This base class is considered an implementation detail that may change in the future. ##### html() @@ -2629,23 +2582,6 @@ $response = React\Http\Message\Response::xml( )->withStatus(React\Http\Message\Response::STATUS_BAD_REQUEST); ``` -#### Request - -The `React\Http\Message\Request` class can be used to -respresent an outgoing HTTP request message. - -This class implements the -[PSR-7 `RequestInterface`](https://www.php-fig.org/psr/psr-7/#32-psrhttpmessagerequestinterface) -which extends the -[PSR-7 `MessageInterface`](https://www.php-fig.org/psr/psr-7/#31-psrhttpmessagemessageinterface). - -This is mostly used internally to represent each outgoing HTTP request -message for the HTTP client implementation. Likewise, you can also use this -class with other HTTP client implementations and for tests. - -> Internally, this implementation builds on top of a base class which is - considered an implementation detail that may change in the future. - #### ServerRequest The `React\Http\Message\ServerRequest` class can be used to @@ -2662,21 +2598,10 @@ This is mostly used internally to represent each incoming request message. Likewise, you can also use this class in test cases to test how your web application reacts to certain HTTP requests. -> Internally, this implementation builds on top of a base class which is +> Internally, this implementation builds on top of an existing outgoing + request message and only adds required server methods. This base class is considered an implementation detail that may change in the future. -#### Uri - -The `React\Http\Message\Uri` class can be used to -respresent a URI (or URL). - -This class implements the -[PSR-7 `UriInterface`](https://www.php-fig.org/psr/psr-7/#35-psrhttpmessageuriinterface). - -This is mostly used internally to represent the URI of each HTTP request -message for our HTTP client and server implementations. Likewise, you may -also use this class with other HTTP implementations and for tests. - #### ResponseException The `React\Http\Message\ResponseException` is an `Exception` sub-class that will be used to reject @@ -2986,7 +2911,7 @@ This project follows [SemVer](https://semver.org/). This will install the latest supported version: ```bash -composer require react/http:^1.10 +$ composer require react/http:^1.6 ``` See also the [CHANGELOG](CHANGELOG.md) for details about version upgrades. @@ -3002,13 +2927,13 @@ To run the test suite, you first need to clone this repo and then install all dependencies [through Composer](https://getcomposer.org/): ```bash -composer install +$ composer install ``` To run the test suite, go to the project root and run: ```bash -vendor/bin/phpunit +$ vendor/bin/phpunit ``` The test suite also contains a number of functional integration tests that rely @@ -3016,7 +2941,7 @@ on a stable internet connection. If you do not want to run these, they can simply be skipped like this: ```bash -vendor/bin/phpunit --exclude-group internet +$ vendor/bin/phpunit --exclude-group internet ``` ## License diff --git a/deps/vendor/react/http/composer.json b/deps/vendor/react/http/composer.json index 23783c0c5..4c9a03834 100644 --- a/deps/vendor/react/http/composer.json +++ b/deps/vendor/react/http/composer.json @@ -31,27 +31,23 @@ "fig/http-message-util": "^1.1", "psr/http-message": "^1.0", "react/event-loop": "^1.2", - "react/promise": "^3 || ^2.3 || ^1.2.1", - "react/socket": "^1.12", - "react/stream": "^1.2" + "react/promise": "^2.3 || ^1.2.1", + "react/promise-stream": "^1.1", + "react/socket": "^1.9", + "react/stream": "^1.2", + "ringcentral/psr7": "^1.2" }, "require-dev": { - "clue/http-proxy-react": "^1.8", - "clue/reactphp-ssh-proxy": "^1.4", - "clue/socks-react": "^1.4", - "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", - "react/async": "^4 || ^3 || ^2", - "react/promise-stream": "^1.4", - "react/promise-timer": "^1.9" + "clue/block-react": "^1.5", + "clue/http-proxy-react": "^1.7", + "clue/reactphp-ssh-proxy": "^1.3", + "clue/socks-react": "^1.3", + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35" }, "autoload": { - "psr-4": { - "React\\Http\\": "src/" - } + "psr-4": { "React\\Http\\": "src" } }, "autoload-dev": { - "psr-4": { - "React\\Tests\\Http\\": "tests/" - } + "psr-4": { "React\\Tests\\Http\\": "tests" } } } diff --git a/deps/vendor/react/http/src/Browser.php b/deps/vendor/react/http/src/Browser.php index 01a266cad..72847f66b 100644 --- a/deps/vendor/react/http/src/Browser.php +++ b/deps/vendor/react/http/src/Browser.php @@ -3,12 +3,13 @@ namespace React\Http; use Psr\Http\Message\ResponseInterface; +use RingCentral\Psr7\Request; +use RingCentral\Psr7\Uri; use React\EventLoop\Loop; use React\EventLoop\LoopInterface; +use React\Http\Io\ReadableBodyStream; use React\Http\Io\Sender; use React\Http\Io\Transaction; -use React\Http\Message\Request; -use React\Http\Message\Uri; use React\Promise\PromiseInterface; use React\Socket\ConnectorInterface; use React\Stream\ReadableStreamInterface; @@ -22,9 +23,6 @@ class Browser private $transaction; private $baseUrl; private $protocolVersion = '1.1'; - private $defaultHeaders = array( - 'User-Agent' => 'ReactPHP/1' - ); /** * The `Browser` is responsible for sending HTTP requests to your HTTP server @@ -344,7 +342,7 @@ public function delete($url, array $headers = array(), $body = '') * @param string $url URL for the request * @param array $headers Additional request headers * @param string|ReadableStreamInterface $body HTTP request body contents - * @return PromiseInterface + * @return PromiseInterface */ public function request($method, $url, array $headers = array(), $body = '') { @@ -417,7 +415,7 @@ public function request($method, $url, array $headers = array(), $body = '') * @param string $url URL for the request * @param array $headers Additional request headers * @param string|ReadableStreamInterface $body HTTP request body contents - * @return PromiseInterface + * @return PromiseInterface */ public function requestStreaming($method, $url, $headers = array(), $body = '') { @@ -727,62 +725,6 @@ public function withResponseBuffer($maximumSize) )); } - /** - * Add a request header for all following requests. - * - * ```php - * $browser = $browser->withHeader('User-Agent', 'ACME'); - * - * $browser->get($url)->then(…); - * ``` - * - * Note that the new header will overwrite any headers previously set with - * the same name (case-insensitive). Following requests will use these headers - * by default unless they are explicitly set for any requests. - * - * @param string $header - * @param string $value - * @return Browser - */ - public function withHeader($header, $value) - { - $browser = $this->withoutHeader($header); - $browser->defaultHeaders[$header] = $value; - - return $browser; - } - - /** - * Remove any default request headers previously set via - * the [`withHeader()` method](#withheader). - * - * ```php - * $browser = $browser->withoutHeader('User-Agent'); - * - * $browser->get($url)->then(…); - * ``` - * - * Note that this method only affects the headers which were set with the - * method `withHeader(string $header, string $value): Browser` - * - * @param string $header - * @return Browser - */ - public function withoutHeader($header) - { - $browser = clone $this; - - /** @var string|int $key */ - foreach (\array_keys($browser->defaultHeaders) as $key) { - if (\strcasecmp($key, $header) === 0) { - unset($browser->defaultHeaders[$key]); - break; - } - } - - return $browser; - } - /** * Changes the [options](#options) to use: * @@ -828,26 +770,17 @@ private function withOptions(array $options) * @param string $url * @param array $headers * @param string|ReadableStreamInterface $body - * @return PromiseInterface + * @return PromiseInterface */ private function requestMayBeStreaming($method, $url, array $headers = array(), $body = '') { if ($this->baseUrl !== null) { // ensure we're actually below the base URL - $url = Uri::resolve($this->baseUrl, new Uri($url)); + $url = Uri::resolve($this->baseUrl, $url); } - foreach ($this->defaultHeaders as $key => $value) { - $explicitHeaderExists = false; - foreach (\array_keys($headers) as $headerKey) { - if (\strcasecmp($headerKey, $key) === 0) { - $explicitHeaderExists = true; - break; - } - } - if (!$explicitHeaderExists) { - $headers[$key] = $value; - } + if ($body instanceof ReadableStreamInterface) { + $body = new ReadableBodyStream($body); } return $this->transaction->send( diff --git a/deps/vendor/react/http/src/Client/Client.php b/deps/vendor/react/http/src/Client/Client.php index 7a5180abd..7a97349c1 100644 --- a/deps/vendor/react/http/src/Client/Client.php +++ b/deps/vendor/react/http/src/Client/Client.php @@ -2,26 +2,30 @@ namespace React\Http\Client; -use Psr\Http\Message\RequestInterface; -use React\Http\Io\ClientConnectionManager; -use React\Http\Io\ClientRequestStream; +use React\EventLoop\LoopInterface; +use React\Socket\ConnectorInterface; +use React\Socket\Connector; /** * @internal */ class Client { - /** @var ClientConnectionManager */ - private $connectionManager; + private $connector; - public function __construct(ClientConnectionManager $connectionManager) + public function __construct(LoopInterface $loop, ConnectorInterface $connector = null) { - $this->connectionManager = $connectionManager; + if ($connector === null) { + $connector = new Connector(array(), $loop); + } + + $this->connector = $connector; } - /** @return ClientRequestStream */ - public function request(RequestInterface $request) + public function request($method, $url, array $headers = array(), $protocolVersion = '1.0') { - return new ClientRequestStream($this->connectionManager, $request); + $requestData = new RequestData($method, $url, $headers, $protocolVersion); + + return new Request($this->connector, $requestData); } } diff --git a/deps/vendor/react/http/src/Client/Request.php b/deps/vendor/react/http/src/Client/Request.php new file mode 100644 index 000000000..51e033133 --- /dev/null +++ b/deps/vendor/react/http/src/Client/Request.php @@ -0,0 +1,237 @@ +connector = $connector; + $this->requestData = $requestData; + } + + public function isWritable() + { + return self::STATE_END > $this->state && !$this->ended; + } + + private function writeHead() + { + $this->state = self::STATE_WRITING_HEAD; + + $requestData = $this->requestData; + $streamRef = &$this->stream; + $stateRef = &$this->state; + $pendingWrites = &$this->pendingWrites; + $that = $this; + + $promise = $this->connect(); + $promise->then( + function (ConnectionInterface $stream) use ($requestData, &$streamRef, &$stateRef, &$pendingWrites, $that) { + $streamRef = $stream; + + $stream->on('drain', array($that, 'handleDrain')); + $stream->on('data', array($that, 'handleData')); + $stream->on('end', array($that, 'handleEnd')); + $stream->on('error', array($that, 'handleError')); + $stream->on('close', array($that, 'handleClose')); + + $headers = (string) $requestData; + + $more = $stream->write($headers . $pendingWrites); + + $stateRef = Request::STATE_HEAD_WRITTEN; + + // clear pending writes if non-empty + if ($pendingWrites !== '') { + $pendingWrites = ''; + + if ($more) { + $that->emit('drain'); + } + } + }, + array($this, 'closeError') + ); + + $this->on('close', function() use ($promise) { + $promise->cancel(); + }); + } + + public function write($data) + { + if (!$this->isWritable()) { + return false; + } + + // write directly to connection stream if already available + if (self::STATE_HEAD_WRITTEN <= $this->state) { + return $this->stream->write($data); + } + + // otherwise buffer and try to establish connection + $this->pendingWrites .= $data; + if (self::STATE_WRITING_HEAD > $this->state) { + $this->writeHead(); + } + + return false; + } + + public function end($data = null) + { + if (!$this->isWritable()) { + return; + } + + if (null !== $data) { + $this->write($data); + } else if (self::STATE_WRITING_HEAD > $this->state) { + $this->writeHead(); + } + + $this->ended = true; + } + + /** @internal */ + public function handleDrain() + { + $this->emit('drain'); + } + + /** @internal */ + public function handleData($data) + { + $this->buffer .= $data; + + // buffer until double CRLF (or double LF for compatibility with legacy servers) + if (false !== strpos($this->buffer, "\r\n\r\n") || false !== strpos($this->buffer, "\n\n")) { + try { + $response = gPsr\parse_response($this->buffer); + $bodyChunk = (string) $response->getBody(); + } catch (\InvalidArgumentException $exception) { + $this->emit('error', array($exception)); + } + + $this->buffer = null; + + $this->stream->removeListener('drain', array($this, 'handleDrain')); + $this->stream->removeListener('data', array($this, 'handleData')); + $this->stream->removeListener('end', array($this, 'handleEnd')); + $this->stream->removeListener('error', array($this, 'handleError')); + $this->stream->removeListener('close', array($this, 'handleClose')); + + if (!isset($response)) { + return; + } + + $this->stream->on('close', array($this, 'handleClose')); + + $this->emit('response', array($response, $this->stream)); + + $this->stream->emit('data', array($bodyChunk)); + } + } + + /** @internal */ + public function handleEnd() + { + $this->closeError(new \RuntimeException( + "Connection ended before receiving response" + )); + } + + /** @internal */ + public function handleError(\Exception $error) + { + $this->closeError(new \RuntimeException( + "An error occurred in the underlying stream", + 0, + $error + )); + } + + /** @internal */ + public function handleClose() + { + $this->close(); + } + + /** @internal */ + public function closeError(\Exception $error) + { + if (self::STATE_END <= $this->state) { + return; + } + $this->emit('error', array($error)); + $this->close(); + } + + public function close() + { + if (self::STATE_END <= $this->state) { + return; + } + + $this->state = self::STATE_END; + $this->pendingWrites = ''; + + if ($this->stream) { + $this->stream->close(); + } + + $this->emit('close'); + $this->removeAllListeners(); + } + + protected function connect() + { + $scheme = $this->requestData->getScheme(); + if ($scheme !== 'https' && $scheme !== 'http') { + return Promise\reject( + new \InvalidArgumentException('Invalid request URL given') + ); + } + + $host = $this->requestData->getHost(); + $port = $this->requestData->getPort(); + + if ($scheme === 'https') { + $host = 'tls://' . $host; + } + + return $this->connector + ->connect($host . ':' . $port); + } +} diff --git a/deps/vendor/react/http/src/Client/RequestData.php b/deps/vendor/react/http/src/Client/RequestData.php new file mode 100644 index 000000000..a5908a085 --- /dev/null +++ b/deps/vendor/react/http/src/Client/RequestData.php @@ -0,0 +1,128 @@ +method = $method; + $this->url = $url; + $this->headers = $headers; + $this->protocolVersion = $protocolVersion; + } + + private function mergeDefaultheaders(array $headers) + { + $port = ($this->getDefaultPort() === $this->getPort()) ? '' : ":{$this->getPort()}"; + $connectionHeaders = ('1.1' === $this->protocolVersion) ? array('Connection' => 'close') : array(); + $authHeaders = $this->getAuthHeaders(); + + $defaults = array_merge( + array( + 'Host' => $this->getHost().$port, + 'User-Agent' => 'ReactPHP/1', + ), + $connectionHeaders, + $authHeaders + ); + + // remove all defaults that already exist in $headers + $lower = array_change_key_case($headers, CASE_LOWER); + foreach ($defaults as $key => $_) { + if (isset($lower[strtolower($key)])) { + unset($defaults[$key]); + } + } + + return array_merge($defaults, $headers); + } + + public function getScheme() + { + return parse_url($this->url, PHP_URL_SCHEME); + } + + public function getHost() + { + return parse_url($this->url, PHP_URL_HOST); + } + + public function getPort() + { + return (int) parse_url($this->url, PHP_URL_PORT) ?: $this->getDefaultPort(); + } + + public function getDefaultPort() + { + return ('https' === $this->getScheme()) ? 443 : 80; + } + + public function getPath() + { + $path = parse_url($this->url, PHP_URL_PATH); + $queryString = parse_url($this->url, PHP_URL_QUERY); + + // assume "/" path by default, but allow "OPTIONS *" + if ($path === null) { + $path = ($this->method === 'OPTIONS' && $queryString === null) ? '*': '/'; + } + if ($queryString !== null) { + $path .= '?' . $queryString; + } + + return $path; + } + + public function setProtocolVersion($version) + { + $this->protocolVersion = $version; + } + + public function __toString() + { + $headers = $this->mergeDefaultheaders($this->headers); + + $data = ''; + $data .= "{$this->method} {$this->getPath()} HTTP/{$this->protocolVersion}\r\n"; + foreach ($headers as $name => $values) { + foreach ((array)$values as $value) { + $data .= "$name: $value\r\n"; + } + } + $data .= "\r\n"; + + return $data; + } + + private function getUrlUserPass() + { + $components = parse_url($this->url); + + if (isset($components['user'])) { + return array( + 'user' => $components['user'], + 'pass' => isset($components['pass']) ? $components['pass'] : null, + ); + } + } + + private function getAuthHeaders() + { + if (null !== $auth = $this->getUrlUserPass()) { + return array( + 'Authorization' => 'Basic ' . base64_encode($auth['user'].':'.$auth['pass']), + ); + } + + return array(); + } +} diff --git a/deps/vendor/react/http/src/Io/AbstractMessage.php b/deps/vendor/react/http/src/Io/AbstractMessage.php deleted file mode 100644 index a0706bb12..000000000 --- a/deps/vendor/react/http/src/Io/AbstractMessage.php +++ /dev/null @@ -1,172 +0,0 @@ -@,;:\\\"\/\[\]?={}\x00-\x20\x7F]++):[\x20\x09]*+((?:[\x20\x09]*+[\x21-\x7E\x80-\xFF]++)*+)[\x20\x09]*+[\r]?+\n/m'; - - /** @var array */ - private $headers = array(); - - /** @var array */ - private $headerNamesLowerCase = array(); - - /** @var string */ - private $protocolVersion; - - /** @var StreamInterface */ - private $body; - - /** - * @param string $protocolVersion - * @param array $headers - * @param StreamInterface $body - */ - protected function __construct($protocolVersion, array $headers, StreamInterface $body) - { - foreach ($headers as $name => $value) { - if ($value !== array()) { - if (\is_array($value)) { - foreach ($value as &$one) { - $one = (string) $one; - } - } else { - $value = array((string) $value); - } - - $lower = \strtolower($name); - if (isset($this->headerNamesLowerCase[$lower])) { - $value = \array_merge($this->headers[$this->headerNamesLowerCase[$lower]], $value); - unset($this->headers[$this->headerNamesLowerCase[$lower]]); - } - - $this->headers[$name] = $value; - $this->headerNamesLowerCase[$lower] = $name; - } - } - - $this->protocolVersion = (string) $protocolVersion; - $this->body = $body; - } - - public function getProtocolVersion() - { - return $this->protocolVersion; - } - - public function withProtocolVersion($version) - { - if ((string) $version === $this->protocolVersion) { - return $this; - } - - $message = clone $this; - $message->protocolVersion = (string) $version; - - return $message; - } - - public function getHeaders() - { - return $this->headers; - } - - public function hasHeader($name) - { - return isset($this->headerNamesLowerCase[\strtolower($name)]); - } - - public function getHeader($name) - { - $lower = \strtolower($name); - return isset($this->headerNamesLowerCase[$lower]) ? $this->headers[$this->headerNamesLowerCase[$lower]] : array(); - } - - public function getHeaderLine($name) - { - return \implode(', ', $this->getHeader($name)); - } - - public function withHeader($name, $value) - { - if ($value === array()) { - return $this->withoutHeader($name); - } elseif (\is_array($value)) { - foreach ($value as &$one) { - $one = (string) $one; - } - } else { - $value = array((string) $value); - } - - $lower = \strtolower($name); - if (isset($this->headerNamesLowerCase[$lower]) && $this->headerNamesLowerCase[$lower] === (string) $name && $this->headers[$this->headerNamesLowerCase[$lower]] === $value) { - return $this; - } - - $message = clone $this; - if (isset($message->headerNamesLowerCase[$lower])) { - unset($message->headers[$message->headerNamesLowerCase[$lower]]); - } - - $message->headers[$name] = $value; - $message->headerNamesLowerCase[$lower] = $name; - - return $message; - } - - public function withAddedHeader($name, $value) - { - if ($value === array()) { - return $this; - } - - return $this->withHeader($name, \array_merge($this->getHeader($name), \is_array($value) ? $value : array($value))); - } - - public function withoutHeader($name) - { - $lower = \strtolower($name); - if (!isset($this->headerNamesLowerCase[$lower])) { - return $this; - } - - $message = clone $this; - unset($message->headers[$message->headerNamesLowerCase[$lower]], $message->headerNamesLowerCase[$lower]); - - return $message; - } - - public function getBody() - { - return $this->body; - } - - public function withBody(StreamInterface $body) - { - if ($body === $this->body) { - return $this; - } - - $message = clone $this; - $message->body = $body; - - return $message; - } -} diff --git a/deps/vendor/react/http/src/Io/AbstractRequest.php b/deps/vendor/react/http/src/Io/AbstractRequest.php deleted file mode 100644 index f32307f79..000000000 --- a/deps/vendor/react/http/src/Io/AbstractRequest.php +++ /dev/null @@ -1,156 +0,0 @@ - $headers - * @param StreamInterface $body - * @param string unknown $protocolVersion - */ - protected function __construct( - $method, - $uri, - array $headers, - StreamInterface $body, - $protocolVersion - ) { - if (\is_string($uri)) { - $uri = new Uri($uri); - } elseif (!$uri instanceof UriInterface) { - throw new \InvalidArgumentException( - 'Argument #2 ($uri) expected string|Psr\Http\Message\UriInterface' - ); - } - - // assign default `Host` request header from URI unless already given explicitly - $host = $uri->getHost(); - if ($host !== '') { - foreach ($headers as $name => $value) { - if (\strtolower($name) === 'host' && $value !== array()) { - $host = ''; - break; - } - } - if ($host !== '') { - $port = $uri->getPort(); - if ($port !== null && (!($port === 80 && $uri->getScheme() === 'http') || !($port === 443 && $uri->getScheme() === 'https'))) { - $host .= ':' . $port; - } - - $headers = array('Host' => $host) + $headers; - } - } - - parent::__construct($protocolVersion, $headers, $body); - - $this->method = $method; - $this->uri = $uri; - } - - public function getRequestTarget() - { - if ($this->requestTarget !== null) { - return $this->requestTarget; - } - - $target = $this->uri->getPath(); - if ($target === '') { - $target = '/'; - } - if (($query = $this->uri->getQuery()) !== '') { - $target .= '?' . $query; - } - - return $target; - } - - public function withRequestTarget($requestTarget) - { - if ((string) $requestTarget === $this->requestTarget) { - return $this; - } - - $request = clone $this; - $request->requestTarget = (string) $requestTarget; - - return $request; - } - - public function getMethod() - { - return $this->method; - } - - public function withMethod($method) - { - if ((string) $method === $this->method) { - return $this; - } - - $request = clone $this; - $request->method = (string) $method; - - return $request; - } - - public function getUri() - { - return $this->uri; - } - - public function withUri(UriInterface $uri, $preserveHost = false) - { - if ($uri === $this->uri) { - return $this; - } - - $request = clone $this; - $request->uri = $uri; - - $host = $uri->getHost(); - $port = $uri->getPort(); - if ($port !== null && $host !== '' && (!($port === 80 && $uri->getScheme() === 'http') || !($port === 443 && $uri->getScheme() === 'https'))) { - $host .= ':' . $port; - } - - // update `Host` request header if URI contains a new host and `$preserveHost` is false - if ($host !== '' && (!$preserveHost || $request->getHeaderLine('Host') === '')) { - // first remove all headers before assigning `Host` header to ensure it always comes first - foreach (\array_keys($request->getHeaders()) as $name) { - $request = $request->withoutHeader($name); - } - - // add `Host` header first, then all other original headers - $request = $request->withHeader('Host', $host); - foreach ($this->withoutHeader('Host')->getHeaders() as $name => $value) { - $request = $request->withHeader($name, $value); - } - } - - return $request; - } -} diff --git a/deps/vendor/react/http/src/Io/ClientConnectionManager.php b/deps/vendor/react/http/src/Io/ClientConnectionManager.php deleted file mode 100644 index faac98b68..000000000 --- a/deps/vendor/react/http/src/Io/ClientConnectionManager.php +++ /dev/null @@ -1,137 +0,0 @@ -connector = $connector; - $this->loop = $loop; - } - - /** - * @return PromiseInterface - */ - public function connect(UriInterface $uri) - { - $scheme = $uri->getScheme(); - if ($scheme !== 'https' && $scheme !== 'http') { - return \React\Promise\reject(new \InvalidArgumentException( - 'Invalid request URL given' - )); - } - - $port = $uri->getPort(); - if ($port === null) { - $port = $scheme === 'https' ? 443 : 80; - } - $uri = ($scheme === 'https' ? 'tls://' : '') . $uri->getHost() . ':' . $port; - - // Reuse idle connection for same URI if available - foreach ($this->idleConnections as $id => $connection) { - if ($this->idleUris[$id] === $uri) { - assert($this->idleStreamHandlers[$id] instanceof \Closure); - $connection->removeListener('close', $this->idleStreamHandlers[$id]); - $connection->removeListener('data', $this->idleStreamHandlers[$id]); - $connection->removeListener('error', $this->idleStreamHandlers[$id]); - - assert($this->idleTimers[$id] instanceof TimerInterface); - $this->loop->cancelTimer($this->idleTimers[$id]); - unset($this->idleUris[$id], $this->idleConnections[$id], $this->idleTimers[$id], $this->idleStreamHandlers[$id]); - - return \React\Promise\resolve($connection); - } - } - - // Create new connection if no idle connection to same URI is available - return $this->connector->connect($uri); - } - - /** - * Hands back an idle connection to the connection manager for possible future reuse. - * - * @return void - */ - public function keepAlive(UriInterface $uri, ConnectionInterface $connection) - { - $scheme = $uri->getScheme(); - assert($scheme === 'https' || $scheme === 'http'); - - $port = $uri->getPort(); - if ($port === null) { - $port = $scheme === 'https' ? 443 : 80; - } - - $this->idleUris[] = ($scheme === 'https' ? 'tls://' : '') . $uri->getHost() . ':' . $port; - $this->idleConnections[] = $connection; - - $that = $this; - $cleanUp = function () use ($connection, $that) { - // call public method to support legacy PHP 5.3 - $that->cleanUpConnection($connection); - }; - - // clean up and close connection when maximum time to keep-alive idle connection has passed - $this->idleTimers[] = $this->loop->addTimer($this->maximumTimeToKeepAliveIdleConnection, $cleanUp); - - // clean up and close connection when unexpected close/data/error event happens during idle time - $this->idleStreamHandlers[] = $cleanUp; - $connection->on('close', $cleanUp); - $connection->on('data', $cleanUp); - $connection->on('error', $cleanUp); - } - - /** - * @internal - * @return void - */ - public function cleanUpConnection(ConnectionInterface $connection) // private (PHP 5.4+) - { - $id = \array_search($connection, $this->idleConnections, true); - if ($id === false) { - return; - } - - assert(\is_int($id)); - assert($this->idleTimers[$id] instanceof TimerInterface); - $this->loop->cancelTimer($this->idleTimers[$id]); - unset($this->idleUris[$id], $this->idleConnections[$id], $this->idleTimers[$id], $this->idleStreamHandlers[$id]); - - $connection->close(); - } -} diff --git a/deps/vendor/react/http/src/Io/ClientRequestState.php b/deps/vendor/react/http/src/Io/ClientRequestState.php deleted file mode 100644 index 73a63a14f..000000000 --- a/deps/vendor/react/http/src/Io/ClientRequestState.php +++ /dev/null @@ -1,16 +0,0 @@ -connectionManager = $connectionManager; - $this->request = $request; - } - - public function isWritable() - { - return self::STATE_END > $this->state && !$this->ended; - } - - private function writeHead() - { - $this->state = self::STATE_WRITING_HEAD; - - $expected = 0; - $headers = "{$this->request->getMethod()} {$this->request->getRequestTarget()} HTTP/{$this->request->getProtocolVersion()}\r\n"; - foreach ($this->request->getHeaders() as $name => $values) { - if (\strpos($name, ':') !== false) { - $expected = -1; - break; - } - foreach ($values as $value) { - $headers .= "$name: $value\r\n"; - ++$expected; - } - } - - /** @var array $m legacy PHP 5.3 only */ - if (!\preg_match('#^\S+ \S+ HTTP/1\.[01]\r\n#m', $headers) || \substr_count($headers, "\n") !== ($expected + 1) || (\PHP_VERSION_ID >= 50400 ? \preg_match_all(AbstractMessage::REGEX_HEADERS, $headers) : \preg_match_all(AbstractMessage::REGEX_HEADERS, $headers, $m)) !== $expected) { - $this->closeError(new \InvalidArgumentException('Unable to send request with invalid request headers')); - return; - } - - $connectionRef = &$this->connection; - $stateRef = &$this->state; - $pendingWrites = &$this->pendingWrites; - $that = $this; - - $promise = $this->connectionManager->connect($this->request->getUri()); - $promise->then( - function (ConnectionInterface $connection) use ($headers, &$connectionRef, &$stateRef, &$pendingWrites, $that) { - $connectionRef = $connection; - assert($connectionRef instanceof ConnectionInterface); - - $connection->on('drain', array($that, 'handleDrain')); - $connection->on('data', array($that, 'handleData')); - $connection->on('end', array($that, 'handleEnd')); - $connection->on('error', array($that, 'handleError')); - $connection->on('close', array($that, 'close')); - - $more = $connection->write($headers . "\r\n" . $pendingWrites); - - assert($stateRef === ClientRequestStream::STATE_WRITING_HEAD); - $stateRef = ClientRequestStream::STATE_HEAD_WRITTEN; - - // clear pending writes if non-empty - if ($pendingWrites !== '') { - $pendingWrites = ''; - - if ($more) { - $that->emit('drain'); - } - } - }, - array($this, 'closeError') - ); - - $this->on('close', function() use ($promise) { - $promise->cancel(); - }); - } - - public function write($data) - { - if (!$this->isWritable()) { - return false; - } - - // write directly to connection stream if already available - if (self::STATE_HEAD_WRITTEN <= $this->state) { - return $this->connection->write($data); - } - - // otherwise buffer and try to establish connection - $this->pendingWrites .= $data; - if (self::STATE_WRITING_HEAD > $this->state) { - $this->writeHead(); - } - - return false; - } - - public function end($data = null) - { - if (!$this->isWritable()) { - return; - } - - if (null !== $data) { - $this->write($data); - } else if (self::STATE_WRITING_HEAD > $this->state) { - $this->writeHead(); - } - - $this->ended = true; - } - - /** @internal */ - public function handleDrain() - { - $this->emit('drain'); - } - - /** @internal */ - public function handleData($data) - { - $this->buffer .= $data; - - // buffer until double CRLF (or double LF for compatibility with legacy servers) - $eom = \strpos($this->buffer, "\r\n\r\n"); - $eomLegacy = \strpos($this->buffer, "\n\n"); - if ($eom !== false || $eomLegacy !== false) { - try { - if ($eom !== false && ($eomLegacy === false || $eom < $eomLegacy)) { - $response = Response::parseMessage(\substr($this->buffer, 0, $eom + 2)); - $bodyChunk = (string) \substr($this->buffer, $eom + 4); - } else { - $response = Response::parseMessage(\substr($this->buffer, 0, $eomLegacy + 1)); - $bodyChunk = (string) \substr($this->buffer, $eomLegacy + 2); - } - } catch (\InvalidArgumentException $exception) { - $this->closeError($exception); - return; - } - - // response headers successfully received => remove listeners for connection events - $connection = $this->connection; - assert($connection instanceof ConnectionInterface); - $connection->removeListener('drain', array($this, 'handleDrain')); - $connection->removeListener('data', array($this, 'handleData')); - $connection->removeListener('end', array($this, 'handleEnd')); - $connection->removeListener('error', array($this, 'handleError')); - $connection->removeListener('close', array($this, 'close')); - $this->connection = null; - $this->buffer = ''; - - // take control over connection handling and check if we can reuse the connection once response body closes - $that = $this; - $request = $this->request; - $connectionManager = $this->connectionManager; - $successfulEndReceived = false; - $input = $body = new CloseProtectionStream($connection); - $input->on('close', function () use ($connection, $that, $connectionManager, $request, $response, &$successfulEndReceived) { - // only reuse connection after successful response and both request and response allow keep alive - if ($successfulEndReceived && $connection->isReadable() && $that->hasMessageKeepAliveEnabled($response) && $that->hasMessageKeepAliveEnabled($request)) { - $connectionManager->keepAlive($request->getUri(), $connection); - } else { - $connection->close(); - } - - $that->close(); - }); - - // determine length of response body - $length = null; - $code = $response->getStatusCode(); - if ($this->request->getMethod() === 'HEAD' || ($code >= 100 && $code < 200) || $code == Response::STATUS_NO_CONTENT || $code == Response::STATUS_NOT_MODIFIED) { - $length = 0; - } elseif (\strtolower($response->getHeaderLine('Transfer-Encoding')) === 'chunked') { - $body = new ChunkedDecoder($body); - } elseif ($response->hasHeader('Content-Length')) { - $length = (int) $response->getHeaderLine('Content-Length'); - } - $response = $response->withBody($body = new ReadableBodyStream($body, $length)); - $body->on('end', function () use (&$successfulEndReceived) { - $successfulEndReceived = true; - }); - - // emit response with streaming response body (see `Sender`) - $this->emit('response', array($response, $body)); - - // re-emit HTTP response body to trigger body parsing if parts of it are buffered - if ($bodyChunk !== '') { - $input->handleData($bodyChunk); - } elseif ($length === 0) { - $input->handleEnd(); - } - } - } - - /** @internal */ - public function handleEnd() - { - $this->closeError(new \RuntimeException( - "Connection ended before receiving response" - )); - } - - /** @internal */ - public function handleError(\Exception $error) - { - $this->closeError(new \RuntimeException( - "An error occurred in the underlying stream", - 0, - $error - )); - } - - /** @internal */ - public function closeError(\Exception $error) - { - if (self::STATE_END <= $this->state) { - return; - } - $this->emit('error', array($error)); - $this->close(); - } - - public function close() - { - if (self::STATE_END <= $this->state) { - return; - } - - $this->state = self::STATE_END; - $this->pendingWrites = ''; - $this->buffer = ''; - - if ($this->connection instanceof ConnectionInterface) { - $this->connection->close(); - $this->connection = null; - } - - $this->emit('close'); - $this->removeAllListeners(); - } - - /** - * @internal - * @return bool - * @link https://www.rfc-editor.org/rfc/rfc9112#section-9.3 - * @link https://www.rfc-editor.org/rfc/rfc7230#section-6.1 - */ - public function hasMessageKeepAliveEnabled(MessageInterface $message) - { - // @link https://www.rfc-editor.org/rfc/rfc9110#section-7.6.1 - $connectionOptions = \array_map('trim', \explode(',', \strtolower($message->getHeaderLine('Connection')))); - - if (\in_array('close', $connectionOptions, true)) { - return false; - } - - if ($message->getProtocolVersion() === '1.1') { - return true; - } - - if (\in_array('keep-alive', $connectionOptions, true)) { - return true; - } - - return false; - } -} diff --git a/deps/vendor/react/http/src/Io/Clock.php b/deps/vendor/react/http/src/Io/Clock.php deleted file mode 100644 index 92c1cb096..000000000 --- a/deps/vendor/react/http/src/Io/Clock.php +++ /dev/null @@ -1,54 +0,0 @@ -loop = $loop; - } - - /** @return float */ - public function now() - { - if ($this->now === null) { - $this->now = \microtime(true); - - // remember clock for current loop tick only and update on next tick - $now =& $this->now; - $this->loop->futureTick(function () use (&$now) { - assert($now !== null); - $now = null; - }); - } - - return $this->now; - } -} diff --git a/deps/vendor/react/http/src/Io/MultipartParser.php b/deps/vendor/react/http/src/Io/MultipartParser.php index 539107aea..536694fd2 100644 --- a/deps/vendor/react/http/src/Io/MultipartParser.php +++ b/deps/vendor/react/http/src/Io/MultipartParser.php @@ -26,13 +26,6 @@ final class MultipartParser */ private $maxFileSize; - /** - * Based on $maxInputVars and $maxFileUploads - * - * @var int - */ - private $maxMultipartBodyParts; - /** * ini setting "max_input_vars" * @@ -69,11 +62,9 @@ final class MultipartParser */ private $maxFileUploads; - private $multipartBodyPartCount = 0; private $postCount = 0; private $filesCount = 0; private $emptyCount = 0; - private $cursor = 0; /** * @param int|string|null $uploadMaxFilesize @@ -96,8 +87,6 @@ public function __construct($uploadMaxFilesize = null, $maxFileUploads = null) $this->uploadMaxFilesize = IniUtil::iniSizeToBytes($uploadMaxFilesize); $this->maxFileUploads = $maxFileUploads === null ? (\ini_get('file_uploads') === '' ? 0 : (int)\ini_get('max_file_uploads')) : (int)$maxFileUploads; - - $this->maxMultipartBodyParts = $this->maxInputVars + $this->maxFileUploads; } public function parse(ServerRequestInterface $request) @@ -112,8 +101,6 @@ public function parse(ServerRequestInterface $request) $request = $this->request; $this->request = null; - $this->multipartBodyPartCount = 0; - $this->cursor = 0; $this->postCount = 0; $this->filesCount = 0; $this->emptyCount = 0; @@ -127,24 +114,20 @@ private function parseBody($boundary, $buffer) $len = \strlen($boundary); // ignore everything before initial boundary (SHOULD be empty) - $this->cursor = \strpos($buffer, $boundary . "\r\n"); + $start = \strpos($buffer, $boundary . "\r\n"); - while ($this->cursor !== false) { + while ($start !== false) { // search following boundary (preceded by newline) // ignore last if not followed by boundary (SHOULD end with "--") - $this->cursor += $len + 2; - $end = \strpos($buffer, "\r\n" . $boundary, $this->cursor); + $start += $len + 2; + $end = \strpos($buffer, "\r\n" . $boundary, $start); if ($end === false) { break; } // parse one part and continue searching for next - $this->parsePart(\substr($buffer, $this->cursor, $end - $this->cursor)); - $this->cursor = $end; - - if (++$this->multipartBodyPartCount > $this->maxMultipartBodyParts) { - break; - } + $this->parsePart(\substr($buffer, $start, $end - $start)); + $start = $end; } } diff --git a/deps/vendor/react/http/src/Io/RequestHeaderParser.php b/deps/vendor/react/http/src/Io/RequestHeaderParser.php index 8975ce576..e5554c46b 100644 --- a/deps/vendor/react/http/src/Io/RequestHeaderParser.php +++ b/deps/vendor/react/http/src/Io/RequestHeaderParser.php @@ -24,17 +24,6 @@ class RequestHeaderParser extends EventEmitter { private $maxSize = 8192; - /** @var Clock */ - private $clock; - - /** @var array> */ - private $connectionParams = array(); - - public function __construct(Clock $clock) - { - $this->clock = $clock; - } - public function handle(ConnectionInterface $conn) { $buffer = ''; @@ -69,7 +58,8 @@ public function handle(ConnectionInterface $conn) try { $request = $that->parseRequest( (string)\substr($buffer, 0, $endOfHeader + 2), - $conn + $conn->getRemoteAddress(), + $conn->getLocalAddress() ); } catch (Exception $exception) { $buffer = ''; @@ -121,59 +111,171 @@ public function handle(ConnectionInterface $conn) /** * @param string $headers buffer string containing request headers only - * @param ConnectionInterface $connection + * @param ?string $remoteSocketUri + * @param ?string $localSocketUri * @return ServerRequestInterface * @throws \InvalidArgumentException * @internal */ - public function parseRequest($headers, ConnectionInterface $connection) + public function parseRequest($headers, $remoteSocketUri, $localSocketUri) { - // reuse same connection params for all server params for this connection - $cid = \PHP_VERSION_ID < 70200 ? \spl_object_hash($connection) : \spl_object_id($connection); - if (isset($this->connectionParams[$cid])) { - $serverParams = $this->connectionParams[$cid]; - } else { - // assign new server params for new connection - $serverParams = array(); - - // scheme is `http` unless TLS is used - $localSocketUri = $connection->getLocalAddress(); - $localParts = $localSocketUri === null ? array() : \parse_url($localSocketUri); - if (isset($localParts['scheme']) && $localParts['scheme'] === 'tls') { - $serverParams['HTTPS'] = 'on'; - } - - // apply SERVER_ADDR and SERVER_PORT if server address is known - // address should always be known, even for Unix domain sockets (UDS) - // but skip UDS as it doesn't have a concept of host/port. - if ($localSocketUri !== null && isset($localParts['host'], $localParts['port'])) { - $serverParams['SERVER_ADDR'] = $localParts['host']; - $serverParams['SERVER_PORT'] = $localParts['port']; - } - - // apply REMOTE_ADDR and REMOTE_PORT if source address is known - // address should always be known, unless this is over Unix domain sockets (UDS) - $remoteSocketUri = $connection->getRemoteAddress(); - if ($remoteSocketUri !== null) { - $remoteAddress = \parse_url($remoteSocketUri); - $serverParams['REMOTE_ADDR'] = $remoteAddress['host']; - $serverParams['REMOTE_PORT'] = $remoteAddress['port']; - } - - // remember server params for all requests from this connection, reset on connection close - $this->connectionParams[$cid] = $serverParams; - $params =& $this->connectionParams; - $connection->on('close', function () use (&$params, $cid) { - assert(\is_array($params)); - unset($params[$cid]); - }); + // additional, stricter safe-guard for request line + // because request parser doesn't properly cope with invalid ones + $start = array(); + if (!\preg_match('#^(?[^ ]+) (?[^ ]+) HTTP/(?\d\.\d)#m', $headers, $start)) { + throw new \InvalidArgumentException('Unable to parse invalid request-line'); + } + + // only support HTTP/1.1 and HTTP/1.0 requests + if ($start['version'] !== '1.1' && $start['version'] !== '1.0') { + throw new \InvalidArgumentException('Received request with invalid protocol version', Response::STATUS_VERSION_NOT_SUPPORTED); + } + + // match all request header fields into array, thanks to @kelunik for checking the HTTP specs and coming up with this regex + $matches = array(); + $n = \preg_match_all('/^([^()<>@,;:\\\"\/\[\]?={}\x01-\x20\x7F]++):[\x20\x09]*+((?:[\x20\x09]*+[\x21-\x7E\x80-\xFF]++)*+)[\x20\x09]*+[\r]?+\n/m', $headers, $matches, \PREG_SET_ORDER); + + // check number of valid header fields matches number of lines + request line + if (\substr_count($headers, "\n") !== $n + 1) { + throw new \InvalidArgumentException('Unable to parse invalid request header fields'); + } + + // format all header fields into associative array + $host = null; + $fields = array(); + foreach ($matches as $match) { + $fields[$match[1]][] = $match[2]; + + // match `Host` request header + if ($host === null && \strtolower($match[1]) === 'host') { + $host = $match[2]; + } } // create new obj implementing ServerRequestInterface by preserving all // previous properties and restoring original request-target - $serverParams['REQUEST_TIME'] = (int) ($now = $this->clock->now()); - $serverParams['REQUEST_TIME_FLOAT'] = $now; + $serverParams = array( + 'REQUEST_TIME' => \time(), + 'REQUEST_TIME_FLOAT' => \microtime(true) + ); + + // scheme is `http` unless TLS is used + $localParts = $localSocketUri === null ? array() : \parse_url($localSocketUri); + if (isset($localParts['scheme']) && $localParts['scheme'] === 'tls') { + $scheme = 'https://'; + $serverParams['HTTPS'] = 'on'; + } else { + $scheme = 'http://'; + } + + // default host if unset comes from local socket address or defaults to localhost + $hasHost = $host !== null; + if ($host === null) { + $host = isset($localParts['host'], $localParts['port']) ? $localParts['host'] . ':' . $localParts['port'] : '127.0.0.1'; + } + + if ($start['method'] === 'OPTIONS' && $start['target'] === '*') { + // support asterisk-form for `OPTIONS *` request line only + $uri = $scheme . $host; + } elseif ($start['method'] === 'CONNECT') { + $parts = \parse_url('tcp://' . $start['target']); + + // check this is a valid authority-form request-target (host:port) + if (!isset($parts['scheme'], $parts['host'], $parts['port']) || \count($parts) !== 3) { + throw new \InvalidArgumentException('CONNECT method MUST use authority-form request target'); + } + $uri = $scheme . $start['target']; + } else { + // support absolute-form or origin-form for proxy requests + if ($start['target'][0] === '/') { + $uri = $scheme . $host . $start['target']; + } else { + // ensure absolute-form request-target contains a valid URI + $parts = \parse_url($start['target']); + + // make sure value contains valid host component (IP or hostname), but no fragment + if (!isset($parts['scheme'], $parts['host']) || $parts['scheme'] !== 'http' || isset($parts['fragment'])) { + throw new \InvalidArgumentException('Invalid absolute-form request-target'); + } + + $uri = $start['target']; + } + } + + // apply REMOTE_ADDR and REMOTE_PORT if source address is known + // address should always be known, unless this is over Unix domain sockets (UDS) + if ($remoteSocketUri !== null) { + $remoteAddress = \parse_url($remoteSocketUri); + $serverParams['REMOTE_ADDR'] = $remoteAddress['host']; + $serverParams['REMOTE_PORT'] = $remoteAddress['port']; + } + + // apply SERVER_ADDR and SERVER_PORT if server address is known + // address should always be known, even for Unix domain sockets (UDS) + // but skip UDS as it doesn't have a concept of host/port. + if ($localSocketUri !== null && isset($localParts['host'], $localParts['port'])) { + $serverParams['SERVER_ADDR'] = $localParts['host']; + $serverParams['SERVER_PORT'] = $localParts['port']; + } + + $request = new ServerRequest( + $start['method'], + $uri, + $fields, + '', + $start['version'], + $serverParams + ); + + // only assign request target if it is not in origin-form (happy path for most normal requests) + if ($start['target'][0] !== '/') { + $request = $request->withRequestTarget($start['target']); + } + + if ($hasHost) { + // Optional Host request header value MUST be valid (host and optional port) + $parts = \parse_url('http://' . $request->getHeaderLine('Host')); + + // make sure value contains valid host component (IP or hostname) + if (!$parts || !isset($parts['scheme'], $parts['host'])) { + $parts = false; + } + + // make sure value does not contain any other URI component + if (\is_array($parts)) { + unset($parts['scheme'], $parts['host'], $parts['port']); + } + if ($parts === false || $parts) { + throw new \InvalidArgumentException('Invalid Host header value'); + } + } elseif (!$hasHost && $start['version'] === '1.1' && $start['method'] !== 'CONNECT') { + // require Host request header for HTTP/1.1 (except for CONNECT method) + throw new \InvalidArgumentException('Missing required Host request header'); + } elseif (!$hasHost) { + // remove default Host request header for HTTP/1.0 when not explicitly given + $request = $request->withoutHeader('Host'); + } + + // ensure message boundaries are valid according to Content-Length and Transfer-Encoding request headers + if ($request->hasHeader('Transfer-Encoding')) { + if (\strtolower($request->getHeaderLine('Transfer-Encoding')) !== 'chunked') { + throw new \InvalidArgumentException('Only chunked-encoding is allowed for Transfer-Encoding', Response::STATUS_NOT_IMPLEMENTED); + } + + // Transfer-Encoding: chunked and Content-Length header MUST NOT be used at the same time + // as per https://tools.ietf.org/html/rfc7230#section-3.3.3 + if ($request->hasHeader('Content-Length')) { + throw new \InvalidArgumentException('Using both `Transfer-Encoding: chunked` and `Content-Length` is not allowed', Response::STATUS_BAD_REQUEST); + } + } elseif ($request->hasHeader('Content-Length')) { + $string = $request->getHeaderLine('Content-Length'); + + if ((string)(int)$string !== $string) { + // Content-Length value is not an integer or not a single integer + throw new \InvalidArgumentException('The value of `Content-Length` is not valid', Response::STATUS_BAD_REQUEST); + } + } - return ServerRequest::parseMessage($headers, $serverParams); + return $request; } } diff --git a/deps/vendor/react/http/src/Io/Sender.php b/deps/vendor/react/http/src/Io/Sender.php index 1d563891e..2f04c7976 100644 --- a/deps/vendor/react/http/src/Io/Sender.php +++ b/deps/vendor/react/http/src/Io/Sender.php @@ -6,9 +6,9 @@ use Psr\Http\Message\ResponseInterface; use React\EventLoop\LoopInterface; use React\Http\Client\Client as HttpClient; +use React\Http\Message\Response; use React\Promise\PromiseInterface; use React\Promise\Deferred; -use React\Socket\Connector; use React\Socket\ConnectorInterface; use React\Stream\ReadableStreamInterface; @@ -50,11 +50,7 @@ class Sender */ public static function createFromLoop(LoopInterface $loop, ConnectorInterface $connector = null) { - if ($connector === null) { - $connector = new Connector(array(), $loop); - } - - return new self(new HttpClient(new ClientConnectionManager($connector, $loop))); + return new self(new HttpClient($loop, $connector)); } private $http; @@ -78,9 +74,6 @@ public function __construct(HttpClient $http) */ public function send(RequestInterface $request) { - // support HTTP/1.1 and HTTP/1.0 only, ensured by `Browser` already - assert(\in_array($request->getProtocolVersion(), array('1.0', '1.1'), true)); - $body = $request->getBody(); $size = $body->getSize(); @@ -90,7 +83,7 @@ public function send(RequestInterface $request) } elseif ($size === 0 && \in_array($request->getMethod(), array('POST', 'PUT', 'PATCH'))) { // only assign a "Content-Length: 0" request header if the body is expected for certain methods $request = $request->withHeader('Content-Length', '0'); - } elseif ($body instanceof ReadableStreamInterface && $size !== 0 && $body->isReadable() && !$request->hasHeader('Content-Length')) { + } elseif ($body instanceof ReadableStreamInterface && $body->isReadable() && !$request->hasHeader('Content-Length')) { // use "Transfer-Encoding: chunked" when this is a streaming body and body size is unknown $request = $request->withHeader('Transfer-Encoding', 'chunked'); } else { @@ -98,12 +91,12 @@ public function send(RequestInterface $request) $size = 0; } - // automatically add `Authorization: Basic …` request header if URL includes `user:pass@host` - if ($request->getUri()->getUserInfo() !== '' && !$request->hasHeader('Authorization')) { - $request = $request->withHeader('Authorization', 'Basic ' . \base64_encode($request->getUri()->getUserInfo())); + $headers = array(); + foreach ($request->getHeaders() as $name => $values) { + $headers[$name] = implode(', ', $values); } - $requestStream = $this->http->request($request); + $requestStream = $this->http->request($request->getMethod(), (string)$request->getUri(), $headers, $request->getProtocolVersion()); $deferred = new Deferred(function ($_, $reject) use ($requestStream) { // close request stream if request is cancelled @@ -115,8 +108,18 @@ public function send(RequestInterface $request) $deferred->reject($error); }); - $requestStream->on('response', function (ResponseInterface $response) use ($deferred, $request) { - $deferred->resolve($response); + $requestStream->on('response', function (ResponseInterface $response, ReadableStreamInterface $body) use ($deferred, $request) { + $length = null; + $code = $response->getStatusCode(); + if ($request->getMethod() === 'HEAD' || ($code >= 100 && $code < 200) || $code == Response::STATUS_NO_CONTENT || $code == Response::STATUS_NOT_MODIFIED) { + $length = 0; + } elseif (\strtolower($response->getHeaderLine('Transfer-Encoding')) === 'chunked') { + $body = new ChunkedDecoder($body); + } elseif ($response->hasHeader('Content-Length')) { + $length = (int) $response->getHeaderLine('Content-Length'); + } + + $deferred->resolve($response->withBody(new ReadableBodyStream($body, $length))); }); if ($body instanceof ReadableStreamInterface) { diff --git a/deps/vendor/react/http/src/Io/StreamingServer.php b/deps/vendor/react/http/src/Io/StreamingServer.php index 143edaa88..7818f0bd9 100644 --- a/deps/vendor/react/http/src/Io/StreamingServer.php +++ b/deps/vendor/react/http/src/Io/StreamingServer.php @@ -9,6 +9,7 @@ use React\Http\Message\Response; use React\Http\Message\ServerRequest; use React\Promise; +use React\Promise\CancellablePromiseInterface; use React\Promise\PromiseInterface; use React\Socket\ConnectionInterface; use React\Socket\ServerInterface; @@ -83,9 +84,7 @@ final class StreamingServer extends EventEmitter { private $callback; private $parser; - - /** @var Clock */ - private $clock; + private $loop; /** * Creates an HTTP server that invokes the given callback for each incoming HTTP request @@ -105,9 +104,10 @@ public function __construct(LoopInterface $loop, $requestHandler) throw new \InvalidArgumentException('Invalid request handler given'); } + $this->loop = $loop; + $this->callback = $requestHandler; - $this->clock = new Clock($loop); - $this->parser = new RequestHeaderParser($this->clock); + $this->parser = new RequestHeaderParser(); $that = $this; $this->parser->on('headers', function (ServerRequestInterface $request, ConnectionInterface $conn) use ($that) { @@ -157,17 +157,10 @@ public function handleRequest(ConnectionInterface $conn, ServerRequestInterface } // cancel pending promise once connection closes - $connectionOnCloseResponseCancelerHandler = function () {}; - if ($response instanceof PromiseInterface && \method_exists($response, 'cancel')) { - $connectionOnCloseResponseCanceler = function () use ($response) { + if ($response instanceof CancellablePromiseInterface) { + $conn->on('close', function () use ($response) { $response->cancel(); - }; - $connectionOnCloseResponseCancelerHandler = function () use ($connectionOnCloseResponseCanceler, $conn) { - if ($connectionOnCloseResponseCanceler !== null) { - $conn->removeListener('close', $connectionOnCloseResponseCanceler); - } - }; - $conn->on('close', $connectionOnCloseResponseCanceler); + }); } // happy path: response returned, handle and return immediately @@ -208,7 +201,7 @@ function ($error) use ($that, $conn, $request) { $that->emit('error', array($exception)); return $that->writeError($conn, Response::STATUS_INTERNAL_SERVER_ERROR, $request); } - )->then($connectionOnCloseResponseCancelerHandler, $connectionOnCloseResponseCancelerHandler); + ); } /** @internal */ @@ -262,7 +255,7 @@ public function handleResponse(ConnectionInterface $connection, ServerRequestInt // assign default "Date" header from current time automatically if (!$response->hasHeader('Date')) { // IMF-fixdate = day-name "," SP date1 SP time-of-day SP GMT - $response = $response->withHeader('Date', gmdate('D, d M Y H:i:s', (int) $this->clock->now()) . ' GMT'); + $response = $response->withHeader('Date', gmdate('D, d M Y H:i:s') . ' GMT'); } elseif ($response->getHeaderLine('Date') === ''){ $response = $response->withoutHeader('Date'); } @@ -272,8 +265,6 @@ public function handleResponse(ConnectionInterface $connection, ServerRequestInt if (($method === 'CONNECT' && $code >= 200 && $code < 300) || ($code >= 100 && $code < 200) || $code === Response::STATUS_NO_CONTENT) { // 2xx response to CONNECT and 1xx and 204 MUST NOT include Content-Length or Transfer-Encoding header $response = $response->withoutHeader('Content-Length'); - } elseif ($method === 'HEAD' && $response->hasHeader('Content-Length')) { - // HEAD Request: preserve explicit Content-Length } elseif ($code === Response::STATUS_NOT_MODIFIED && ($response->hasHeader('Content-Length') || $body->getSize() === 0)) { // 304 Not Modified: preserve explicit Content-Length and preserve missing header if body is empty } elseif ($body->getSize() !== null) { @@ -333,26 +324,13 @@ public function handleResponse(ConnectionInterface $connection, ServerRequestInt } // build HTTP response header by appending status line and header fields - $expected = 0; $headers = "HTTP/" . $version . " " . $code . " " . $response->getReasonPhrase() . "\r\n"; foreach ($response->getHeaders() as $name => $values) { - if (\strpos($name, ':') !== false) { - $expected = -1; - break; - } foreach ($values as $value) { $headers .= $name . ": " . $value . "\r\n"; - ++$expected; } } - /** @var array $m legacy PHP 5.3 only */ - if ($code < 100 || $code > 999 || \substr_count($headers, "\n") !== ($expected + 1) || (\PHP_VERSION_ID >= 50400 ? \preg_match_all(AbstractMessage::REGEX_HEADERS, $headers) : \preg_match_all(AbstractMessage::REGEX_HEADERS, $headers, $m)) !== $expected) { - $this->emit('error', array(new \InvalidArgumentException('Unable to send response with invalid response headers'))); - $this->writeError($connection, Response::STATUS_INTERNAL_SERVER_ERROR, $request); - return; - } - // response to HEAD and 1xx, 204 and 304 responses MUST NOT include a body // exclude status 101 (Switching Protocols) here for Upgrade request handling above if ($method === 'HEAD' || ($code >= 100 && $code < 200 && $code !== Response::STATUS_SWITCHING_PROTOCOLS) || $code === Response::STATUS_NO_CONTENT || $code === Response::STATUS_NOT_MODIFIED) { diff --git a/deps/vendor/react/http/src/Io/Transaction.php b/deps/vendor/react/http/src/Io/Transaction.php index 64738f565..7bf7008fd 100644 --- a/deps/vendor/react/http/src/Io/Transaction.php +++ b/deps/vendor/react/http/src/Io/Transaction.php @@ -5,12 +5,11 @@ use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\UriInterface; +use RingCentral\Psr7\Request; +use RingCentral\Psr7\Uri; use React\EventLoop\LoopInterface; -use React\Http\Message\Response; use React\Http\Message\ResponseException; -use React\Http\Message\Uri; use React\Promise\Deferred; -use React\Promise\Promise; use React\Promise\PromiseInterface; use React\Stream\ReadableStreamInterface; @@ -68,31 +67,32 @@ public function withOptions(array $options) public function send(RequestInterface $request) { - $state = new ClientRequestState(); - $deferred = new Deferred(function () use ($state) { - if ($state->pending !== null) { - $state->pending->cancel(); - $state->pending = null; + $deferred = new Deferred(function () use (&$deferred) { + if (isset($deferred->pending)) { + $deferred->pending->cancel(); + unset($deferred->pending); } }); + $deferred->numRequests = 0; + // use timeout from options or default to PHP's default_socket_timeout (60) $timeout = (float)($this->timeout !== null ? $this->timeout : ini_get("default_socket_timeout")); $loop = $this->loop; - $this->next($request, $deferred, $state)->then( - function (ResponseInterface $response) use ($state, $deferred, $loop, &$timeout) { - if ($state->timeout !== null) { - $loop->cancelTimer($state->timeout); - $state->timeout = null; + $this->next($request, $deferred)->then( + function (ResponseInterface $response) use ($deferred, $loop, &$timeout) { + if (isset($deferred->timeout)) { + $loop->cancelTimer($deferred->timeout); + unset($deferred->timeout); } $timeout = -1; $deferred->resolve($response); }, - function ($e) use ($state, $deferred, $loop, &$timeout) { - if ($state->timeout !== null) { - $loop->cancelTimer($state->timeout); - $state->timeout = null; + function ($e) use ($deferred, $loop, &$timeout) { + if (isset($deferred->timeout)) { + $loop->cancelTimer($deferred->timeout); + unset($deferred->timeout); } $timeout = -1; $deferred->reject($e); @@ -106,13 +106,13 @@ function ($e) use ($state, $deferred, $loop, &$timeout) { $body = $request->getBody(); if ($body instanceof ReadableStreamInterface && $body->isReadable()) { $that = $this; - $body->on('close', function () use ($that, $deferred, $state, &$timeout) { + $body->on('close', function () use ($that, $deferred, &$timeout) { if ($timeout >= 0) { - $that->applyTimeout($deferred, $state, $timeout); + $that->applyTimeout($deferred, $timeout); } }); } else { - $this->applyTimeout($deferred, $state, $timeout); + $this->applyTimeout($deferred, $timeout); } return $deferred->promise(); @@ -120,128 +120,111 @@ function ($e) use ($state, $deferred, $loop, &$timeout) { /** * @internal - * @param number $timeout + * @param Deferred $deferred + * @param number $timeout * @return void */ - public function applyTimeout(Deferred $deferred, ClientRequestState $state, $timeout) + public function applyTimeout(Deferred $deferred, $timeout) { - $state->timeout = $this->loop->addTimer($timeout, function () use ($timeout, $deferred, $state) { + $deferred->timeout = $this->loop->addTimer($timeout, function () use ($timeout, $deferred) { $deferred->reject(new \RuntimeException( 'Request timed out after ' . $timeout . ' seconds' )); - if ($state->pending !== null) { - $state->pending->cancel(); - $state->pending = null; + if (isset($deferred->pending)) { + $deferred->pending->cancel(); + unset($deferred->pending); } }); } - private function next(RequestInterface $request, Deferred $deferred, ClientRequestState $state) + private function next(RequestInterface $request, Deferred $deferred) { $this->progress('request', array($request)); $that = $this; - ++$state->numRequests; + ++$deferred->numRequests; $promise = $this->sender->send($request); if (!$this->streaming) { - $promise = $promise->then(function ($response) use ($deferred, $state, $that) { - return $that->bufferResponse($response, $deferred, $state); + $promise = $promise->then(function ($response) use ($deferred, $that) { + return $that->bufferResponse($response, $deferred); }); } - $state->pending = $promise; + $deferred->pending = $promise; return $promise->then( - function (ResponseInterface $response) use ($request, $that, $deferred, $state) { - return $that->onResponse($response, $request, $deferred, $state); + function (ResponseInterface $response) use ($request, $that, $deferred) { + return $that->onResponse($response, $request, $deferred); } ); } /** * @internal + * @param ResponseInterface $response * @return PromiseInterface Promise */ - public function bufferResponse(ResponseInterface $response, Deferred $deferred, ClientRequestState $state) + public function bufferResponse(ResponseInterface $response, $deferred) { - $body = $response->getBody(); - $size = $body->getSize(); + $stream = $response->getBody(); + $size = $stream->getSize(); if ($size !== null && $size > $this->maximumSize) { - $body->close(); + $stream->close(); return \React\Promise\reject(new \OverflowException( 'Response body size of ' . $size . ' bytes exceeds maximum of ' . $this->maximumSize . ' bytes', - \defined('SOCKET_EMSGSIZE') ? \SOCKET_EMSGSIZE : 90 + \defined('SOCKET_EMSGSIZE') ? \SOCKET_EMSGSIZE : 0 )); } // body is not streaming => already buffered - if (!$body instanceof ReadableStreamInterface) { + if (!$stream instanceof ReadableStreamInterface) { return \React\Promise\resolve($response); } - /** @var ?\Closure $closer */ - $closer = null; + // buffer stream and resolve with buffered body $maximumSize = $this->maximumSize; + $promise = \React\Promise\Stream\buffer($stream, $maximumSize)->then( + function ($body) use ($response) { + return $response->withBody(new BufferedBody($body)); + }, + function ($e) use ($stream, $maximumSize) { + // try to close stream if buffering fails (or is cancelled) + $stream->close(); - return $state->pending = new Promise(function ($resolve, $reject) use ($body, $maximumSize, $response, &$closer) { - // resolve with current buffer when stream closes successfully - $buffer = ''; - $body->on('close', $closer = function () use (&$buffer, $response, $maximumSize, $resolve, $reject) { - $resolve($response->withBody(new BufferedBody($buffer))); - }); - - // buffer response body data in memory - $body->on('data', function ($data) use (&$buffer, $maximumSize, $body, $closer, $reject) { - $buffer .= $data; - - // close stream and reject promise if limit is exceeded - if (isset($buffer[$maximumSize])) { - $buffer = ''; - assert($closer instanceof \Closure); - $body->removeListener('close', $closer); - $body->close(); - - $reject(new \OverflowException( + if ($e instanceof \OverflowException) { + $e = new \OverflowException( 'Response body size exceeds maximum of ' . $maximumSize . ' bytes', - \defined('SOCKET_EMSGSIZE') ? \SOCKET_EMSGSIZE : 90 - )); + \defined('SOCKET_EMSGSIZE') ? \SOCKET_EMSGSIZE : 0 + ); } - }); - // reject buffering if body emits error - $body->on('error', function (\Exception $e) use ($reject) { - $reject(new \RuntimeException( - 'Error while buffering response body: ' . $e->getMessage(), - $e->getCode(), - $e - )); - }); - }, function () use ($body, &$closer) { - // cancelled buffering: remove close handler to avoid resolving, then close and reject - assert($closer instanceof \Closure); - $body->removeListener('close', $closer); - $body->close(); + throw $e; + } + ); - throw new \RuntimeException('Cancelled buffering response body'); - }); + $deferred->pending = $promise; + + return $promise; } /** * @internal + * @param ResponseInterface $response + * @param RequestInterface $request * @throws ResponseException * @return ResponseInterface|PromiseInterface */ - public function onResponse(ResponseInterface $response, RequestInterface $request, Deferred $deferred, ClientRequestState $state) + public function onResponse(ResponseInterface $response, RequestInterface $request, $deferred) { $this->progress('response', array($response, $request)); // follow 3xx (Redirection) response status codes if Location header is present and not explicitly disabled // @link https://tools.ietf.org/html/rfc7231#section-6.4 if ($this->followRedirects && ($response->getStatusCode() >= 300 && $response->getStatusCode() < 400) && $response->hasHeader('Location')) { - return $this->onResponseRedirect($response, $request, $deferred, $state); + return $this->onResponseRedirect($response, $request, $deferred); } // only status codes 200-399 are considered to be valid, reject otherwise @@ -256,56 +239,46 @@ public function onResponse(ResponseInterface $response, RequestInterface $reques /** * @param ResponseInterface $response * @param RequestInterface $request - * @param Deferred $deferred - * @param ClientRequestState $state * @return PromiseInterface * @throws \RuntimeException */ - private function onResponseRedirect(ResponseInterface $response, RequestInterface $request, Deferred $deferred, ClientRequestState $state) + private function onResponseRedirect(ResponseInterface $response, RequestInterface $request, Deferred $deferred) { // resolve location relative to last request URI - $location = Uri::resolve($request->getUri(), new Uri($response->getHeaderLine('Location'))); + $location = Uri::resolve($request->getUri(), $response->getHeaderLine('Location')); - $request = $this->makeRedirectRequest($request, $location, $response->getStatusCode()); + $request = $this->makeRedirectRequest($request, $location); $this->progress('redirect', array($request)); - if ($state->numRequests >= $this->maxRedirects) { + if ($deferred->numRequests >= $this->maxRedirects) { throw new \RuntimeException('Maximum number of redirects (' . $this->maxRedirects . ') exceeded'); } - return $this->next($request, $deferred, $state); + return $this->next($request, $deferred); } /** * @param RequestInterface $request * @param UriInterface $location - * @param int $statusCode * @return RequestInterface - * @throws \RuntimeException */ - private function makeRedirectRequest(RequestInterface $request, UriInterface $location, $statusCode) + private function makeRedirectRequest(RequestInterface $request, UriInterface $location) { - // Remove authorization if changing hostnames (but not if just changing ports or protocols). $originalHost = $request->getUri()->getHost(); + $request = $request + ->withoutHeader('Host') + ->withoutHeader('Content-Type') + ->withoutHeader('Content-Length'); + + // Remove authorization if changing hostnames (but not if just changing ports or protocols). if ($location->getHost() !== $originalHost) { $request = $request->withoutHeader('Authorization'); } - $request = $request->withoutHeader('Host')->withUri($location); - - if ($statusCode === Response::STATUS_TEMPORARY_REDIRECT || $statusCode === Response::STATUS_PERMANENT_REDIRECT) { - if ($request->getBody() instanceof ReadableStreamInterface) { - throw new \RuntimeException('Unable to redirect request with streaming body'); - } - } else { - $request = $request - ->withMethod($request->getMethod() === 'HEAD' ? 'HEAD' : 'GET') - ->withoutHeader('Content-Type') - ->withoutHeader('Content-Length') - ->withBody(new BufferedBody('')); - } + // naïve approach.. + $method = ($request->getMethod() === 'HEAD') ? 'HEAD' : 'GET'; - return $request; + return new Request($method, $location, $request->getHeaders()); } private function progress($name, array $args = array()) diff --git a/deps/vendor/react/http/src/Message/Request.php b/deps/vendor/react/http/src/Message/Request.php deleted file mode 100644 index 3de8c1b3e..000000000 --- a/deps/vendor/react/http/src/Message/Request.php +++ /dev/null @@ -1,57 +0,0 @@ - Internally, this implementation builds on top of a base class which is - * considered an implementation detail that may change in the future. - * - * @see RequestInterface - */ -final class Request extends AbstractRequest implements RequestInterface -{ - /** - * @param string $method HTTP method for the request. - * @param string|UriInterface $url URL for the request. - * @param array $headers Headers for the message. - * @param string|ReadableStreamInterface|StreamInterface $body Message body. - * @param string $version HTTP protocol version. - * @throws \InvalidArgumentException for an invalid URL or body - */ - public function __construct( - $method, - $url, - array $headers = array(), - $body = '', - $version = '1.1' - ) { - if (\is_string($body)) { - $body = new BufferedBody($body); - } elseif ($body instanceof ReadableStreamInterface && !$body instanceof StreamInterface) { - $body = new ReadableBodyStream($body); - } elseif (!$body instanceof StreamInterface) { - throw new \InvalidArgumentException('Invalid request body given'); - } - - parent::__construct($method, $url, $headers, $body, $version); - } -} diff --git a/deps/vendor/react/http/src/Message/Response.php b/deps/vendor/react/http/src/Message/Response.php index fa6366ed1..edd6245bd 100644 --- a/deps/vendor/react/http/src/Message/Response.php +++ b/deps/vendor/react/http/src/Message/Response.php @@ -3,12 +3,11 @@ namespace React\Http\Message; use Fig\Http\Message\StatusCodeInterface; -use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\StreamInterface; -use React\Http\Io\AbstractMessage; use React\Http\Io\BufferedBody; use React\Http\Io\HttpBodyStream; use React\Stream\ReadableStreamInterface; +use RingCentral\Psr7\Response as Psr7Response; /** * Represents an outgoing server response message. @@ -35,12 +34,13 @@ * `404 Not Found` status codes can used as `Response::STATUS_OK` and * `Response::STATUS_NOT_FOUND` respectively. * - * > Internally, this implementation builds on top a base class which is + * > Internally, this implementation builds on top of an existing incoming + * response message and only adds required streaming support. This base class is * considered an implementation detail that may change in the future. * * @see \Psr\Http\Message\ResponseInterface */ -final class Response extends AbstractMessage implements ResponseInterface, StatusCodeInterface +final class Response extends Psr7Response implements StatusCodeInterface { /** * Create an HTML response @@ -257,41 +257,6 @@ public static function xml($xml) return new self(self::STATUS_OK, array('Content-Type' => 'application/xml'), $xml); } - /** - * @var bool - * @see self::$phrasesMap - */ - private static $phrasesInitialized = false; - - /** - * Map of standard HTTP status codes to standard reason phrases. - * - * This map will be fully populated with all standard reason phrases on - * first access. By default, it only contains a subset of HTTP status codes - * that have a custom mapping to reason phrases (such as those with dashes - * and all caps words). See `self::STATUS_*` for all possible status code - * constants. - * - * @var array - * @see self::STATUS_* - * @see self::getReasonPhraseForStatusCode() - */ - private static $phrasesMap = array( - 200 => 'OK', - 203 => 'Non-Authoritative Information', - 207 => 'Multi-Status', - 226 => 'IM Used', - 414 => 'URI Too Large', - 418 => 'I\'m a teapot', - 505 => 'HTTP Version Not Supported' - ); - - /** @var int */ - private $statusCode; - - /** @var string */ - private $reasonPhrase; - /** * @param int $status HTTP status code (e.g. 200/404), see `self::STATUS_*` constants * @param array $headers additional response headers @@ -315,100 +280,12 @@ public function __construct( throw new \InvalidArgumentException('Invalid response body given'); } - parent::__construct($version, $headers, $body); - - $this->statusCode = (int) $status; - $this->reasonPhrase = ($reason !== '' && $reason !== null) ? (string) $reason : self::getReasonPhraseForStatusCode($status); - } - - public function getStatusCode() - { - return $this->statusCode; - } - - public function withStatus($code, $reasonPhrase = '') - { - if ((string) $reasonPhrase === '') { - $reasonPhrase = self::getReasonPhraseForStatusCode($code); - } - - if ($this->statusCode === (int) $code && $this->reasonPhrase === (string) $reasonPhrase) { - return $this; - } - - $response = clone $this; - $response->statusCode = (int) $code; - $response->reasonPhrase = (string) $reasonPhrase; - - return $response; - } - - public function getReasonPhrase() - { - return $this->reasonPhrase; - } - - /** - * @param int $code - * @return string default reason phrase for given status code or empty string if unknown - */ - private static function getReasonPhraseForStatusCode($code) - { - if (!self::$phrasesInitialized) { - self::$phrasesInitialized = true; - - // map all `self::STATUS_` constants from status code to reason phrase - // e.g. `self::STATUS_NOT_FOUND = 404` will be mapped to `404 Not Found` - $ref = new \ReflectionClass(__CLASS__); - foreach ($ref->getConstants() as $name => $value) { - if (!isset(self::$phrasesMap[$value]) && \strpos($name, 'STATUS_') === 0) { - self::$phrasesMap[$value] = \ucwords(\strtolower(\str_replace('_', ' ', \substr($name, 7)))); - } - } - } - - return isset(self::$phrasesMap[$code]) ? self::$phrasesMap[$code] : ''; - } - - /** - * [Internal] Parse incoming HTTP protocol message - * - * @internal - * @param string $message - * @return self - * @throws \InvalidArgumentException if given $message is not a valid HTTP response message - */ - public static function parseMessage($message) - { - $start = array(); - if (!\preg_match('#^HTTP/(?\d\.\d) (?\d{3})(?: (?[^\r\n]*+))?[\r]?+\n#m', $message, $start)) { - throw new \InvalidArgumentException('Unable to parse invalid status-line'); - } - - // only support HTTP/1.1 and HTTP/1.0 requests - if ($start['version'] !== '1.1' && $start['version'] !== '1.0') { - throw new \InvalidArgumentException('Received response with invalid protocol version'); - } - - // check number of valid header fields matches number of lines + status line - $matches = array(); - $n = \preg_match_all(self::REGEX_HEADERS, $message, $matches, \PREG_SET_ORDER); - if (\substr_count($message, "\n") !== $n + 1) { - throw new \InvalidArgumentException('Unable to parse invalid response header fields'); - } - - // format all header fields into associative array - $headers = array(); - foreach ($matches as $match) { - $headers[$match[1]][] = $match[2]; - } - - return new self( - (int) $start['status'], + parent::__construct( + $status, $headers, - '', - $start['version'], - isset($start['reason']) ? $start['reason'] : '' + $body, + $version, + $reason ); } } diff --git a/deps/vendor/react/http/src/Message/ServerRequest.php b/deps/vendor/react/http/src/Message/ServerRequest.php index 32a0f62f6..f446f24e8 100644 --- a/deps/vendor/react/http/src/Message/ServerRequest.php +++ b/deps/vendor/react/http/src/Message/ServerRequest.php @@ -5,10 +5,10 @@ use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\StreamInterface; use Psr\Http\Message\UriInterface; -use React\Http\Io\AbstractRequest; use React\Http\Io\BufferedBody; use React\Http\Io\HttpBodyStream; use React\Stream\ReadableStreamInterface; +use RingCentral\Psr7\Request; /** * Respresents an incoming server request message. @@ -24,12 +24,13 @@ * Likewise, you can also use this class in test cases to test how your web * application reacts to certain HTTP requests. * - * > Internally, this implementation builds on top of a base class which is + * > Internally, this implementation builds on top of an existing outgoing + * request message and only adds required server methods. This base class is * considered an implementation detail that may change in the future. * * @see ServerRequestInterface */ -final class ServerRequest extends AbstractRequest implements ServerRequestInterface +final class ServerRequest extends Request implements ServerRequestInterface { private $attributes = array(); @@ -56,22 +57,26 @@ public function __construct( $version = '1.1', $serverParams = array() ) { + $stream = null; if (\is_string($body)) { $body = new BufferedBody($body); } elseif ($body instanceof ReadableStreamInterface && !$body instanceof StreamInterface) { - $temp = new self($method, '', $headers); - $size = (int) $temp->getHeaderLine('Content-Length'); - if (\strtolower($temp->getHeaderLine('Transfer-Encoding')) === 'chunked') { - $size = null; - } - $body = new HttpBodyStream($body, $size); + $stream = $body; + $body = null; } elseif (!$body instanceof StreamInterface) { throw new \InvalidArgumentException('Invalid server request body given'); } + $this->serverParams = $serverParams; parent::__construct($method, $url, $headers, $body, $version); - $this->serverParams = $serverParams; + if ($stream !== null) { + $size = (int) $this->getHeaderLine('Content-Length'); + if (\strtolower($this->getHeaderLine('Transfer-Encoding')) === 'chunked') { + $size = null; + } + $this->stream = new HttpBodyStream($stream, $size); + } $query = $this->getUri()->getQuery(); if ($query !== '') { @@ -181,7 +186,7 @@ private function parseCookie($cookie) $nameValuePair = \explode('=', $pair, 2); if (\count($nameValuePair) === 2) { - $key = $nameValuePair[0]; + $key = \urldecode($nameValuePair[0]); $value = \urldecode($nameValuePair[1]); $result[$key] = $value; } @@ -189,143 +194,4 @@ private function parseCookie($cookie) return $result; } - - /** - * [Internal] Parse incoming HTTP protocol message - * - * @internal - * @param string $message - * @param array $serverParams - * @return self - * @throws \InvalidArgumentException if given $message is not a valid HTTP request message - */ - public static function parseMessage($message, array $serverParams) - { - // parse request line like "GET /path HTTP/1.1" - $start = array(); - if (!\preg_match('#^(?[^ ]+) (?[^ ]+) HTTP/(?\d\.\d)#m', $message, $start)) { - throw new \InvalidArgumentException('Unable to parse invalid request-line'); - } - - // only support HTTP/1.1 and HTTP/1.0 requests - if ($start['version'] !== '1.1' && $start['version'] !== '1.0') { - throw new \InvalidArgumentException('Received request with invalid protocol version', Response::STATUS_VERSION_NOT_SUPPORTED); - } - - // check number of valid header fields matches number of lines + request line - $matches = array(); - $n = \preg_match_all(self::REGEX_HEADERS, $message, $matches, \PREG_SET_ORDER); - if (\substr_count($message, "\n") !== $n + 1) { - throw new \InvalidArgumentException('Unable to parse invalid request header fields'); - } - - // format all header fields into associative array - $host = null; - $headers = array(); - foreach ($matches as $match) { - $headers[$match[1]][] = $match[2]; - - // match `Host` request header - if ($host === null && \strtolower($match[1]) === 'host') { - $host = $match[2]; - } - } - - // scheme is `http` unless TLS is used - $scheme = isset($serverParams['HTTPS']) ? 'https://' : 'http://'; - - // default host if unset comes from local socket address or defaults to localhost - $hasHost = $host !== null; - if ($host === null) { - $host = isset($serverParams['SERVER_ADDR'], $serverParams['SERVER_PORT']) ? $serverParams['SERVER_ADDR'] . ':' . $serverParams['SERVER_PORT'] : '127.0.0.1'; - } - - if ($start['method'] === 'OPTIONS' && $start['target'] === '*') { - // support asterisk-form for `OPTIONS *` request line only - $uri = $scheme . $host; - } elseif ($start['method'] === 'CONNECT') { - $parts = \parse_url('tcp://' . $start['target']); - - // check this is a valid authority-form request-target (host:port) - if (!isset($parts['scheme'], $parts['host'], $parts['port']) || \count($parts) !== 3) { - throw new \InvalidArgumentException('CONNECT method MUST use authority-form request target'); - } - $uri = $scheme . $start['target']; - } else { - // support absolute-form or origin-form for proxy requests - if ($start['target'][0] === '/') { - $uri = $scheme . $host . $start['target']; - } else { - // ensure absolute-form request-target contains a valid URI - $parts = \parse_url($start['target']); - - // make sure value contains valid host component (IP or hostname), but no fragment - if (!isset($parts['scheme'], $parts['host']) || $parts['scheme'] !== 'http' || isset($parts['fragment'])) { - throw new \InvalidArgumentException('Invalid absolute-form request-target'); - } - - $uri = $start['target']; - } - } - - $request = new self( - $start['method'], - $uri, - $headers, - '', - $start['version'], - $serverParams - ); - - // only assign request target if it is not in origin-form (happy path for most normal requests) - if ($start['target'][0] !== '/') { - $request = $request->withRequestTarget($start['target']); - } - - if ($hasHost) { - // Optional Host request header value MUST be valid (host and optional port) - $parts = \parse_url('http://' . $request->getHeaderLine('Host')); - - // make sure value contains valid host component (IP or hostname) - if (!$parts || !isset($parts['scheme'], $parts['host'])) { - $parts = false; - } - - // make sure value does not contain any other URI component - if (\is_array($parts)) { - unset($parts['scheme'], $parts['host'], $parts['port']); - } - if ($parts === false || $parts) { - throw new \InvalidArgumentException('Invalid Host header value'); - } - } elseif (!$hasHost && $start['version'] === '1.1' && $start['method'] !== 'CONNECT') { - // require Host request header for HTTP/1.1 (except for CONNECT method) - throw new \InvalidArgumentException('Missing required Host request header'); - } elseif (!$hasHost) { - // remove default Host request header for HTTP/1.0 when not explicitly given - $request = $request->withoutHeader('Host'); - } - - // ensure message boundaries are valid according to Content-Length and Transfer-Encoding request headers - if ($request->hasHeader('Transfer-Encoding')) { - if (\strtolower($request->getHeaderLine('Transfer-Encoding')) !== 'chunked') { - throw new \InvalidArgumentException('Only chunked-encoding is allowed for Transfer-Encoding', Response::STATUS_NOT_IMPLEMENTED); - } - - // Transfer-Encoding: chunked and Content-Length header MUST NOT be used at the same time - // as per https://tools.ietf.org/html/rfc7230#section-3.3.3 - if ($request->hasHeader('Content-Length')) { - throw new \InvalidArgumentException('Using both `Transfer-Encoding: chunked` and `Content-Length` is not allowed', Response::STATUS_BAD_REQUEST); - } - } elseif ($request->hasHeader('Content-Length')) { - $string = $request->getHeaderLine('Content-Length'); - - if ((string)(int)$string !== $string) { - // Content-Length value is not an integer or not a single integer - throw new \InvalidArgumentException('The value of `Content-Length` is not valid', Response::STATUS_BAD_REQUEST); - } - } - - return $request; - } } diff --git a/deps/vendor/react/http/src/Message/Uri.php b/deps/vendor/react/http/src/Message/Uri.php deleted file mode 100644 index 4309bbeda..000000000 --- a/deps/vendor/react/http/src/Message/Uri.php +++ /dev/null @@ -1,356 +0,0 @@ -scheme = \strtolower($parts['scheme']); - } - - if (isset($parts['user']) || isset($parts['pass'])) { - $this->userInfo = $this->encode(isset($parts['user']) ? $parts['user'] : '', \PHP_URL_USER) . (isset($parts['pass']) ? ':' . $this->encode($parts['pass'], \PHP_URL_PASS) : ''); - } - - if (isset($parts['host'])) { - $this->host = \strtolower($parts['host']); - } - - if (isset($parts['port']) && !(($parts['port'] === 80 && $this->scheme === 'http') || ($parts['port'] === 443 && $this->scheme === 'https'))) { - $this->port = $parts['port']; - } - - if (isset($parts['path'])) { - $this->path = $this->encode($parts['path'], \PHP_URL_PATH); - } - - if (isset($parts['query'])) { - $this->query = $this->encode($parts['query'], \PHP_URL_QUERY); - } - - if (isset($parts['fragment'])) { - $this->fragment = $this->encode($parts['fragment'], \PHP_URL_FRAGMENT); - } - } - - public function getScheme() - { - return $this->scheme; - } - - public function getAuthority() - { - if ($this->host === '') { - return ''; - } - - return ($this->userInfo !== '' ? $this->userInfo . '@' : '') . $this->host . ($this->port !== null ? ':' . $this->port : ''); - } - - public function getUserInfo() - { - return $this->userInfo; - } - - public function getHost() - { - return $this->host; - } - - public function getPort() - { - return $this->port; - } - - public function getPath() - { - return $this->path; - } - - public function getQuery() - { - return $this->query; - } - - public function getFragment() - { - return $this->fragment; - } - - public function withScheme($scheme) - { - $scheme = \strtolower($scheme); - if ($scheme === $this->scheme) { - return $this; - } - - if (!\preg_match('#^[a-z]*$#', $scheme)) { - throw new \InvalidArgumentException('Invalid URI scheme given'); - } - - $new = clone $this; - $new->scheme = $scheme; - - if (($this->port === 80 && $scheme === 'http') || ($this->port === 443 && $scheme === 'https')) { - $new->port = null; - } - - return $new; - } - - public function withUserInfo($user, $password = null) - { - $userInfo = $this->encode($user, \PHP_URL_USER) . ($password !== null ? ':' . $this->encode($password, \PHP_URL_PASS) : ''); - if ($userInfo === $this->userInfo) { - return $this; - } - - $new = clone $this; - $new->userInfo = $userInfo; - - return $new; - } - - public function withHost($host) - { - $host = \strtolower($host); - if ($host === $this->host) { - return $this; - } - - if (\preg_match('#[\s_%+]#', $host) || ($host !== '' && \parse_url('http://' . $host, \PHP_URL_HOST) !== $host)) { - throw new \InvalidArgumentException('Invalid URI host given'); - } - - $new = clone $this; - $new->host = $host; - - return $new; - } - - public function withPort($port) - { - $port = $port === null ? null : (int) $port; - if (($port === 80 && $this->scheme === 'http') || ($port === 443 && $this->scheme === 'https')) { - $port = null; - } - - if ($port === $this->port) { - return $this; - } - - if ($port !== null && ($port < 1 || $port > 0xffff)) { - throw new \InvalidArgumentException('Invalid URI port given'); - } - - $new = clone $this; - $new->port = $port; - - return $new; - } - - public function withPath($path) - { - $path = $this->encode($path, \PHP_URL_PATH); - if ($path === $this->path) { - return $this; - } - - $new = clone $this; - $new->path = $path; - - return $new; - } - - public function withQuery($query) - { - $query = $this->encode($query, \PHP_URL_QUERY); - if ($query === $this->query) { - return $this; - } - - $new = clone $this; - $new->query = $query; - - return $new; - } - - public function withFragment($fragment) - { - $fragment = $this->encode($fragment, \PHP_URL_FRAGMENT); - if ($fragment === $this->fragment) { - return $this; - } - - $new = clone $this; - $new->fragment = $fragment; - - return $new; - } - - public function __toString() - { - $uri = ''; - if ($this->scheme !== '') { - $uri .= $this->scheme . ':'; - } - - $authority = $this->getAuthority(); - if ($authority !== '') { - $uri .= '//' . $authority; - } - - if ($authority !== '' && isset($this->path[0]) && $this->path[0] !== '/') { - $uri .= '/' . $this->path; - } elseif ($authority === '' && isset($this->path[0]) && $this->path[0] === '/') { - $uri .= '/' . \ltrim($this->path, '/'); - } else { - $uri .= $this->path; - } - - if ($this->query !== '') { - $uri .= '?' . $this->query; - } - - if ($this->fragment !== '') { - $uri .= '#' . $this->fragment; - } - - return $uri; - } - - /** - * @param string $part - * @param int $component - * @return string - */ - private function encode($part, $component) - { - return \preg_replace_callback( - '/(?:[^a-z0-9_\-\.~!\$&\'\(\)\*\+,;=' . ($component === \PHP_URL_PATH ? ':@\/' : ($component === \PHP_URL_QUERY || $component === \PHP_URL_FRAGMENT ? ':@\/\?' : '')) . '%]++|%(?![a-f0-9]{2}))/i', - function (array $match) { - return \rawurlencode($match[0]); - }, - $part - ); - } - - /** - * [Internal] Resolve URI relative to base URI and return new absolute URI - * - * @internal - * @param UriInterface $base - * @param UriInterface $rel - * @return UriInterface - * @throws void - */ - public static function resolve(UriInterface $base, UriInterface $rel) - { - if ($rel->getScheme() !== '') { - return $rel->getPath() === '' ? $rel : $rel->withPath(self::removeDotSegments($rel->getPath())); - } - - $reset = false; - $new = $base; - if ($rel->getAuthority() !== '') { - $reset = true; - $userInfo = \explode(':', $rel->getUserInfo(), 2); - $new = $base->withUserInfo($userInfo[0], isset($userInfo[1]) ? $userInfo[1]: null)->withHost($rel->getHost())->withPort($rel->getPort()); - } - - if ($reset && $rel->getPath() === '') { - $new = $new->withPath(''); - } elseif (($path = $rel->getPath()) !== '') { - $start = ''; - if ($path === '' || $path[0] !== '/') { - $start = $base->getPath(); - if (\substr($start, -1) !== '/') { - $start .= '/../'; - } - } - $reset = true; - $new = $new->withPath(self::removeDotSegments($start . $path)); - } - if ($reset || $rel->getQuery() !== '') { - $reset = true; - $new = $new->withQuery($rel->getQuery()); - } - if ($reset || $rel->getFragment() !== '') { - $new = $new->withFragment($rel->getFragment()); - } - - return $new; - } - - /** - * @param string $path - * @return string - */ - private static function removeDotSegments($path) - { - $segments = array(); - foreach (\explode('/', $path) as $segment) { - if ($segment === '..') { - \array_pop($segments); - } elseif ($segment !== '.' && $segment !== '') { - $segments[] = $segment; - } - } - return '/' . \implode('/', $segments) . ($path !== '/' && \substr($path, -1) === '/' ? '/' : ''); - } -} diff --git a/deps/vendor/react/http/src/Middleware/LimitConcurrentRequestsMiddleware.php b/deps/vendor/react/http/src/Middleware/LimitConcurrentRequestsMiddleware.php index b1c00da00..533381008 100644 --- a/deps/vendor/react/http/src/Middleware/LimitConcurrentRequestsMiddleware.php +++ b/deps/vendor/react/http/src/Middleware/LimitConcurrentRequestsMiddleware.php @@ -206,6 +206,6 @@ public function processQueue() $first = \reset($this->queue); unset($this->queue[key($this->queue)]); - $first->resolve(null); + $first->resolve(); } } diff --git a/deps/vendor/react/http/src/Middleware/RequestBodyBufferMiddleware.php b/deps/vendor/react/http/src/Middleware/RequestBodyBufferMiddleware.php index ddb39f5e9..c13a5dec5 100644 --- a/deps/vendor/react/http/src/Middleware/RequestBodyBufferMiddleware.php +++ b/deps/vendor/react/http/src/Middleware/RequestBodyBufferMiddleware.php @@ -6,7 +6,7 @@ use Psr\Http\Message\ServerRequestInterface; use React\Http\Io\BufferedBody; use React\Http\Io\IniUtil; -use React\Promise\Promise; +use React\Promise\Stream; use React\Stream\ReadableStreamInterface; final class RequestBodyBufferMiddleware @@ -29,19 +29,19 @@ public function __construct($sizeLimit = null) $this->sizeLimit = IniUtil::iniSizeToBytes($sizeLimit); } - public function __invoke(ServerRequestInterface $request, $next) + public function __invoke(ServerRequestInterface $request, $stack) { $body = $request->getBody(); $size = $body->getSize(); // happy path: skip if body is known to be empty (or is already buffered) - if ($size === 0 || !$body instanceof ReadableStreamInterface || !$body->isReadable()) { + if ($size === 0 || !$body instanceof ReadableStreamInterface) { // replace with empty body if body is streaming (or buffered size exceeds limit) if ($body instanceof ReadableStreamInterface || $size > $this->sizeLimit) { $request = $request->withBody(new BufferedBody('')); } - return $next($request); + return $stack($request); } // request body of known size exceeding limit @@ -50,60 +50,21 @@ public function __invoke(ServerRequestInterface $request, $next) $sizeLimit = 0; } - /** @var ?\Closure $closer */ - $closer = null; - - return new Promise(function ($resolve, $reject) use ($body, &$closer, $sizeLimit, $request, $next) { - // buffer request body data in memory, discard but keep buffering if limit is reached - $buffer = ''; - $bufferer = null; - $body->on('data', $bufferer = function ($data) use (&$buffer, $sizeLimit, $body, &$bufferer) { - $buffer .= $data; - - // On buffer overflow keep the request body stream in, - // but ignore the contents and wait for the close event - // before passing the request on to the next middleware. - if (isset($buffer[$sizeLimit])) { - assert($bufferer instanceof \Closure); - $body->removeListener('data', $bufferer); - $bufferer = null; - $buffer = ''; - } - }); - - // call $next with current buffer and resolve or reject with its results - $body->on('close', $closer = function () use (&$buffer, $request, $resolve, $reject, $next) { - try { - // resolve with result of next handler - $resolve($next($request->withBody(new BufferedBody($buffer)))); - } catch (\Exception $e) { - $reject($e); - } catch (\Throwable $e) { // @codeCoverageIgnoreStart - // reject Errors just like Exceptions (PHP 7+) - $reject($e); // @codeCoverageIgnoreEnd - } - }); - - // reject buffering if body emits error - $body->on('error', function (\Exception $e) use ($reject, $body, $closer) { - // remove close handler to avoid resolving, then close and reject - assert($closer instanceof \Closure); - $body->removeListener('close', $closer); - $body->close(); - - $reject(new \RuntimeException( - 'Error while buffering request body: ' . $e->getMessage(), - $e->getCode(), - $e - )); - }); - }, function () use ($body, &$closer) { - // cancelled buffering: remove close handler to avoid resolving, then close and reject - assert($closer instanceof \Closure); - $body->removeListener('close', $closer); - $body->close(); + return Stream\buffer($body, $sizeLimit)->then(function ($buffer) use ($request, $stack) { + $request = $request->withBody(new BufferedBody($buffer)); + + return $stack($request); + }, function ($error) use ($stack, $request, $body) { + // On buffer overflow keep the request body stream in, + // but ignore the contents and wait for the close event + // before passing the request on to the next middleware. + if ($error instanceof OverflowException) { + return Stream\first($body, 'close')->then(function () use ($stack, $request) { + return $stack($request); + }); + } - throw new \RuntimeException('Cancelled buffering request body'); + throw $error; }); } } diff --git a/deps/vendor/react/promise-stream/CHANGELOG.md b/deps/vendor/react/promise-stream/CHANGELOG.md new file mode 100644 index 000000000..63d6f0182 --- /dev/null +++ b/deps/vendor/react/promise-stream/CHANGELOG.md @@ -0,0 +1,79 @@ +# Changelog + +## 1.3.0 (2021-10-18) + +* Feature: Improve error reporting by appending previous exception messages. + (#26 by @clue) + + For most common use cases this means that simply reporting the `Exception` + message should give the most relevant details for any issues: + + ```php + React\Promise\Stream\buffer($stream)->then(function (string $contents) { + // … + }, function (Exception $e) { + echo 'Error:' . $e->getMessage() . PHP_EOL; + }); + ``` + +* Improve documentation, describe promise and stream data types. + (#27 by @clue and #23 by @WyriHaximus) + +* Improve test suite and add `.gitattributes` to exclude dev files from exports. + Use GitHub actions for continuous integration (CI) and run tests on PHPUnit 9 and PHP 8. + (#21 by @reedy and #22, #24 and #25 by @SimonFrings) + +## 1.2.0 (2019-07-03) + +* Feature: Support unwrapping object streams by buffering original write chunks in array. + (#15 by @clue) + +* Feature: Clean up unneeded references for unwrapped streams when closing. + (#18 by @clue) + +* Fix: Writing to closed unwrapped stream should return false (backpressure). + (#17 by @clue) + +* Improve test suite to support PHPUnit 7, PHP 7.3 and fix incomplete test + and improve API documentation. + (#16 and #19 by @clue) + +## 1.1.1 (2017-12-22) + +* Fix: Fix `all()` to assume null values if no event data is passed + (#13 by @clue) + +* Improve test suite by simplifying test bootstrapping logic via Composer and + add forward compatibility with PHPUnit 5 and PHPUnit 6 and + test against PHP 7.1 and 7.2 + (#11 and #12 by @clue and #9 by @carusogabriel) + +## 1.1.0 (2017-11-28) + +* Feature: Reject `first()` when stream emits an error event + (#7 by @clue) + +* Fix: Explicit `close()` of unwrapped stream should not emit `error` event + (#8 by @clue) + +* Internal refactoring to simplify `buffer()` function + (#6 by @kelunik) + +## 1.0.0 (2017-10-24) + +* First stable release, now following SemVer + +> Contains no other changes, so it's actually fully compatible with the v0.1.2 release. + +## 0.1.2 (2017-10-18) + +* Feature: Optional maximum buffer length for `buffer()` (#3 by @WyriHaximus) +* Improvement: Readme improvements (#5 by @jsor) + +## 0.1.1 (2017-05-15) + +* Improvement: Forward compatibility with stream 1.0, 0.7, 0.6, and 0.5 (#2 by @WyriHaximus) + +## 0.1.0 (2017-05-10) + +* Initial release, adapted from [`clue/promise-stream-react`](https://github.com/clue/php-promise-stream-react) diff --git a/deps/vendor/react/promise-stream/LICENSE b/deps/vendor/react/promise-stream/LICENSE new file mode 100644 index 000000000..25e707125 --- /dev/null +++ b/deps/vendor/react/promise-stream/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Christian Lück, Cees-Jan Kiewiet, Jan Sorgalla, Chris Boden + +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: + +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, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/deps/vendor/react/promise-stream/README.md b/deps/vendor/react/promise-stream/README.md new file mode 100644 index 000000000..b8ad1b457 --- /dev/null +++ b/deps/vendor/react/promise-stream/README.md @@ -0,0 +1,292 @@ +# PromiseStream + +[![CI status](https://github.com/reactphp/promise-stream/workflows/CI/badge.svg)](https://github.com/reactphp/promise-stream/actions) + +The missing link between Promise-land and Stream-land +for [ReactPHP](https://reactphp.org/). + +**Table of Contents** + +* [Usage](#usage) + * [buffer()](#buffer) + * [first()](#first) + * [all()](#all) + * [unwrapReadable()](#unwrapreadable) + * [unwrapWritable()](#unwrapwritable) +* [Install](#install) +* [Tests](#tests) +* [License](#license) + +## Usage + +This lightweight library consists only of a few simple functions. +All functions reside under the `React\Promise\Stream` namespace. + +The below examples refer to all functions with their fully-qualified names like this: + +```php +React\Promise\Stream\buffer(…); +``` + +As of PHP 5.6+ you can also import each required function into your code like this: + +```php +use function React\Promise\Stream\buffer; + +buffer(…); +``` + +Alternatively, you can also use an import statement similar to this: + +```php +use React\Promise\Stream; + +Stream\buffer(…); +``` + +### buffer() + +The `buffer(ReadableStreamInterface $stream, ?int $maxLength = null): PromiseInterface` function can be used to +create a `Promise` which will be fulfilled with the stream data buffer. + +```php +$stream = accessSomeJsonStream(); + +React\Promise\Stream\buffer($stream)->then(function (string $contents) { + var_dump(json_decode($contents)); +}); +``` + +The promise will be fulfilled with a `string` of all data chunks concatenated once the stream closes. + +The promise will be fulfilled with an empty `string` if the stream is already closed. + +The promise will be rejected with a `RuntimeException` if the stream emits an error. + +The promise will be rejected with a `RuntimeException` if it is cancelled. + +The optional `$maxLength` argument defaults to no limit. In case the maximum +length is given and the stream emits more data before the end, the promise +will be rejected with an `OverflowException`. + +```php +$stream = accessSomeToLargeStream(); + +React\Promise\Stream\buffer($stream, 1024)->then(function ($contents) { + var_dump(json_decode($contents)); +}, function ($error) { + // Reaching here when the stream buffer goes above the max size, + // in this example that is 1024 bytes, + // or when the stream emits an error. +}); +``` + +### first() + +The `first(ReadableStreamInterface|WritableStreamInterface $stream, string $event = 'data'): PromiseInterface` function can be used to +create a `Promise` which will be fulfilled once the given event triggers for the first time. + +```php +$stream = accessSomeJsonStream(); + +React\Promise\Stream\first($stream)->then(function (string $chunk) { + echo 'The first chunk arrived: ' . $chunk; +}); +``` + +The promise will be fulfilled with a `mixed` value of whatever the first event +emitted or `null` if the event does not pass any data. +If you do not pass a custom event name, then it will wait for the first "data" +event. +For common streams of type `ReadableStreamInterface`, this means it will be +fulfilled with a `string` containing the first data chunk. + +The promise will be rejected with a `RuntimeException` if the stream emits an error +– unless you're waiting for the "error" event, in which case it will be fulfilled. + +The promise will be rejected with a `RuntimeException` once the stream closes +– unless you're waiting for the "close" event, in which case it will be fulfilled. + +The promise will be rejected with a `RuntimeException` if the stream is already closed. + +The promise will be rejected with a `RuntimeException` if it is cancelled. + +### all() + +The `all(ReadableStreamInterface|WritableStreamInterface $stream, string $event = 'data'): PromiseInterface` function can be used to +create a `Promise` which will be fulfilled with an array of all the event data. + +```php +$stream = accessSomeJsonStream(); + +React\Promise\Stream\all($stream)->then(function (array $chunks) { + echo 'The stream consists of ' . count($chunks) . ' chunk(s)'; +}); +``` + +The promise will be fulfilled with an `array` once the stream closes. The array +will contain whatever all events emitted or `null` values if the events do not pass any data. +If you do not pass a custom event name, then it will wait for all the "data" +events. +For common streams of type `ReadableStreamInterface`, this means it will be +fulfilled with a `string[]` array containing all the data chunk. + +The promise will be fulfilled with an empty `array` if the stream is already closed. + +The promise will be rejected with a `RuntimeException` if the stream emits an error. + +The promise will be rejected with a `RuntimeException` if it is cancelled. + +### unwrapReadable() + +The `unwrapReadable(PromiseInterface,Exception> $promise): ReadableStreamInterface` function can be used to +unwrap a `Promise` which will be fulfilled with a `ReadableStreamInterface`. + +This function returns a readable stream instance (implementing `ReadableStreamInterface`) +right away which acts as a proxy for the future promise resolution. +Once the given Promise will be fulfilled with a `ReadableStreamInterface`, its +data will be piped to the output stream. + +```php +//$promise = someFunctionWhichResolvesWithAStream(); +$promise = startDownloadStream($uri); + +$stream = React\Promise\Stream\unwrapReadable($promise); + +$stream->on('data', function (string $data) { + echo $data; +}); + +$stream->on('end', function () { + echo 'DONE'; +}); +``` + +If the given promise is either rejected or fulfilled with anything but an +instance of `ReadableStreamInterface`, then the output stream will emit +an `error` event and close: + +```php +$promise = startDownloadStream($invalidUri); + +$stream = React\Promise\Stream\unwrapReadable($promise); + +$stream->on('error', function (Exception $error) { + echo 'Error: ' . $error->getMessage(); +}); +``` + +The given `$promise` SHOULD be pending, i.e. it SHOULD NOT be fulfilled or rejected +at the time of invoking this function. +If the given promise is already settled and does not fulfill with an instance of +`ReadableStreamInterface`, then you will not be able to receive the `error` event. + +You can `close()` the resulting stream at any time, which will either try to +`cancel()` the pending promise or try to `close()` the underlying stream. + +```php +$promise = startDownloadStream($uri); + +$stream = React\Promise\Stream\unwrapReadable($promise); + +$loop->addTimer(2.0, function () use ($stream) { + $stream->close(); +}); +``` + +### unwrapWritable() + +The `unwrapWritable(PromiseInterface,Exception> $promise): WritableStreamInterface` function can be used to +unwrap a `Promise` which will be fulfilled with a `WritableStreamInterface`. + +This function returns a writable stream instance (implementing `WritableStreamInterface`) +right away which acts as a proxy for the future promise resolution. +Any writes to this instance will be buffered in memory for when the promise will +be fulfilled. +Once the given Promise will be fulfilled with a `WritableStreamInterface`, any +data you have written to the proxy will be forwarded transparently to the inner +stream. + +```php +//$promise = someFunctionWhichResolvesWithAStream(); +$promise = startUploadStream($uri); + +$stream = React\Promise\Stream\unwrapWritable($promise); + +$stream->write('hello'); +$stream->end('world'); + +$stream->on('close', function () { + echo 'DONE'; +}); +``` + +If the given promise is either rejected or fulfilled with anything but an +instance of `WritableStreamInterface`, then the output stream will emit +an `error` event and close: + +```php +$promise = startUploadStream($invalidUri); + +$stream = React\Promise\Stream\unwrapWritable($promise); + +$stream->on('error', function (Exception $error) { + echo 'Error: ' . $error->getMessage(); +}); +``` + +The given `$promise` SHOULD be pending, i.e. it SHOULD NOT be fulfilled or rejected +at the time of invoking this function. +If the given promise is already settled and does not fulfill with an instance of +`WritableStreamInterface`, then you will not be able to receive the `error` event. + +You can `close()` the resulting stream at any time, which will either try to +`cancel()` the pending promise or try to `close()` the underlying stream. + +```php +$promise = startUploadStream($uri); + +$stream = React\Promise\Stream\unwrapWritable($promise); + +$loop->addTimer(2.0, function () use ($stream) { + $stream->close(); +}); +``` + +## Install + +The recommended way to install this library is [through Composer](https://getcomposer.org/). +[New to Composer?](https://getcomposer.org/doc/00-intro.md) + +This project follows [SemVer](https://semver.org/). +This will install the latest supported version: + +```bash +$ composer require react/promise-stream:^1.3 +``` + +See also the [CHANGELOG](CHANGELOG.md) for details about version upgrades. + +This project aims to run on any platform and thus does not require any PHP +extensions and supports running on legacy PHP 5.3 through current PHP 8+ and +HHVM. +It's *highly recommended to use the latest supported PHP version* for this project. + +## Tests + +To run the test suite, you first need to clone this repo and then install all +dependencies [through Composer](https://getcomposer.org/): + +```bash +$ composer install +``` + +To run the test suite, go to the project root and run: + +```bash +$ vendor/bin/phpunit +``` + +## License + +MIT, see [LICENSE file](LICENSE). diff --git a/deps/vendor/react/promise-stream/composer.json b/deps/vendor/react/promise-stream/composer.json new file mode 100644 index 000000000..ee3972cee --- /dev/null +++ b/deps/vendor/react/promise-stream/composer.json @@ -0,0 +1,47 @@ +{ + "name": "react/promise-stream", + "description": "The missing link between Promise-land and Stream-land for ReactPHP", + "keywords": ["unwrap", "stream", "buffer", "promise", "ReactPHP", "async"], + "homepage": "https://github.com/reactphp/promise-stream", + "license": "MIT", + "authors": [ + { + "name": "Christian Lück", + "homepage": "https://clue.engineering/", + "email": "christian@clue.engineering" + }, + { + "name": "Cees-Jan Kiewiet", + "homepage": "https://wyrihaximus.net/", + "email": "reactphp@ceesjankiewiet.nl" + }, + { + "name": "Jan Sorgalla", + "homepage": "https://sorgalla.com/", + "email": "jsorgalla@gmail.com" + }, + { + "name": "Chris Boden", + "homepage": "https://cboden.dev/", + "email": "cboden@gmail.com" + } + ], + "autoload": { + "psr-4": { "React\\Promise\\Stream\\" : "src/" }, + "files": [ "src/functions_include.php" ] + }, + "autoload-dev": { + "psr-4": { "React\\Tests\\Promise\\Stream\\": "tests/" } + }, + "require": { + "php": ">=5.3", + "react/stream": "^1.0 || ^0.7 || ^0.6 || ^0.5 || ^0.4.6", + "react/promise": "^2.1 || ^1.2" + }, + "require-dev": { + "react/event-loop": "^1.0 || ^0.5 || ^0.4 || ^0.3", + "react/promise-timer": "^1.0", + "clue/block-react": "^1.0", + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35" + } +} diff --git a/deps/vendor/react/promise-stream/src/UnwrapReadableStream.php b/deps/vendor/react/promise-stream/src/UnwrapReadableStream.php new file mode 100644 index 000000000..acd23be73 --- /dev/null +++ b/deps/vendor/react/promise-stream/src/UnwrapReadableStream.php @@ -0,0 +1,137 @@ + + */ + public function __construct(PromiseInterface $promise) + { + $out = $this; + $closed =& $this->closed; + + $this->promise = $promise->then( + function ($stream) { + if (!$stream instanceof ReadableStreamInterface) { + throw new InvalidArgumentException('Not a readable stream'); + } + return $stream; + } + )->then( + function (ReadableStreamInterface $stream) use ($out, &$closed) { + // stream is already closed, make sure to close output stream + if (!$stream->isReadable()) { + $out->close(); + return $stream; + } + + // resolves but output is already closed, make sure to close stream silently + if ($closed) { + $stream->close(); + return $stream; + } + + // stream any writes into output stream + $stream->on('data', function ($data) use ($out) { + $out->emit('data', array($data, $out)); + }); + + // forward end events and close + $stream->on('end', function () use ($out, &$closed) { + if (!$closed) { + $out->emit('end', array($out)); + $out->close(); + } + }); + + // error events cancel output stream + $stream->on('error', function ($error) use ($out) { + $out->emit('error', array($error, $out)); + $out->close(); + }); + + // close both streams once either side closes + $stream->on('close', array($out, 'close')); + $out->on('close', array($stream, 'close')); + + return $stream; + }, + function ($e) use ($out, &$closed) { + if (!$closed) { + $out->emit('error', array($e, $out)); + $out->close(); + } + + // resume() and pause() may attach to this promise, so ensure we actually reject here + throw $e; + } + ); + } + + public function isReadable() + { + return !$this->closed; + } + + public function pause() + { + if ($this->promise !== null) { + $this->promise->then(function (ReadableStreamInterface $stream) { + $stream->pause(); + }); + } + } + + public function resume() + { + if ($this->promise !== null) { + $this->promise->then(function (ReadableStreamInterface $stream) { + $stream->resume(); + }); + } + } + + public function pipe(WritableStreamInterface $dest, array $options = array()) + { + Util::pipe($this, $dest, $options); + + return $dest; + } + + public function close() + { + if ($this->closed) { + return; + } + + $this->closed = true; + + // try to cancel promise once the stream closes + if ($this->promise instanceof CancellablePromiseInterface) { + $this->promise->cancel(); + } + $this->promise = null; + + $this->emit('close'); + $this->removeAllListeners(); + } +} diff --git a/deps/vendor/react/promise-stream/src/UnwrapWritableStream.php b/deps/vendor/react/promise-stream/src/UnwrapWritableStream.php new file mode 100644 index 000000000..f19e706ee --- /dev/null +++ b/deps/vendor/react/promise-stream/src/UnwrapWritableStream.php @@ -0,0 +1,164 @@ + + */ + public function __construct(PromiseInterface $promise) + { + $out = $this; + $store =& $this->stream; + $buffer =& $this->buffer; + $ending =& $this->ending; + $closed =& $this->closed; + + $this->promise = $promise->then( + function ($stream) { + if (!$stream instanceof WritableStreamInterface) { + throw new InvalidArgumentException('Not a writable stream'); + } + return $stream; + } + )->then( + function (WritableStreamInterface $stream) use ($out, &$store, &$buffer, &$ending, &$closed) { + // stream is already closed, make sure to close output stream + if (!$stream->isWritable()) { + $out->close(); + return $stream; + } + + // resolves but output is already closed, make sure to close stream silently + if ($closed) { + $stream->close(); + return $stream; + } + + // forward drain events for back pressure + $stream->on('drain', function () use ($out) { + $out->emit('drain', array($out)); + }); + + // error events cancel output stream + $stream->on('error', function ($error) use ($out) { + $out->emit('error', array($error, $out)); + $out->close(); + }); + + // close both streams once either side closes + $stream->on('close', array($out, 'close')); + $out->on('close', array($stream, 'close')); + + if ($buffer) { + // flush buffer to stream and check if its buffer is not exceeded + $drained = true; + foreach ($buffer as $chunk) { + if (!$stream->write($chunk)) { + $drained = false; + } + } + $buffer = array(); + + if ($drained) { + // signal drain event, because the output stream previous signalled a full buffer + $out->emit('drain', array($out)); + } + } + + if ($ending) { + $stream->end(); + } else { + $store = $stream; + } + + return $stream; + }, + function ($e) use ($out, &$closed) { + if (!$closed) { + $out->emit('error', array($e, $out)); + $out->close(); + } + } + ); + } + + public function write($data) + { + if ($this->ending) { + return false; + } + + // forward to inner stream if possible + if ($this->stream !== null) { + return $this->stream->write($data); + } + + // append to buffer and signal the buffer is full + $this->buffer[] = $data; + return false; + } + + public function end($data = null) + { + if ($this->ending) { + return; + } + + $this->ending = true; + + // forward to inner stream if possible + if ($this->stream !== null) { + return $this->stream->end($data); + } + + // append to buffer + if ($data !== null) { + $this->buffer[] = $data; + } + } + + public function isWritable() + { + return !$this->ending; + } + + public function close() + { + if ($this->closed) { + return; + } + + $this->buffer = array(); + $this->ending = true; + $this->closed = true; + + // try to cancel promise once the stream closes + if ($this->promise instanceof CancellablePromiseInterface) { + $this->promise->cancel(); + } + $this->promise = $this->stream = null; + + $this->emit('close'); + $this->removeAllListeners(); + } +} diff --git a/deps/vendor/react/promise-stream/src/functions.php b/deps/vendor/react/promise-stream/src/functions.php new file mode 100644 index 000000000..da66de8ba --- /dev/null +++ b/deps/vendor/react/promise-stream/src/functions.php @@ -0,0 +1,370 @@ +then(function (string $contents) { + * var_dump(json_decode($contents)); + * }); + * ``` + * + * The promise will be fulfilled with a `string` of all data chunks concatenated once the stream closes. + * + * The promise will be fulfilled with an empty `string` if the stream is already closed. + * + * The promise will be rejected with a `RuntimeException` if the stream emits an error. + * + * The promise will be rejected with a `RuntimeException` if it is cancelled. + * + * The optional `$maxLength` argument defaults to no limit. In case the maximum + * length is given and the stream emits more data before the end, the promise + * will be rejected with an `OverflowException`. + * + * ```php + * $stream = accessSomeToLargeStream(); + * + * React\Promise\Stream\buffer($stream, 1024)->then(function ($contents) { + * var_dump(json_decode($contents)); + * }, function ($error) { + * // Reaching here when the stream buffer goes above the max size, + * // in this example that is 1024 bytes, + * // or when the stream emits an error. + * }); + * ``` + * + * @param ReadableStreamInterface $stream + * @param ?int $maxLength Maximum number of bytes to buffer or null for unlimited. + * @return PromiseInterface + */ +function buffer(ReadableStreamInterface $stream, $maxLength = null) +{ + // stream already ended => resolve with empty buffer + if (!$stream->isReadable()) { + return Promise\resolve(''); + } + + $buffer = ''; + + $promise = new Promise\Promise(function ($resolve, $reject) use ($stream, $maxLength, &$buffer, &$bufferer) { + $bufferer = function ($data) use (&$buffer, $reject, $maxLength) { + $buffer .= $data; + + if ($maxLength !== null && isset($buffer[$maxLength])) { + $reject(new \OverflowException('Buffer exceeded maximum length')); + } + }; + + $stream->on('data', $bufferer); + + $stream->on('error', function (\Exception $e) use ($reject) { + $reject(new \RuntimeException( + 'An error occured on the underlying stream while buffering: ' . $e->getMessage(), + $e->getCode(), + $e + )); + }); + + $stream->on('close', function () use ($resolve, &$buffer) { + $resolve($buffer); + }); + }, function ($_, $reject) { + $reject(new \RuntimeException('Cancelled buffering')); + }); + + return $promise->then(null, function (\Exception $error) use (&$buffer, $bufferer, $stream) { + // promise rejected => clear buffer and buffering + $buffer = ''; + $stream->removeListener('data', $bufferer); + + throw $error; + }); +} + +/** + * Create a `Promise` which will be fulfilled once the given event triggers for the first time. + * + * ```php + * $stream = accessSomeJsonStream(); + * + * React\Promise\Stream\first($stream)->then(function (string $chunk) { + * echo 'The first chunk arrived: ' . $chunk; + * }); + * ``` + * + * The promise will be fulfilled with a `mixed` value of whatever the first event + * emitted or `null` if the event does not pass any data. + * If you do not pass a custom event name, then it will wait for the first "data" + * event. + * For common streams of type `ReadableStreamInterface`, this means it will be + * fulfilled with a `string` containing the first data chunk. + * + * The promise will be rejected with a `RuntimeException` if the stream emits an error + * – unless you're waiting for the "error" event, in which case it will be fulfilled. + * + * The promise will be rejected with a `RuntimeException` once the stream closes + * – unless you're waiting for the "close" event, in which case it will be fulfilled. + * + * The promise will be rejected with a `RuntimeException` if the stream is already closed. + * + * The promise will be rejected with a `RuntimeException` if it is cancelled. + * + * @param ReadableStreamInterface|WritableStreamInterface $stream + * @param string $event + * @return PromiseInterface + */ +function first(EventEmitterInterface $stream, $event = 'data') +{ + if ($stream instanceof ReadableStreamInterface) { + // readable or duplex stream not readable => already closed + // a half-open duplex stream is considered closed if its readable side is closed + if (!$stream->isReadable()) { + return Promise\reject(new \RuntimeException('Stream already closed')); + } + } elseif ($stream instanceof WritableStreamInterface) { + // writable-only stream (not duplex) not writable => already closed + if (!$stream->isWritable()) { + return Promise\reject(new \RuntimeException('Stream already closed')); + } + } + + return new Promise\Promise(function ($resolve, $reject) use ($stream, $event, &$listener) { + $listener = function ($data = null) use ($stream, $event, &$listener, $resolve) { + $stream->removeListener($event, $listener); + $resolve($data); + }; + $stream->on($event, $listener); + + if ($event !== 'error') { + $stream->on('error', function (\Exception $e) use ($stream, $event, $listener, $reject) { + $stream->removeListener($event, $listener); + $reject(new \RuntimeException( + 'An error occured on the underlying stream while waiting for event: ' . $e->getMessage(), + $e->getCode(), + $e + )); + }); + } + + $stream->on('close', function () use ($stream, $event, $listener, $reject) { + $stream->removeListener($event, $listener); + $reject(new \RuntimeException('Stream closed')); + }); + }, function ($_, $reject) use ($stream, $event, &$listener) { + $stream->removeListener($event, $listener); + $reject(new \RuntimeException('Operation cancelled')); + }); +} + +/** + * Create a `Promise` which will be fulfilled with an array of all the event data. + * + * ```php + * $stream = accessSomeJsonStream(); + * + * React\Promise\Stream\all($stream)->then(function (array $chunks) { + * echo 'The stream consists of ' . count($chunks) . ' chunk(s)'; + * }); + * ``` + * + * The promise will be fulfilled with an `array` once the stream closes. The array + * will contain whatever all events emitted or `null` values if the events do not pass any data. + * If you do not pass a custom event name, then it will wait for all the "data" + * events. + * For common streams of type `ReadableStreamInterface`, this means it will be + * fulfilled with a `string[]` array containing all the data chunk. + * + * The promise will be fulfilled with an empty `array` if the stream is already closed. + * + * The promise will be rejected with a `RuntimeException` if the stream emits an error. + * + * The promise will be rejected with a `RuntimeException` if it is cancelled. + * + * @param ReadableStreamInterface|WritableStreamInterface $stream + * @param string $event + * @return PromiseInterface + */ +function all(EventEmitterInterface $stream, $event = 'data') +{ + // stream already ended => resolve with empty buffer + if ($stream instanceof ReadableStreamInterface) { + // readable or duplex stream not readable => already closed + // a half-open duplex stream is considered closed if its readable side is closed + if (!$stream->isReadable()) { + return Promise\resolve(array()); + } + } elseif ($stream instanceof WritableStreamInterface) { + // writable-only stream (not duplex) not writable => already closed + if (!$stream->isWritable()) { + return Promise\resolve(array()); + } + } + + $buffer = array(); + $bufferer = function ($data = null) use (&$buffer) { + $buffer []= $data; + }; + $stream->on($event, $bufferer); + + $promise = new Promise\Promise(function ($resolve, $reject) use ($stream, &$buffer) { + $stream->on('error', function (\Exception $e) use ($reject) { + $reject(new \RuntimeException( + 'An error occured on the underlying stream while buffering: ' . $e->getMessage(), + $e->getCode(), + $e + )); + }); + + $stream->on('close', function () use ($resolve, &$buffer) { + $resolve($buffer); + }); + }, function ($_, $reject) { + $reject(new \RuntimeException('Cancelled buffering')); + }); + + return $promise->then(null, function ($error) use (&$buffer, $bufferer, $stream, $event) { + // promise rejected => clear buffer and buffering + $buffer = array(); + $stream->removeListener($event, $bufferer); + + throw $error; + }); +} + +/** + * Unwrap a `Promise` which will be fulfilled with a `ReadableStreamInterface`. + * + * This function returns a readable stream instance (implementing `ReadableStreamInterface`) + * right away which acts as a proxy for the future promise resolution. + * Once the given Promise will be fulfilled with a `ReadableStreamInterface`, its + * data will be piped to the output stream. + * + * ```php + * //$promise = someFunctionWhichResolvesWithAStream(); + * $promise = startDownloadStream($uri); + * + * $stream = React\Promise\Stream\unwrapReadable($promise); + * + * $stream->on('data', function (string $data) { + * echo $data; + * }); + * + * $stream->on('end', function () { + * echo 'DONE'; + * }); + * ``` + * + * If the given promise is either rejected or fulfilled with anything but an + * instance of `ReadableStreamInterface`, then the output stream will emit + * an `error` event and close: + * + * ```php + * $promise = startDownloadStream($invalidUri); + * + * $stream = React\Promise\Stream\unwrapReadable($promise); + * + * $stream->on('error', function (Exception $error) { + * echo 'Error: ' . $error->getMessage(); + * }); + * ``` + * + * The given `$promise` SHOULD be pending, i.e. it SHOULD NOT be fulfilled or rejected + * at the time of invoking this function. + * If the given promise is already settled and does not fulfill with an instance of + * `ReadableStreamInterface`, then you will not be able to receive the `error` event. + * + * You can `close()` the resulting stream at any time, which will either try to + * `cancel()` the pending promise or try to `close()` the underlying stream. + * + * ```php + * $promise = startDownloadStream($uri); + * + * $stream = React\Promise\Stream\unwrapReadable($promise); + * + * $loop->addTimer(2.0, function () use ($stream) { + * $stream->close(); + * }); + * ``` + * + * @param PromiseInterface,\Exception> $promise + * @return ReadableStreamInterface + */ +function unwrapReadable(PromiseInterface $promise) +{ + return new UnwrapReadableStream($promise); +} + +/** + * unwrap a `Promise` which will be fulfilled with a `WritableStreamInterface`. + * + * This function returns a writable stream instance (implementing `WritableStreamInterface`) + * right away which acts as a proxy for the future promise resolution. + * Any writes to this instance will be buffered in memory for when the promise will + * be fulfilled. + * Once the given Promise will be fulfilled with a `WritableStreamInterface`, any + * data you have written to the proxy will be forwarded transparently to the inner + * stream. + * + * ```php + * //$promise = someFunctionWhichResolvesWithAStream(); + * $promise = startUploadStream($uri); + * + * $stream = React\Promise\Stream\unwrapWritable($promise); + * + * $stream->write('hello'); + * $stream->end('world'); + * + * $stream->on('close', function () { + * echo 'DONE'; + * }); + * ``` + * + * If the given promise is either rejected or fulfilled with anything but an + * instance of `WritableStreamInterface`, then the output stream will emit + * an `error` event and close: + * + * ```php + * $promise = startUploadStream($invalidUri); + * + * $stream = React\Promise\Stream\unwrapWritable($promise); + * + * $stream->on('error', function (Exception $error) { + * echo 'Error: ' . $error->getMessage(); + * }); + * ``` + * + * The given `$promise` SHOULD be pending, i.e. it SHOULD NOT be fulfilled or rejected + * at the time of invoking this function. + * If the given promise is already settled and does not fulfill with an instance of + * `WritableStreamInterface`, then you will not be able to receive the `error` event. + * + * You can `close()` the resulting stream at any time, which will either try to + * `cancel()` the pending promise or try to `close()` the underlying stream. + * + * ```php + * $promise = startUploadStream($uri); + * + * $stream = React\Promise\Stream\unwrapWritable($promise); + * + * $loop->addTimer(2.0, function () use ($stream) { + * $stream->close(); + * }); + * ``` + * + * @param PromiseInterface,\Exception> $promise + * @return WritableStreamInterface + */ +function unwrapWritable(PromiseInterface $promise) +{ + return new UnwrapWritableStream($promise); +} diff --git a/deps/vendor/react/promise-stream/src/functions_include.php b/deps/vendor/react/promise-stream/src/functions_include.php new file mode 100644 index 000000000..768a4fdbe --- /dev/null +++ b/deps/vendor/react/promise-stream/src/functions_include.php @@ -0,0 +1,7 @@ + $promise, float $time, ?LoopInterface $loop = null): PromiseInterface` function can be used to +cancel operations that take *too long*. + +You need to pass in an input `$promise` that represents a pending operation +and timeout parameters. It returns a new promise with the following +resolution behavior: + +- If the input `$promise` resolves before `$time` seconds, resolve the + resulting promise with its fulfillment value. + +- If the input `$promise` rejects before `$time` seconds, reject the + resulting promise with its rejection value. + +- If the input `$promise` does not settle before `$time` seconds, *cancel* + the operation and reject the resulting promise with a [`TimeoutException`](#timeoutexception). + +Internally, the given `$time` value will be used to start a timer that will +*cancel* the pending operation once it triggers. This implies that if you +pass a really small (or negative) value, it will still start a timer and will +thus trigger at the earliest possible time in the future. + +If the input `$promise` is already settled, then the resulting promise will +resolve or reject immediately without starting a timer at all. + +This function takes an optional `LoopInterface|null $loop` parameter that can be used to +pass the event loop instance to use. You can use a `null` value here in order to +use the [default loop](https://github.com/reactphp/event-loop#loop). This value +SHOULD NOT be given unless you're sure you want to explicitly use a given event +loop instance. + +A common use case for handling only resolved values looks like this: + +```php +$promise = accessSomeRemoteResource(); +React\Promise\Timer\timeout($promise, 10.0)->then(function ($value) { + // the operation finished within 10.0 seconds +}); +``` + +A more complete example could look like this: + +```php +$promise = accessSomeRemoteResource(); +React\Promise\Timer\timeout($promise, 10.0)->then( + function ($value) { + // the operation finished within 10.0 seconds + }, + function ($error) { + if ($error instanceof React\Promise\Timer\TimeoutException) { + // the operation has failed due to a timeout + } else { + // the input operation has failed due to some other error + } + } +); +``` + +Or if you're using [react/promise v2.2.0](https://github.com/reactphp/promise) or up: + +```php +React\Promise\Timer\timeout($promise, 10.0) + ->then(function ($value) { + // the operation finished within 10.0 seconds + }) + ->otherwise(function (React\Promise\Timer\TimeoutException $error) { + // the operation has failed due to a timeout + }) + ->otherwise(function ($error) { + // the input operation has failed due to some other error + }) +; +``` + +As discussed above, the [`timeout()`](#timeout) function will take care of +the underlying operation if it takes *too long*. In this case, you can be +sure the resulting promise will always be rejected with a +[`TimeoutException`](#timeoutexception). On top of this, the function will +try to *cancel* the underlying operation. Responsibility for this +cancellation logic is left up to the underlying operation. + +- A common use case involves cleaning up any resources like open network + sockets or file handles or terminating external processes or timers. + +- If the given input `$promise` does not support cancellation, then this is a + NO-OP. This means that while the resulting promise will still be rejected, + the underlying input `$promise` may still be pending and can hence continue + consuming resources + +On top of this, the returned promise is implemented in such a way that it can +be cancelled when it is still pending. Cancelling a pending promise will +cancel the underlying operation. As discussed above, responsibility for this +cancellation logic is left up to the underlying operation. + +```php +$promise = accessSomeRemoteResource(); +$timeout = React\Promise\Timer\timeout($promise, 10.0); + +$timeout->cancel(); +``` + +For more details on the promise cancellation, please refer to the +[Promise documentation](https://github.com/reactphp/promise#cancellablepromiseinterface). + +If you want to wait for multiple promises to resolve, you can use the normal +promise primitives like this: + +```php +$promises = array( + accessSomeRemoteResource(), + accessSomeRemoteResource(), + accessSomeRemoteResource() +); + +$promise = React\Promise\all($promises); + +React\Promise\Timer\timeout($promise, 10)->then(function ($values) { + // *all* promises resolved +}); +``` + +The applies to all promise collection primitives alike, i.e. `all()`, +`race()`, `any()`, `some()` etc. + +For more details on the promise primitives, please refer to the +[Promise documentation](https://github.com/reactphp/promise#functions). + +### sleep() + +The `sleep(float $time, ?LoopInterface $loop = null): PromiseInterface` function can be used to +create a new promise that resolves in `$time` seconds. + +```php +React\Promise\Timer\sleep(1.5)->then(function () { + echo 'Thanks for waiting!' . PHP_EOL; +}); +``` + +Internally, the given `$time` value will be used to start a timer that will +resolve the promise once it triggers. This implies that if you pass a really +small (or negative) value, it will still start a timer and will thus trigger +at the earliest possible time in the future. + +This function takes an optional `LoopInterface|null $loop` parameter that can be used to +pass the event loop instance to use. You can use a `null` value here in order to +use the [default loop](https://github.com/reactphp/event-loop#loop). This value +SHOULD NOT be given unless you're sure you want to explicitly use a given event +loop instance. + +The returned promise is implemented in such a way that it can be cancelled +when it is still pending. Cancelling a pending promise will reject its value +with a `RuntimeException` and clean up any pending timers. + +```php +$timer = React\Promise\Timer\sleep(2.0); + +$timer->cancel(); +``` + +### ~~resolve()~~ + +> Deprecated since v1.8.0, see [`sleep()`](#sleep) instead. + +The `resolve(float $time, ?LoopInterface $loop = null): PromiseInterface` function can be used to +create a new promise that resolves in `$time` seconds with the `$time` as the fulfillment value. + +```php +React\Promise\Timer\resolve(1.5)->then(function ($time) { + echo 'Thanks for waiting ' . $time . ' seconds' . PHP_EOL; +}); +``` + +Internally, the given `$time` value will be used to start a timer that will +resolve the promise once it triggers. This implies that if you pass a really +small (or negative) value, it will still start a timer and will thus trigger +at the earliest possible time in the future. + +This function takes an optional `LoopInterface|null $loop` parameter that can be used to +pass the event loop instance to use. You can use a `null` value here in order to +use the [default loop](https://github.com/reactphp/event-loop#loop). This value +SHOULD NOT be given unless you're sure you want to explicitly use a given event +loop instance. + +The returned promise is implemented in such a way that it can be cancelled +when it is still pending. Cancelling a pending promise will reject its value +with a `RuntimeException` and clean up any pending timers. + +```php +$timer = React\Promise\Timer\resolve(2.0); + +$timer->cancel(); +``` + +### ~~reject()~~ + +> Deprecated since v1.8.0, see [`sleep()`](#sleep) instead. + +The `reject(float $time, ?LoopInterface $loop = null): PromiseInterface` function can be used to +create a new promise which rejects in `$time` seconds with a `TimeoutException`. + +```php +React\Promise\Timer\reject(2.0)->then(null, function (React\Promise\Timer\TimeoutException $e) { + echo 'Rejected after ' . $e->getTimeout() . ' seconds ' . PHP_EOL; +}); +``` + +Internally, the given `$time` value will be used to start a timer that will +reject the promise once it triggers. This implies that if you pass a really +small (or negative) value, it will still start a timer and will thus trigger +at the earliest possible time in the future. + +This function takes an optional `LoopInterface|null $loop` parameter that can be used to +pass the event loop instance to use. You can use a `null` value here in order to +use the [default loop](https://github.com/reactphp/event-loop#loop). This value +SHOULD NOT be given unless you're sure you want to explicitly use a given event +loop instance. + +The returned promise is implemented in such a way that it can be cancelled +when it is still pending. Cancelling a pending promise will reject its value +with a `RuntimeException` and clean up any pending timers. + +```php +$timer = React\Promise\Timer\reject(2.0); + +$timer->cancel(); +``` + +### TimeoutException + +The `TimeoutException` extends PHP's built-in `RuntimeException`. + + +#### getTimeout() + +The `getTimeout(): float` method can be used to +get the timeout value in seconds. + +## Install + +The recommended way to install this library is [through Composer](https://getcomposer.org/). +[New to Composer?](https://getcomposer.org/doc/00-intro.md) + +This project follows [SemVer](https://semver.org/). +This will install the latest supported version: + +```bash +$ composer require react/promise-timer:^1.8 +``` + +See also the [CHANGELOG](CHANGELOG.md) for details about version upgrades. + +This project aims to run on any platform and thus does not require any PHP +extensions and supports running on legacy PHP 5.3 through current PHP 8+ and +HHVM. +It's *highly recommended to use the latest supported PHP version* for this project. + +## Tests + +To run the test suite, you first need to clone this repo and then install all +dependencies [through Composer](https://getcomposer.org/): + +```bash +$ composer install +``` + +To run the test suite, go to the project root and run: + +```bash +$ vendor/bin/phpunit +``` + +## License + +MIT, see [LICENSE file](LICENSE). diff --git a/deps/vendor/react/promise-timer/composer.json b/deps/vendor/react/promise-timer/composer.json new file mode 100644 index 000000000..7335298cc --- /dev/null +++ b/deps/vendor/react/promise-timer/composer.json @@ -0,0 +1,44 @@ +{ + "name": "react/promise-timer", + "description": "A trivial implementation of timeouts for Promises, built on top of ReactPHP.", + "keywords": ["Promise", "timeout", "timer", "event-loop", "ReactPHP", "async"], + "homepage": "https://github.com/reactphp/promise-timer", + "license": "MIT", + "authors": [ + { + "name": "Christian Lück", + "homepage": "https://clue.engineering/", + "email": "christian@clue.engineering" + }, + { + "name": "Cees-Jan Kiewiet", + "homepage": "https://wyrihaximus.net/", + "email": "reactphp@ceesjankiewiet.nl" + }, + { + "name": "Jan Sorgalla", + "homepage": "https://sorgalla.com/", + "email": "jsorgalla@gmail.com" + }, + { + "name": "Chris Boden", + "homepage": "https://cboden.dev/", + "email": "cboden@gmail.com" + } + ], + "autoload": { + "psr-4": { "React\\Promise\\Timer\\": "src/" }, + "files": [ "src/functions_include.php" ] + }, + "autoload-dev": { + "psr-4": { "React\\Tests\\Promise\\Timer\\": "tests/" } + }, + "require": { + "php": ">=5.3", + "react/event-loop": "^1.2", + "react/promise": "^3.0 || ^2.7.0 || ^1.2.1" + }, + "require-dev": { + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35" + } +} diff --git a/deps/vendor/react/promise-timer/src/TimeoutException.php b/deps/vendor/react/promise-timer/src/TimeoutException.php new file mode 100644 index 000000000..7f03ba00a --- /dev/null +++ b/deps/vendor/react/promise-timer/src/TimeoutException.php @@ -0,0 +1,35 @@ +timeout = (float) $timeout; + } + + /** + * Get the timeout value in seconds. + * + * @return float + */ + public function getTimeout() + { + return $this->timeout; + } +} diff --git a/deps/vendor/react/promise-timer/src/functions.php b/deps/vendor/react/promise-timer/src/functions.php new file mode 100644 index 000000000..43665b2b9 --- /dev/null +++ b/deps/vendor/react/promise-timer/src/functions.php @@ -0,0 +1,335 @@ +then(function ($value) { + * // the operation finished within 10.0 seconds + * }); + * ``` + * + * A more complete example could look like this: + * + * ```php + * $promise = accessSomeRemoteResource(); + * React\Promise\Timer\timeout($promise, 10.0)->then( + * function ($value) { + * // the operation finished within 10.0 seconds + * }, + * function ($error) { + * if ($error instanceof React\Promise\Timer\TimeoutException) { + * // the operation has failed due to a timeout + * } else { + * // the input operation has failed due to some other error + * } + * } + * ); + * ``` + * + * Or if you're using [react/promise v2.2.0](https://github.com/reactphp/promise) or up: + * + * ```php + * React\Promise\Timer\timeout($promise, 10.0) + * ->then(function ($value) { + * // the operation finished within 10.0 seconds + * }) + * ->otherwise(function (React\Promise\Timer\TimeoutException $error) { + * // the operation has failed due to a timeout + * }) + * ->otherwise(function ($error) { + * // the input operation has failed due to some other error + * }) + * ; + * ``` + * + * As discussed above, the [`timeout()`](#timeout) function will take care of + * the underlying operation if it takes *too long*. In this case, you can be + * sure the resulting promise will always be rejected with a + * [`TimeoutException`](#timeoutexception). On top of this, the function will + * try to *cancel* the underlying operation. Responsibility for this + * cancellation logic is left up to the underlying operation. + * + * - A common use case involves cleaning up any resources like open network + * sockets or file handles or terminating external processes or timers. + * + * - If the given input `$promise` does not support cancellation, then this is a + * NO-OP. This means that while the resulting promise will still be rejected, + * the underlying input `$promise` may still be pending and can hence continue + * consuming resources + * + * On top of this, the returned promise is implemented in such a way that it can + * be cancelled when it is still pending. Cancelling a pending promise will + * cancel the underlying operation. As discussed above, responsibility for this + * cancellation logic is left up to the underlying operation. + * + * ```php + * $promise = accessSomeRemoteResource(); + * $timeout = React\Promise\Timer\timeout($promise, 10.0); + * + * $timeout->cancel(); + * ``` + * + * For more details on the promise cancellation, please refer to the + * [Promise documentation](https://github.com/reactphp/promise#cancellablepromiseinterface). + * + * If you want to wait for multiple promises to resolve, you can use the normal + * promise primitives like this: + * + * ```php + * $promises = array( + * accessSomeRemoteResource(), + * accessSomeRemoteResource(), + * accessSomeRemoteResource() + * ); + * + * $promise = React\Promise\all($promises); + * + * React\Promise\Timer\timeout($promise, 10)->then(function ($values) { + * // *all* promises resolved + * }); + * ``` + * + * The applies to all promise collection primitives alike, i.e. `all()`, + * `race()`, `any()`, `some()` etc. + * + * For more details on the promise primitives, please refer to the + * [Promise documentation](https://github.com/reactphp/promise#functions). + * + * @param PromiseInterface $promise + * @param float $time + * @param ?LoopInterface $loop + * @return PromiseInterface + */ +function timeout(PromiseInterface $promise, $time, LoopInterface $loop = null) +{ + // cancelling this promise will only try to cancel the input promise, + // thus leaving responsibility to the input promise. + $canceller = null; + if ($promise instanceof CancellablePromiseInterface || (!\interface_exists('React\Promise\CancellablePromiseInterface') && \method_exists($promise, 'cancel'))) { + // pass promise by reference to clean reference after cancellation handler + // has been invoked once in order to avoid garbage references in call stack. + $canceller = function () use (&$promise) { + $promise->cancel(); + $promise = null; + }; + } + + if ($loop === null) { + $loop = Loop::get(); + } + + return new Promise(function ($resolve, $reject) use ($loop, $time, $promise) { + $timer = null; + $promise = $promise->then(function ($v) use (&$timer, $loop, $resolve) { + if ($timer) { + $loop->cancelTimer($timer); + } + $timer = false; + $resolve($v); + }, function ($v) use (&$timer, $loop, $reject) { + if ($timer) { + $loop->cancelTimer($timer); + } + $timer = false; + $reject($v); + }); + + // promise already resolved => no need to start timer + if ($timer === false) { + return; + } + + // start timeout timer which will cancel the input promise + $timer = $loop->addTimer($time, function () use ($time, &$promise, $reject) { + $reject(new TimeoutException($time, 'Timed out after ' . $time . ' seconds')); + + // try to invoke cancellation handler of input promise and then clean + // reference in order to avoid garbage references in call stack. + if ($promise instanceof CancellablePromiseInterface || (!\interface_exists('React\Promise\CancellablePromiseInterface') && \method_exists($promise, 'cancel'))) { + $promise->cancel(); + } + $promise = null; + }); + }, $canceller); +} + +/** + * Create a new promise that resolves in `$time` seconds. + * + * ```php + * React\Promise\Timer\sleep(1.5)->then(function () { + * echo 'Thanks for waiting!' . PHP_EOL; + * }); + * ``` + * + * Internally, the given `$time` value will be used to start a timer that will + * resolve the promise once it triggers. This implies that if you pass a really + * small (or negative) value, it will still start a timer and will thus trigger + * at the earliest possible time in the future. + * + * This function takes an optional `LoopInterface|null $loop` parameter that can be used to + * pass the event loop instance to use. You can use a `null` value here in order to + * use the [default loop](https://github.com/reactphp/event-loop#loop). This value + * SHOULD NOT be given unless you're sure you want to explicitly use a given event + * loop instance. + * + * The returned promise is implemented in such a way that it can be cancelled + * when it is still pending. Cancelling a pending promise will reject its value + * with a `RuntimeException` and clean up any pending timers. + * + * ```php + * $timer = React\Promise\Timer\sleep(2.0); + * + * $timer->cancel(); + * ``` + * + * @param float $time + * @param ?LoopInterface $loop + * @return PromiseInterface + */ +function sleep($time, LoopInterface $loop = null) +{ + if ($loop === null) { + $loop = Loop::get(); + } + + $timer = null; + return new Promise(function ($resolve) use ($loop, $time, &$timer) { + // resolve the promise when the timer fires in $time seconds + $timer = $loop->addTimer($time, function () use ($resolve) { + $resolve(); + }); + }, function () use (&$timer, $loop) { + // cancelling this promise will cancel the timer, clean the reference + // in order to avoid garbage references in call stack and then reject. + $loop->cancelTimer($timer); + $timer = null; + + throw new \RuntimeException('Timer cancelled'); + }); +} + +/** + * [Deprecated] Create a new promise that resolves in `$time` seconds with the `$time` as the fulfillment value. + * + * ```php + * React\Promise\Timer\resolve(1.5)->then(function ($time) { + * echo 'Thanks for waiting ' . $time . ' seconds' . PHP_EOL; + * }); + * ``` + * + * Internally, the given `$time` value will be used to start a timer that will + * resolve the promise once it triggers. This implies that if you pass a really + * small (or negative) value, it will still start a timer and will thus trigger + * at the earliest possible time in the future. + * + * This function takes an optional `LoopInterface|null $loop` parameter that can be used to + * pass the event loop instance to use. You can use a `null` value here in order to + * use the [default loop](https://github.com/reactphp/event-loop#loop). This value + * SHOULD NOT be given unless you're sure you want to explicitly use a given event + * loop instance. + * + * The returned promise is implemented in such a way that it can be cancelled + * when it is still pending. Cancelling a pending promise will reject its value + * with a `RuntimeException` and clean up any pending timers. + * + * ```php + * $timer = React\Promise\Timer\resolve(2.0); + * + * $timer->cancel(); + * ``` + * + * @param float $time + * @param ?LoopInterface $loop + * @return PromiseInterface + * @deprecated 1.8.0 See `sleep()` instead + * @see sleep() + */ +function resolve($time, LoopInterface $loop = null) +{ + return sleep($time, $loop)->then(function() use ($time) { + return $time; + }); +} + +/** + * [Deprecated] Create a new promise which rejects in `$time` seconds with a `TimeoutException`. + * + * ```php + * React\Promise\Timer\reject(2.0)->then(null, function (React\Promise\Timer\TimeoutException $e) { + * echo 'Rejected after ' . $e->getTimeout() . ' seconds ' . PHP_EOL; + * }); + * ``` + * + * Internally, the given `$time` value will be used to start a timer that will + * reject the promise once it triggers. This implies that if you pass a really + * small (or negative) value, it will still start a timer and will thus trigger + * at the earliest possible time in the future. + * + * This function takes an optional `LoopInterface|null $loop` parameter that can be used to + * pass the event loop instance to use. You can use a `null` value here in order to + * use the [default loop](https://github.com/reactphp/event-loop#loop). This value + * SHOULD NOT be given unless you're sure you want to explicitly use a given event + * loop instance. + * + * The returned promise is implemented in such a way that it can be cancelled + * when it is still pending. Cancelling a pending promise will reject its value + * with a `RuntimeException` and clean up any pending timers. + * + * ```php + * $timer = React\Promise\Timer\reject(2.0); + * + * $timer->cancel(); + * ``` + * + * @param float $time + * @param LoopInterface $loop + * @return PromiseInterface + * @deprecated 1.8.0 See `sleep()` instead + * @see sleep() + */ +function reject($time, LoopInterface $loop = null) +{ + return sleep($time, $loop)->then(function () use ($time) { + throw new TimeoutException($time, 'Timer expired after ' . $time . ' seconds'); + }); +} diff --git a/deps/vendor/react/promise-timer/src/functions_include.php b/deps/vendor/react/promise-timer/src/functions_include.php new file mode 100644 index 000000000..1d5673aed --- /dev/null +++ b/deps/vendor/react/promise-timer/src/functions_include.php @@ -0,0 +1,7 @@ +otherwise(function (OverflowException|UnderflowException $e) { + echo 'Error: ' . $e->getMessage() . PHP_EOL; + }); + ``` -This update involves some major new features and a minor BC break over the -`v2.0.0` release. We've tried hard to avoid BC breaks where possible and -minimize impact otherwise. We expect that most consumers of this package will be -affected by BC breaks, but updating should take no longer than a few minutes. -See below for more details: + * Feature: Support intersection types (PHP 8.1+). + (#195 by @bzikarsky) -* BC break: PHP 8.1+ recommended, PHP 7.1+ required. - (#138 and #149 by @WyriHaximus) + ```php + $promise->otherwise(function (OverflowException&CacheException $e) { + echo 'Error: ' . $e->getMessage() . PHP_EOL; + }); + ``` -* Feature / BC break: The `PromiseInterface` now includes the functionality of the old ~~`ExtendedPromiseInterface`~~ and ~~`CancellablePromiseInterface`~~. - Each promise now always includes the `then()`, `catch()`, `finally()` and `cancel()` methods. - The new `catch()` and `finally()` methods replace the deprecated ~~`otherwise()`~~ and ~~`always()`~~ methods which continue to exist for BC reasons. - The old ~~`ExtendedPromiseInterface`~~ and ~~`CancellablePromiseInterface`~~ are no longer needed and have been removed as a consequence. - (#75 by @jsor and #208 by @clue and @WyriHaximus) + * Improve test suite, use GitHub actions for continuous integration (CI), + update to PHPUnit 9, and add full core team to the license. + (#174, #183, #186, and #201 by @SimonFrings and #211 by @clue) - ```php - // old (multiple interfaces may or may not be implemented) - assert($promise instanceof PromiseInterface); - assert(method_exists($promise, 'then')); - if ($promise instanceof ExtendedPromiseInterface) { assert(method_exists($promise, 'otherwise')); } - if ($promise instanceof ExtendedPromiseInterface) { assert(method_exists($promise, 'always')); } - if ($promise instanceof CancellablePromiseInterface) { assert(method_exists($promise, 'cancel')); } - - // new (single PromiseInterface with all methods) - assert($promise instanceof PromiseInterface); - assert(method_exists($promise, 'then')); - assert(method_exists($promise, 'catch')); - assert(method_exists($promise, 'finally')); - assert(method_exists($promise, 'cancel')); - ``` +* 2.8.0 (2020-05-12) -* Feature / BC break: Improve type safety of promises. Require `mixed` fulfillment value argument and `Throwable` (or `Exception`) as rejection reason. - Add PHPStan template types to ensure strict types for `resolve(T $value): PromiseInterface` and `reject(Throwable $reason): PromiseInterface`. - It is no longer possible to resolve a promise without a value (use `null` instead) or reject a promise without a reason (use `Throwable` instead). - (#93, #141 and #142 by @jsor, #138, #149 and #247 by @WyriHaximus and #213 and #246 by @clue) + * Mark `FulfilledPromise`, `RejectedPromise` and `LazyPromise` as deprecated for Promise v2 (and remove for Promise v3). + (#143 and #165 by @clue) - ```php - // old (arguments used to be optional) - $promise = resolve(); - $promise = reject(); - - // new (already supported before) - $promise = resolve(null); - $promise = reject(new RuntimeException()); - ``` + ```php + // deprecated + $fulfilled = new React\Promise\FulfilledPromise($value); + $rejected = new React\Promise\RejectedPromise($reason); -* Feature / BC break: Report all unhandled rejections by default and remove ~~`done()`~~ method. - Add new `set_rejection_handler()` function to set the global rejection handler for unhandled promise rejections. - (#248, #249 and #224 by @clue) + // recommended alternatives + $fulfilled = React\Promise\resolve($value); + $rejected = React\Promise\reject($reason); + ``` - ```php - // Unhandled promise rejection with RuntimeException: Unhandled in example.php:2 - reject(new RuntimeException('Unhandled')); - ``` + * Fix: Fix checking whether cancellable promise is an object and avoid possible warning. + (#168 by @smscr and @jsor) -* BC break: Remove all deprecated APIs and reduce API surface. - Remove ~~`some()`~~, ~~`map()`~~, ~~`reduce()`~~ functions, use `any()` and `all()` functions instead. - Remove internal ~~`FulfilledPromise`~~ and ~~`RejectedPromise`~~ classes, use `resolve()` and `reject()` functions instead. - Remove legacy promise progress API (deprecated third argument to `then()` method) and deprecated ~~`LazyPromise`~~ class. - (#32 and #98 by @jsor and #164, #219 and #220 by @clue) + * Improve documentation and add docblocks to functions and interfaces. + (#135 by @CharlotteDunois) -* BC break: Make all classes final to encourage composition over inheritance. - (#80 by @jsor) + * Add `.gitattributes` to exclude dev files from exports. + (#154 by @reedy) -* Feature / BC break: Require `array` (or `iterable`) type for `all()` + `race()` + `any()` functions and bring in line with ES6 specification. - These functions now require a single argument with a variable number of promises or values as input. - (#225 by @clue and #35 by @jsor) + * Improve test suite, run tests on PHP 7.4 and update PHPUnit test setup. + (#163 by @clue) -* Fix / BC break: Fix `race()` to return a forever pending promise when called with an empty `array` (or `iterable`) and bring in line with ES6 specification. - (#83 by @jsor and #225 by @clue) +* 2.7.1 (2018-01-07) -* Minor performance improvements by initializing `Deferred` in the constructor and avoiding `call_user_func()` calls. - (#151 by @WyriHaximus and #171 by @Kubo2) + * Fix: file_exists warning when resolving with long strings. + (#130 by @sbesselsen) + * Improve performance by prefixing all global functions calls with \ to skip the look up and resolve process and go straight to the global function. + (#133 by @WyriHaximus) -* Minor documentation improvements. - (#110 by @seregazhuk, #132 by @CharlotteDunois, #145 by @danielecr, #178 by @WyriHaximus, #189 by @srdante, #212 by @clue, #214, #239 and #243 by @SimonFrings and #231 by @nhedger) +* 2.7.0 (2018-06-13) -The following changes had to be ported to this release due to our branching -strategy, but also appeared in the [`2.x` branch](https://github.com/reactphp/promise/tree/2.x): + * Feature: Improve memory consumption for pending promises by using static internal callbacks without binding to self. + (#124 by @clue) -* Feature: Support union types and address deprecation of `ReflectionType::getClass()` (PHP 8+). - (#197 by @cdosoftei and @SimonFrings) +* 2.6.0 (2018-06-11) -* Feature: Support intersection types (PHP 8.1+). - (#209 by @bzikarsky) + * Feature: Significantly improve memory consumption and performance by only passing resolver args + to resolver and canceller if callback requires them. Also use static callbacks without + binding to promise, clean up canceller function reference when they are no longer + needed and hide resolver and canceller references from call stack on PHP 7+. + (#113, #115, #116, #117, #118, #119 and #123 by @clue) -* Feature: Support DNS types (PHP 8.2+). - (#236 by @nhedger) + These changes combined mean that rejecting promises with an `Exception` should + no longer cause any internal circular references which could cause some unexpected + memory growth in previous versions. By explicitly avoiding and explicitly + cleaning up said references, we can avoid relying on PHP's circular garbage collector + to kick in which significantly improves performance when rejecting many promises. -* Feature: Port all memory improvements from `2.x` to `3.x`. - (#150 by @clue and @WyriHaximus) + * Mark legacy progress support / notification API as deprecated + (#112 by @clue) -* Fix: Fix checking whether cancellable promise is an object and avoid possible warning. - (#161 by @smscr) + * Recommend rejecting promises by throwing an exception + (#114 by @jsor) -* Improve performance by prefixing all global functions calls with \ to skip the look up and resolve process and go straight to the global function. - (#134 by @WyriHaximus) + * Improve documentation to properly instantiate LazyPromise + (#121 by @holtkamp) -* Improve test suite, update PHPUnit and PHP versions and add `.gitattributes` to exclude dev files from exports. - (#107 by @carusogabriel, #148 and #234 by @WyriHaximus, #153 by @reedy, #162, #230 and #240 by @clue, #173, #177, #185 and #199 by @SimonFrings, #193 by @woodongwong and #210 by @bzikarsky) - -The following changes were originally planned for this release but later reverted -and are not part of the final release: + * Follower cancellation propagation was originally planned for this release + but has been reverted for now and is planned for a future release. + (#99 by @jsor and #122 by @clue) -* Add iterative callback queue handler to avoid recursion (later removed to improve Fiber support). - (#28, #82 and #86 by @jsor, #158 by @WyriHaximus and #229 and #238 by @clue) +* 2.5.1 (2017-03-25) -* Trigger an `E_USER_ERROR` instead of throwing an exception from `done()` (later removed entire `done()` method to globally report unhandled rejections). - (#97 by @jsor and #224 and #248 by @clue) + * Fix circular references when resolving with a promise which follows + itself (#94). -* Add type declarations for `some()` (later removed entire `some()` function). - (#172 by @WyriHaximus and #219 by @clue) +* 2.5.0 (2016-12-22) -## 2.0.0 (2013-12-10) + * Revert automatic cancellation of pending collection promises once the + output promise resolves. This was introduced in 42d86b7 (PR #36, released + in [v2.3.0](https://github.com/reactphp/promise/releases/tag/v2.3.0)) and + was both unintended and backward incompatible. -See [`2.x` CHANGELOG](https://github.com/reactphp/promise/blob/2.x/CHANGELOG.md) for more details. + If you need automatic cancellation, you can use something like: -## 1.0.0 (2012-11-07) + ```php + function allAndCancel(array $promises) + { + return \React\Promise\all($promises) + ->always(function() use ($promises) { + foreach ($promises as $promise) { + if ($promise instanceof \React\Promise\CancellablePromiseInterface) { + $promise->cancel(); + } + } + }); + } + ``` + * `all()` and `map()` functions now preserve the order of the array (#77). + * Fix circular references when resolving a promise with itself (#71). -See [`1.x` CHANGELOG](https://github.com/reactphp/promise/blob/1.x/CHANGELOG.md) for more details. +* 2.4.1 (2016-05-03) + + * Fix `some()` not cancelling pending promises when too much input promises + reject (16ff799). + +* 2.4.0 (2016-03-31) + + * Support foreign thenables in `resolve()`. + Any object that provides a `then()` method is now assimilated to a trusted + promise that follows the state of this thenable (#52). + * Fix `some()` and `any()` for input arrays containing not enough items + (#34). + +* 2.3.0 (2016-03-24) + + * Allow cancellation of promises returned by functions working on promise + collections (#36). + * Handle `\Throwable` in the same way as `\Exception` (#51 by @joshdifabio). + +* 2.2.2 (2016-02-26) + + * Fix cancellation handlers called multiple times (#47 by @clue). + +* 2.2.1 (2015-07-03) + + * Fix stack error when resolving a promise in its own fulfillment or + rejection handlers. + +* 2.2.0 (2014-12-30) + + * Introduce new `ExtendedPromiseInterface` implemented by all promises. + * Add new `done()` method (part of the `ExtendedPromiseInterface`). + * Add new `otherwise()` method (part of the `ExtendedPromiseInterface`). + * Add new `always()` method (part of the `ExtendedPromiseInterface`). + * Add new `progress()` method (part of the `ExtendedPromiseInterface`). + * Rename `Deferred::progress` to `Deferred::notify` to avoid confusion with + `ExtendedPromiseInterface::progress` (a `Deferred::progress` alias is + still available for backward compatibility) + * `resolve()` now always returns a `ExtendedPromiseInterface`. + +* 2.1.0 (2014-10-15) + + * Introduce new `CancellablePromiseInterface` implemented by all promises. + * Add new `cancel()` method (part of the `CancellablePromiseInterface`). + +* 2.0.0 (2013-12-10) + + New major release. The goal is to streamline the API and to make it more + compliant with other promise libraries and especially with the new upcoming + [ES6 promises specification](https://github.com/domenic/promises-unwrapping/). + + * Add standalone Promise class. + * Add new `race()` function. + * BC break: Bump minimum PHP version to PHP 5.4. + * BC break: Remove `ResolverInterface` and `PromiseInterface` from + `Deferred`. + * BC break: Change signature of `PromiseInterface`. + * BC break: Remove `When` and `Util` classes and move static methods to + functions. + * BC break: `FulfilledPromise` and `RejectedPromise` now throw an exception + when initialized with a promise instead of a value/reason. + * BC break: `Deferred::resolve()` and `Deferred::reject()` no longer return + a promise. diff --git a/deps/vendor/react/promise/README.md b/deps/vendor/react/promise/README.md index 2108d982e..d904a1d8f 100644 --- a/deps/vendor/react/promise/README.md +++ b/deps/vendor/react/promise/README.md @@ -4,8 +4,7 @@ Promise A lightweight implementation of [CommonJS Promises/A](http://wiki.commonjs.org/wiki/Promises/A) for PHP. -[![CI status](https://github.com/reactphp/promise/workflows/CI/badge.svg)](https://github.com/reactphp/promise/actions) -[![installs on Packagist](https://img.shields.io/packagist/dt/react/promise?color=blue&label=installs%20on%20Packagist)](https://packagist.org/packages/react/promise) +[![CI status](https://github.com/reactphp/promise/workflows/CI/badge.svg?branch=2.x)](https://github.com/reactphp/promise/actions) Table of Contents ----------------- @@ -19,31 +18,41 @@ Table of Contents * [Deferred::promise()](#deferredpromise) * [Deferred::resolve()](#deferredresolve) * [Deferred::reject()](#deferredreject) + * [Deferred::notify()](#deferrednotify) * [PromiseInterface](#promiseinterface) * [PromiseInterface::then()](#promiseinterfacethen) - * [PromiseInterface::catch()](#promiseinterfacecatch) - * [PromiseInterface::finally()](#promiseinterfacefinally) - * [PromiseInterface::cancel()](#promiseinterfacecancel) - * [~~PromiseInterface::otherwise()~~](#promiseinterfaceotherwise) - * [~~PromiseInterface::always()~~](#promiseinterfacealways) + * [ExtendedPromiseInterface](#extendedpromiseinterface) + * [ExtendedPromiseInterface::done()](#extendedpromiseinterfacedone) + * [ExtendedPromiseInterface::otherwise()](#extendedpromiseinterfaceotherwise) + * [ExtendedPromiseInterface::always()](#extendedpromiseinterfacealways) + * [ExtendedPromiseInterface::progress()](#extendedpromiseinterfaceprogress) + * [CancellablePromiseInterface](#cancellablepromiseinterface) + * [CancellablePromiseInterface::cancel()](#cancellablepromiseinterfacecancel) * [Promise](#promise-2) + * [FulfilledPromise](#fulfilledpromise) + * [RejectedPromise](#rejectedpromise) + * [LazyPromise](#lazypromise) * [Functions](#functions) * [resolve()](#resolve) * [reject()](#reject) * [all()](#all) * [race()](#race) * [any()](#any) - * [set_rejection_handler()](#set_rejection_handler) + * [some()](#some) + * [map()](#map) + * [reduce()](#reduce) + * [PromisorInterface](#promisorinterface) 4. [Examples](#examples) * [How to use Deferred](#how-to-use-deferred) * [How promise forwarding works](#how-promise-forwarding-works) * [Resolution forwarding](#resolution-forwarding) * [Rejection forwarding](#rejection-forwarding) * [Mixed resolution and rejection forwarding](#mixed-resolution-and-rejection-forwarding) + * [Progress event forwarding](#progress-event-forwarding) + * [done() vs. then()](#done-vs-then) 5. [Install](#install) -6. [Tests](#tests) -7. [Credits](#credits) -8. [License](#license) +6. [Credits](#credits) +7. [License](#license) Introduction ------------ @@ -55,7 +64,7 @@ It also provides several other useful promise-related concepts, such as joining multiple promises and mapping and reducing collections of promises. If you've never heard about promises before, -[read this first](https://gist.github.com/domenic/3889970). +[read this first](https://gist.github.com/3889970). Concepts -------- @@ -85,14 +94,17 @@ $deferred = new React\Promise\Deferred(); $promise = $deferred->promise(); -$deferred->resolve(mixed $value); -$deferred->reject(\Throwable $reason); +$deferred->resolve(mixed $value = null); +$deferred->reject(mixed $reason = null); +$deferred->notify(mixed $update = null); ``` The `promise` method returns the promise of the deferred. The `resolve` and `reject` methods control the state of the deferred. +The deprecated `notify` method is for progress notification. + The constructor of the `Deferred` accepts an optional `$canceller` argument. See [Promise](#promise-2) for more information. @@ -108,7 +120,7 @@ keeping the authority to modify its state to yourself. #### Deferred::resolve() ```php -$deferred->resolve(mixed $value); +$deferred->resolve(mixed $value = null); ``` Resolves the promise returned by `promise()`. All consumers are notified by @@ -118,12 +130,10 @@ having `$onFulfilled` (which they registered via `$promise->then()`) called with If `$value` itself is a promise, the promise will transition to the state of this promise once it is resolved. -See also the [`resolve()` function](#resolve). - #### Deferred::reject() ```php -$deferred->reject(\Throwable $reason); +$deferred->reject(mixed $reason = null); ``` Rejects the promise returned by `promise()`, signalling that the deferred's @@ -131,14 +141,27 @@ computation failed. All consumers are notified by having `$onRejected` (which they registered via `$promise->then()`) called with `$reason`. -See also the [`reject()` function](#reject). +If `$reason` itself is a promise, the promise will be rejected with the outcome +of this promise regardless whether it fulfills or rejects. + +#### Deferred::notify() + +> Deprecated in v2.6.0: Progress support is deprecated and should not be used anymore. + +```php +$deferred->notify(mixed $update = null); +``` + +Triggers progress notifications, to indicate to consumers that the computation +is making progress toward its result. + +All consumers are notified by having `$onProgress` (which they registered via +`$promise->then()`) called with `$update`. ### PromiseInterface The promise interface provides the common interface for all promise implementations. -See [Promise](#promise-2) for the only public implementation exposed by this -package. A promise represents an eventual outcome, which is either fulfillment (success) and an associated value, or rejection (failure) and an associated reason. @@ -146,22 +169,32 @@ and an associated value, or rejection (failure) and an associated reason. Once in the fulfilled or rejected state, a promise becomes immutable. Neither its state nor its result (or error) can be modified. +#### Implementations + +* [Promise](#promise-2) +* [FulfilledPromise](#fulfilledpromise) (deprecated) +* [RejectedPromise](#rejectedpromise) (deprecated) +* [LazyPromise](#lazypromise) (deprecated) + #### PromiseInterface::then() ```php -$transformedPromise = $promise->then(callable $onFulfilled = null, callable $onRejected = null); +$transformedPromise = $promise->then(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null); ``` Transforms a promise's value by applying a function to the promise's fulfillment or rejection value. Returns a new promise for the transformed result. -The `then()` method registers new fulfilled and rejection handlers with a promise -(all parameters are optional): +The `then()` method registers new fulfilled, rejection and progress handlers +with a promise (all parameters are optional): * `$onFulfilled` will be invoked once the promise is fulfilled and passed the result as the first argument. * `$onRejected` will be invoked once the promise is rejected and passed the reason as the first argument. + * `$onProgress` (deprecated) will be invoked whenever the producer of the promise + triggers progress notifications and passed a single argument (whatever it + wants) to indicate progress. It returns a new promise that will fulfill with the return value of either `$onFulfilled` or `$onRejected`, whichever is called, or will reject with @@ -174,16 +207,51 @@ the same call to `then()`: never both. 2. `$onFulfilled` and `$onRejected` will never be called more than once. + 3. `$onProgress` (deprecated) may be called multiple times. #### See also * [resolve()](#resolve) - Creating a resolved promise * [reject()](#reject) - Creating a rejected promise +* [ExtendedPromiseInterface::done()](#extendedpromiseinterfacedone) +* [done() vs. then()](#done-vs-then) + +### ExtendedPromiseInterface + +The ExtendedPromiseInterface extends the PromiseInterface with useful shortcut +and utility methods which are not part of the Promises/A specification. + +#### Implementations + +* [Promise](#promise-1) +* [FulfilledPromise](#fulfilledpromise) (deprecated) +* [RejectedPromise](#rejectedpromise) (deprecated) +* [LazyPromise](#lazypromise) (deprecated) + +#### ExtendedPromiseInterface::done() + +```php +$promise->done(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null); +``` -#### PromiseInterface::catch() +Consumes the promise's ultimate value if the promise fulfills, or handles the +ultimate error. + +It will cause a fatal error if either `$onFulfilled` or `$onRejected` throw or +return a rejected promise. + +Since the purpose of `done()` is consumption rather than transformation, +`done()` always returns `null`. + +#### See also + +* [PromiseInterface::then()](#promiseinterfacethen) +* [done() vs. then()](#done-vs-then) + +#### ExtendedPromiseInterface::otherwise() ```php -$promise->catch(callable $onRejected); +$promise->otherwise(callable $onRejected); ``` Registers a rejection handler for promise. It is a shortcut for: @@ -197,19 +265,19 @@ only specific errors. ```php $promise - ->catch(function (\RuntimeException $reason) { + ->otherwise(function (\RuntimeException $reason) { // Only catch \RuntimeException instances // All other types of errors will propagate automatically }) - ->catch(function (\Throwable $reason) { + ->otherwise(function ($reason) { // Catch other errors - }); + )}; ``` -#### PromiseInterface::finally() +#### ExtendedPromiseInterface::always() ```php -$newPromise = $promise->finally(callable $onFulfilledOrRejected); +$newPromise = $promise->always(callable $onFulfilledOrRejected); ``` Allows you to execute "cleanup" type tasks in a promise chain. @@ -228,16 +296,16 @@ when the promise is either fulfilled or rejected. rejected promise, `$newPromise` will reject with the thrown exception or rejected promise's reason. -`finally()` behaves similarly to the synchronous finally statement. When combined -with `catch()`, `finally()` allows you to write code that is similar to the familiar +`always()` behaves similarly to the synchronous finally statement. When combined +with `otherwise()`, `always()` allows you to write code that is similar to the familiar synchronous catch/finally pair. Consider the following synchronous code: ```php try { - return doSomething(); -} catch (\Throwable $e) { + return doSomething(); +} catch(\Exception $e) { return handleError($e); } finally { cleanup(); @@ -249,47 +317,48 @@ written: ```php return doSomething() - ->catch('handleError') - ->finally('cleanup'); + ->otherwise('handleError') + ->always('cleanup'); ``` -#### PromiseInterface::cancel() +#### ExtendedPromiseInterface::progress() -``` php -$promise->cancel(); -``` +> Deprecated in v2.6.0: Progress support is deprecated and should not be used anymore. -The `cancel()` method notifies the creator of the promise that there is no -further interest in the results of the operation. +```php +$promise->progress(callable $onProgress); +``` -Once a promise is settled (either fulfilled or rejected), calling `cancel()` on -a promise has no effect. +Registers a handler for progress updates from promise. It is a shortcut for: -#### ~~PromiseInterface::otherwise()~~ +```php +$promise->then(null, null, $onProgress); +``` -> Deprecated since v3.0.0, see [`catch()`](#promiseinterfacecatch) instead. +### CancellablePromiseInterface -The `otherwise()` method registers a rejection handler for a promise. +A cancellable promise provides a mechanism for consumers to notify the creator +of the promise that they are not longer interested in the result of an +operation. -This method continues to exist only for BC reasons and to ease upgrading -between versions. It is an alias for: +#### CancellablePromiseInterface::cancel() -```php -$promise->catch($onRejected); +``` php +$promise->cancel(); ``` -#### ~~PromiseInterface::always()~~ - -> Deprecated since v3.0.0, see [`finally()`](#promiseinterfacefinally) instead. +The `cancel()` method notifies the creator of the promise that there is no +further interest in the results of the operation. -The `always()` method allows you to execute "cleanup" type tasks in a promise chain. +Once a promise is settled (either fulfilled or rejected), calling `cancel()` on +a promise has no effect. -This method continues to exist only for BC reasons and to ease upgrading -between versions. It is an alias for: +#### Implementations -```php -$promise->finally($onFulfilledOrRejected); -``` +* [Promise](#promise-1) +* [FulfilledPromise](#fulfilledpromise) (deprecated) +* [RejectedPromise](#rejectedpromise) (deprecated) +* [LazyPromise](#lazypromise) (deprecated) ### Promise @@ -297,14 +366,16 @@ Creates a promise whose state is controlled by the functions passed to `$resolver`. ```php -$resolver = function (callable $resolve, callable $reject) { +$resolver = function (callable $resolve, callable $reject, callable $notify) { // Do some work, possibly asynchronously, and then - // resolve or reject. + // resolve or reject. You can notify of progress events (deprecated) + // along the way if you want/need. $resolve($awesomeResult); // or throw new Exception('Promise rejected'); // or $resolve($anotherPromise); // or $reject($nastyError); + // or $notify($progressNotification); }; $canceller = function () { @@ -318,7 +389,7 @@ $promise = new React\Promise\Promise($resolver, $canceller); ``` The promise constructor receives a resolver function and an optional canceller -function which both will be called with two arguments: +function which both will be called with 3 arguments: * `$resolve($value)` - Primary function that seals the fate of the returned promise. Accepts either a non-promise value, or another promise. @@ -327,6 +398,7 @@ function which both will be called with two arguments: fate will be equivalent to that of `$otherPromise`. * `$reject($reason)` - Function that rejects the promise. It is recommended to just throw an exception instead of using `$reject()`. + * `$notify($update)` - Deprecated function that issues progress events for the promise. If the resolver or canceller throw an exception, the promise will be rejected with that thrown exception as the rejection reason. @@ -334,108 +406,108 @@ with that thrown exception as the rejection reason. The resolver function will be called immediately, the canceller function only once all consumers called the `cancel()` method of the promise. -### Functions +### FulfilledPromise -Useful functions for creating and joining collections of promises. +> Deprecated in v2.8.0: External usage of `FulfilledPromise` is deprecated, use `resolve()` instead. -All functions working on promise collections (like `all()`, `race()`, -etc.) support cancellation. This means, if you call `cancel()` on the returned -promise, all promises in the collection are cancelled. - -#### resolve() +Creates a already fulfilled promise. ```php -$promise = React\Promise\resolve(mixed $promiseOrValue); +$promise = React\Promise\FulfilledPromise($value); ``` -Creates a promise for the supplied `$promiseOrValue`. +Note, that `$value` **cannot** be a promise. It's recommended to use +[resolve()](#resolve) for creating resolved promises. -If `$promiseOrValue` is a value, it will be the resolution value of the -returned promise. - -If `$promiseOrValue` is a thenable (any object that provides a `then()` method), -a trusted promise that follows the state of the thenable is returned. +### RejectedPromise -If `$promiseOrValue` is a promise, it will be returned as is. +> Deprecated in v2.8.0: External usage of `RejectedPromise` is deprecated, use `reject()` instead. -The resulting `$promise` implements the [`PromiseInterface`](#promiseinterface) -and can be consumed like any other promise: +Creates a already rejected promise. ```php -$promise = React\Promise\resolve(42); - -$promise->then(function (int $result): void { - var_dump($result); -}, function (\Throwable $e): void { - echo 'Error: ' . $e->getMessage() . PHP_EOL; -}); +$promise = React\Promise\RejectedPromise($reason); ``` -#### reject() - -```php -$promise = React\Promise\reject(\Throwable $reason); -``` +Note, that `$reason` **cannot** be a promise. It's recommended to use +[reject()](#reject) for creating rejected promises. -Creates a rejected promise for the supplied `$reason`. +### LazyPromise -Note that the [`\Throwable`](https://www.php.net/manual/en/class.throwable.php) interface introduced in PHP 7 covers -both user land [`\Exception`](https://www.php.net/manual/en/class.exception.php)'s and -[`\Error`](https://www.php.net/manual/en/class.error.php) internal PHP errors. By enforcing `\Throwable` as reason to -reject a promise, any language error or user land exception can be used to reject a promise. +> Deprecated in v2.8.0: LazyPromise is deprecated and should not be used anymore. -The resulting `$promise` implements the [`PromiseInterface`](#promiseinterface) -and can be consumed like any other promise: +Creates a promise which will be lazily initialized by `$factory` once a consumer +calls the `then()` method. ```php -$promise = React\Promise\reject(new RuntimeException('Request failed')); +$factory = function () { + $deferred = new React\Promise\Deferred(); + + // Do some heavy stuff here and resolve the deferred once completed -$promise->then(function (int $result): void { - var_dump($result); -}, function (\Throwable $e): void { - echo 'Error: ' . $e->getMessage() . PHP_EOL; + return $deferred->promise(); +}; + +$promise = new React\Promise\LazyPromise($factory); + +// $factory will only be executed once we call then() +$promise->then(function ($value) { }); ``` -Note that rejected promises should always be handled similar to how any -exceptions should always be caught in a `try` + `catch` block. If you remove the -last reference to a rejected promise that has not been handled, it will -report an unhandled promise rejection: +### Functions + +Useful functions for creating, joining, mapping and reducing collections of +promises. + +All functions working on promise collections (like `all()`, `race()`, `some()` +etc.) support cancellation. This means, if you call `cancel()` on the returned +promise, all promises in the collection are cancelled. If the collection itself +is a promise which resolves to an array, this promise is also cancelled. + +#### resolve() ```php -function incorrect(): int -{ - $promise = React\Promise\reject(new RuntimeException('Request failed')); +$promise = React\Promise\resolve(mixed $promiseOrValue); +``` - // Commented out: No rejection handler registered here. - // $promise->then(null, function (\Throwable $e): void { /* ignore */ }); +Creates a promise for the supplied `$promiseOrValue`. - // Returning from a function will remove all local variable references, hence why - // this will report an unhandled promise rejection here. - return 42; -} +If `$promiseOrValue` is a value, it will be the resolution value of the +returned promise. -// Calling this function will log an error message plus its stack trace: -// Unhandled promise rejection with RuntimeException: Request failed in example.php:10 -incorrect(); +If `$promiseOrValue` is a thenable (any object that provides a `then()` method), +a trusted promise that follows the state of the thenable is returned. + +If `$promiseOrValue` is a promise, it will be returned as is. + +Note: The promise returned is always a promise implementing +[ExtendedPromiseInterface](#extendedpromiseinterface). If you pass in a custom +promise which only implements [PromiseInterface](#promiseinterface), this +promise will be assimilated to a extended promise following `$promiseOrValue`. + +#### reject() + +```php +$promise = React\Promise\reject(mixed $promiseOrValue); ``` -A rejected promise will be considered "handled" if you catch the rejection -reason with either the [`then()` method](#promiseinterfacethen), the -[`catch()` method](#promiseinterfacecatch), or the -[`finally()` method](#promiseinterfacefinally). Note that each of these methods -return a new promise that may again be rejected if you re-throw an exception. +Creates a rejected promise for the supplied `$promiseOrValue`. + +If `$promiseOrValue` is a value, it will be the rejection value of the +returned promise. -A rejected promise will also be considered "handled" if you abort the operation -with the [`cancel()` method](#promiseinterfacecancel) (which in turn would -usually reject the promise if it is still pending). +If `$promiseOrValue` is a promise, its completion value will be the rejected +value of the returned promise. -See also the [`set_rejection_handler()` function](#set_rejection_handler). +This can be useful in situations where you need to reject a promise without +throwing an exception. For example, it allows you to propagate a rejection with +the value of another promise. #### all() ```php -$promise = React\Promise\all(iterable $promisesOrValues); +$promise = React\Promise\all(array|React\Promise\PromiseInterface $promisesOrValues); ``` Returns a promise that will resolve only once all the items in @@ -446,19 +518,16 @@ will be an array containing the resolution values of each of the items in #### race() ```php -$promise = React\Promise\race(iterable $promisesOrValues); +$promise = React\Promise\race(array|React\Promise\PromiseInterface $promisesOrValues); ``` Initiates a competitive race that allows one winner. Returns a promise which is resolved in the same way the first settled promise resolves. -The returned promise will become **infinitely pending** if `$promisesOrValues` -contains 0 items. - #### any() ```php -$promise = React\Promise\any(iterable $promisesOrValues); +$promise = React\Promise\any(array|React\Promise\PromiseInterface $promisesOrValues); ``` Returns a promise that will resolve when any one of the items in @@ -466,52 +535,58 @@ Returns a promise that will resolve when any one of the items in will be the resolution value of the triggering item. The returned promise will only reject if *all* items in `$promisesOrValues` are -rejected. The rejection value will be a `React\Promise\Exception\CompositeException` -which holds all rejection reasons. The rejection reasons can be obtained with -`CompositeException::getThrowables()`. +rejected. The rejection value will be an array of all rejection reasons. The returned promise will also reject with a `React\Promise\Exception\LengthException` if `$promisesOrValues` contains 0 items. -#### set_rejection_handler() +#### some() ```php -React\Promise\set_rejection_handler(?callable $callback): ?callable; +$promise = React\Promise\some(array|React\Promise\PromiseInterface $promisesOrValues, integer $howMany); ``` -Sets the global rejection handler for unhandled promise rejections. +Returns a promise that will resolve when `$howMany` of the supplied items in +`$promisesOrValues` resolve. The resolution value of the returned promise +will be an array of length `$howMany` containing the resolution values of the +triggering items. + +The returned promise will reject if it becomes impossible for `$howMany` items +to resolve (that is, when `(count($promisesOrValues) - $howMany) + 1` items +reject). The rejection value will be an array of +`(count($promisesOrValues) - $howMany) + 1` rejection reasons. + +The returned promise will also reject with a `React\Promise\Exception\LengthException` +if `$promisesOrValues` contains less items than `$howMany`. + +#### map() -Note that rejected promises should always be handled similar to how any -exceptions should always be caught in a `try` + `catch` block. If you remove -the last reference to a rejected promise that has not been handled, it will -report an unhandled promise rejection. See also the [`reject()` function](#reject) -for more details. +```php +$promise = React\Promise\map(array|React\Promise\PromiseInterface $promisesOrValues, callable $mapFunc); +``` -The `?callable $callback` argument MUST be a valid callback function that -accepts a single `Throwable` argument or a `null` value to restore the -default promise rejection handler. The return value of the callback function -will be ignored and has no effect, so you SHOULD return a `void` value. The -callback function MUST NOT throw or the program will be terminated with a -fatal error. +Traditional map function, similar to `array_map()`, but allows input to contain +promises and/or values, and `$mapFunc` may return either a value or a promise. -The function returns the previous rejection handler or `null` if using the -default promise rejection handler. +The map function receives each item as argument, where item is a fully resolved +value of a promise or value in `$promisesOrValues`. -The default promise rejection handler will log an error message plus its stack -trace: +#### reduce() ```php -// Unhandled promise rejection with RuntimeException: Unhandled in example.php:2 -React\Promise\reject(new RuntimeException('Unhandled')); +$promise = React\Promise\reduce(array|React\Promise\PromiseInterface $promisesOrValues, callable $reduceFunc , $initialValue = null); ``` -The promise rejection handler may be used to use customize the log message or -write to custom log targets. As a rule of thumb, this function should only be -used as a last resort and promise rejections are best handled with either the -[`then()` method](#promiseinterfacethen), the -[`catch()` method](#promiseinterfacecatch), or the -[`finally()` method](#promiseinterfacefinally). -See also the [`reject()` function](#reject) for more details. +Traditional reduce function, similar to `array_reduce()`, but input may contain +promises and/or values, and `$reduceFunc` may return either a value or a +promise, *and* `$initialValue` may be a promise or a value for the starting +value. + +### PromisorInterface + +The `React\Promise\PromisorInterface` provides a common interface for objects +that provide a promise. `React\Promise\Deferred` implements it, but since it +is part of the public API anyone can implement it. Examples -------- @@ -524,7 +599,7 @@ function getAwesomeResultPromise() $deferred = new React\Promise\Deferred(); // Execute a Node.js-style function using the callback pattern - computeAwesomeResultAsynchronously(function (\Throwable $error, $result) use ($deferred) { + computeAwesomeResultAsynchronously(function ($error, $result) use ($deferred) { if ($error) { $deferred->reject($error); } else { @@ -541,8 +616,11 @@ getAwesomeResultPromise() function ($value) { // Deferred resolved, do something with $value }, - function (\Throwable $reason) { + function ($reason) { // Deferred rejected, do something with $reason + }, + function ($update) { + // Progress notification triggered, do something with $update } ); ``` @@ -610,17 +688,17 @@ $deferred->promise() ->then(function ($x) { throw new \Exception($x + 1); }) - ->catch(function (\Exception $x) { + ->otherwise(function (\Exception $x) { // Propagate the rejection throw $x; }) - ->catch(function (\Exception $x) { + ->otherwise(function (\Exception $x) { // Can also propagate by returning another rejection return React\Promise\reject( new \Exception($x->getMessage() + 1) ); }) - ->catch(function ($x) { + ->otherwise(function ($x) { echo 'Reject ' . $x->getMessage(); // 3 }); @@ -642,7 +720,7 @@ $deferred->promise() ->then(function ($x) { throw new \Exception($x + 1); }) - ->catch(function (\Exception $x) { + ->otherwise(function (\Exception $x) { // Handle the rejection, and don't propagate. // This is like catch without a rethrow return $x->getMessage() + 1; @@ -654,58 +732,132 @@ $deferred->promise() $deferred->resolve(1); // Prints "Mixed 4" ``` -Install -------- +#### Progress event forwarding -The recommended way to install this library is [through Composer](https://getcomposer.org/). -[New to Composer?](https://getcomposer.org/doc/00-intro.md) +> Deprecated in v2.6.0: Progress support is deprecated and should not be used anymore. -This project follows [SemVer](https://semver.org/). -This will install the latest supported version from this branch: +In the same way as resolution and rejection handlers, your progress handler +**MUST** return a progress event to be propagated to the next link in the chain. +If you return nothing, `null` will be propagated. -```bash -composer require react/promise:^3.2 -``` +Also in the same way as resolutions and rejections, if you don't register a +progress handler, the update will be propagated through. -See also the [CHANGELOG](CHANGELOG.md) for details about version upgrades. +If your progress handler throws an exception, the exception will be propagated +to the next link in the chain. The best thing to do is to ensure your progress +handlers do not throw exceptions. -This project aims to run on any platform and thus does not require any PHP -extensions and supports running on PHP 7.1 through current PHP 8+. -It's *highly recommended to use the latest supported PHP version* for this project. +This gives you the opportunity to transform progress events at each step in the +chain so that they are meaningful to the next step. It also allows you to choose +not to transform them, and simply let them propagate untransformed, by not +registering a progress handler. -We're committed to providing long-term support (LTS) options and to provide a -smooth upgrade path. If you're using an older PHP version, you may use the -[`2.x` branch](https://github.com/reactphp/promise/tree/2.x) (PHP 5.4+) or -[`1.x` branch](https://github.com/reactphp/promise/tree/1.x) (PHP 5.3+) which both -provide a compatible API but do not take advantage of newer language features. -You may target multiple versions at the same time to support a wider range of -PHP versions like this: +```php +$deferred = new React\Promise\Deferred(); -```bash -composer require "react/promise:^3 || ^2 || ^1" +$deferred->promise() + ->progress(function ($update) { + return $update + 1; + }) + ->progress(function ($update) { + echo 'Progress ' . $update; // 2 + }); + +$deferred->notify(1); // Prints "Progress 2" ``` -## Tests +### done() vs. then() -To run the test suite, you first need to clone this repo and then install all -dependencies [through Composer](https://getcomposer.org/): +The golden rule is: -```bash -composer install -``` + Either return your promise, or call done() on it. -To run the test suite, go to the project root and run: +At a first glance, `then()` and `done()` seem very similar. However, there are +important distinctions. -```bash -vendor/bin/phpunit +The intent of `then()` is to transform a promise's value and to pass or return +a new promise for the transformed value along to other parts of your code. + +The intent of `done()` is to consume a promise's value, transferring +responsibility for the value to your code. + +In addition to transforming a value, `then()` allows you to recover from, or +propagate intermediate errors. Any errors that are not handled will be caught +by the promise machinery and used to reject the promise returned by `then()`. + +Calling `done()` transfers all responsibility for errors to your code. If an +error (either a thrown exception or returned rejection) escapes the +`$onFulfilled` or `$onRejected` callbacks you provide to done, it will be +rethrown in an uncatchable way causing a fatal error. + +```php +function getJsonResult() +{ + return queryApi() + ->then( + // Transform API results to an object + function ($jsonResultString) { + return json_decode($jsonResultString); + }, + // Transform API errors to an exception + function ($jsonErrorString) { + $object = json_decode($jsonErrorString); + throw new ApiErrorException($object->errorMessage); + } + ); +} + +// Here we provide no rejection handler. If the promise returned has been +// rejected, the ApiErrorException will be thrown +getJsonResult() + ->done( + // Consume transformed object + function ($jsonResultObject) { + // Do something with $jsonResultObject + } + ); + +// Here we provide a rejection handler which will either throw while debugging +// or log the exception +getJsonResult() + ->done( + function ($jsonResultObject) { + // Do something with $jsonResultObject + }, + function (ApiErrorException $exception) { + if (isDebug()) { + throw $exception; + } else { + logException($exception); + } + } + ); ``` -On top of this, we use PHPStan on max level to ensure type safety across the project: +Note that if a rejection value is not an instance of `\Exception`, it will be +wrapped in an exception of the type `React\Promise\UnhandledRejectionException`. + +You can get the original rejection reason by calling `$exception->getReason()`. + +Install +------- + +The recommended way to install this library is [through Composer](https://getcomposer.org). +[New to Composer?](https://getcomposer.org/doc/00-intro.md) + +This project follows [SemVer](https://semver.org/). +This will install the latest supported version: ```bash -vendor/bin/phpstan +$ composer require react/promise:^2.9 ``` +See also the [CHANGELOG](CHANGELOG.md) for details about version upgrades. + +This project aims to run on any platform and thus does not require any PHP +extensions and supports running on legacy PHP 5.4 through current PHP 8+ and HHVM. +It's *highly recommended to use the latest supported PHP version* for this project. + Credits ------- diff --git a/deps/vendor/react/promise/composer.json b/deps/vendor/react/promise/composer.json index 5d1e27710..f933f1537 100644 --- a/deps/vendor/react/promise/composer.json +++ b/deps/vendor/react/promise/composer.json @@ -25,30 +25,21 @@ } ], "require": { - "php": ">=7.1.0" + "php": ">=5.4.0" }, "require-dev": { - "phpstan/phpstan": "1.10.39 || 1.4.10", - "phpunit/phpunit": "^9.6 || ^7.5" + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.36" }, "autoload": { "psr-4": { "React\\Promise\\": "src/" }, - "files": [ - "src/functions_include.php" - ] + "files": ["src/functions_include.php"] }, "autoload-dev": { "psr-4": { - "React\\Promise\\": [ - "tests/fixtures/", - "tests/" - ] - }, - "files": [ - "tests/Fiber.php" - ] + "React\\Promise\\": ["tests", "tests/fixtures"] + } }, "keywords": [ "promise", diff --git a/deps/vendor/react/promise/src/CancellablePromiseInterface.php b/deps/vendor/react/promise/src/CancellablePromiseInterface.php new file mode 100644 index 000000000..6b3a8c65d --- /dev/null +++ b/deps/vendor/react/promise/src/CancellablePromiseInterface.php @@ -0,0 +1,17 @@ +started) { return; @@ -23,10 +17,7 @@ public function __invoke(): void $this->drain(); } - /** - * @param mixed $cancellable - */ - public function enqueue($cancellable): void + public function enqueue($cancellable) { if (!\is_object($cancellable) || !\method_exists($cancellable, 'then') || !\method_exists($cancellable, 'cancel')) { return; @@ -39,17 +30,17 @@ public function enqueue($cancellable): void } } - private function drain(): void + private function drain() { - for ($i = \key($this->queue); isset($this->queue[$i]); $i++) { + for ($i = key($this->queue); isset($this->queue[$i]); $i++) { $cancellable = $this->queue[$i]; - assert(\method_exists($cancellable, 'cancel')); $exception = null; try { $cancellable->cancel(); } catch (\Throwable $exception) { + } catch (\Exception $exception) { } unset($this->queue[$i]); diff --git a/deps/vendor/react/promise/src/Deferred.php b/deps/vendor/react/promise/src/Deferred.php index 80b8fcfbd..3ca034b85 100644 --- a/deps/vendor/react/promise/src/Deferred.php +++ b/deps/vendor/react/promise/src/Deferred.php @@ -2,51 +2,64 @@ namespace React\Promise; -/** - * @template T - */ -final class Deferred +class Deferred implements PromisorInterface { - /** - * @var PromiseInterface - */ private $promise; - - /** @var callable(T):void */ private $resolveCallback; - - /** @var callable(\Throwable):void */ private $rejectCallback; + private $notifyCallback; + private $canceller; - /** - * @param (callable(callable(T):void,callable(\Throwable):void):void)|null $canceller - */ - public function __construct(?callable $canceller = null) + public function __construct(callable $canceller = null) { - $this->promise = new Promise(function ($resolve, $reject): void { - $this->resolveCallback = $resolve; - $this->rejectCallback = $reject; - }, $canceller); + $this->canceller = $canceller; } - /** - * @return PromiseInterface - */ - public function promise(): PromiseInterface + public function promise() { + if (null === $this->promise) { + $this->promise = new Promise(function ($resolve, $reject, $notify) { + $this->resolveCallback = $resolve; + $this->rejectCallback = $reject; + $this->notifyCallback = $notify; + }, $this->canceller); + $this->canceller = null; + } + return $this->promise; } + public function resolve($value = null) + { + $this->promise(); + + \call_user_func($this->resolveCallback, $value); + } + + public function reject($reason = null) + { + $this->promise(); + + \call_user_func($this->rejectCallback, $reason); + } + /** - * @param T $value + * @deprecated 2.6.0 Progress support is deprecated and should not be used anymore. + * @param mixed $update */ - public function resolve($value): void + public function notify($update = null) { - ($this->resolveCallback)($value); + $this->promise(); + + \call_user_func($this->notifyCallback, $update); } - public function reject(\Throwable $reason): void + /** + * @deprecated 2.2.0 + * @see Deferred::notify() + */ + public function progress($update = null) { - ($this->rejectCallback)($reason); + $this->notify($update); } } diff --git a/deps/vendor/react/promise/src/Exception/CompositeException.php b/deps/vendor/react/promise/src/Exception/CompositeException.php deleted file mode 100644 index 2e672a04a..000000000 --- a/deps/vendor/react/promise/src/Exception/CompositeException.php +++ /dev/null @@ -1,32 +0,0 @@ -throwables = $throwables; - } - - /** - * @return \Throwable[] - */ - public function getThrowables(): array - { - return $this->throwables; - } -} diff --git a/deps/vendor/react/promise/src/ExtendedPromiseInterface.php b/deps/vendor/react/promise/src/ExtendedPromiseInterface.php new file mode 100644 index 000000000..13b636917 --- /dev/null +++ b/deps/vendor/react/promise/src/ExtendedPromiseInterface.php @@ -0,0 +1,98 @@ +then(null, $onRejected); + * ``` + * + * Additionally, you can type hint the `$reason` argument of `$onRejected` to catch + * only specific errors. + * + * @param callable $onRejected + * @return ExtendedPromiseInterface + */ + public function otherwise(callable $onRejected); + + /** + * Allows you to execute "cleanup" type tasks in a promise chain. + * + * It arranges for `$onFulfilledOrRejected` to be called, with no arguments, + * when the promise is either fulfilled or rejected. + * + * * If `$promise` fulfills, and `$onFulfilledOrRejected` returns successfully, + * `$newPromise` will fulfill with the same value as `$promise`. + * * If `$promise` fulfills, and `$onFulfilledOrRejected` throws or returns a + * rejected promise, `$newPromise` will reject with the thrown exception or + * rejected promise's reason. + * * If `$promise` rejects, and `$onFulfilledOrRejected` returns successfully, + * `$newPromise` will reject with the same reason as `$promise`. + * * If `$promise` rejects, and `$onFulfilledOrRejected` throws or returns a + * rejected promise, `$newPromise` will reject with the thrown exception or + * rejected promise's reason. + * + * `always()` behaves similarly to the synchronous finally statement. When combined + * with `otherwise()`, `always()` allows you to write code that is similar to the familiar + * synchronous catch/finally pair. + * + * Consider the following synchronous code: + * + * ```php + * try { + * return doSomething(); + * } catch(\Exception $e) { + * return handleError($e); + * } finally { + * cleanup(); + * } + * ``` + * + * Similar asynchronous code (with `doSomething()` that returns a promise) can be + * written: + * + * ```php + * return doSomething() + * ->otherwise('handleError') + * ->always('cleanup'); + * ``` + * + * @param callable $onFulfilledOrRejected + * @return ExtendedPromiseInterface + */ + public function always(callable $onFulfilledOrRejected); + + /** + * Registers a handler for progress updates from promise. It is a shortcut for: + * + * ```php + * $promise->then(null, null, $onProgress); + * ``` + * + * @param callable $onProgress + * @return ExtendedPromiseInterface + * @deprecated 2.6.0 Progress support is deprecated and should not be used anymore. + */ + public function progress(callable $onProgress); +} diff --git a/deps/vendor/react/promise/src/FulfilledPromise.php b/deps/vendor/react/promise/src/FulfilledPromise.php new file mode 100644 index 000000000..147275277 --- /dev/null +++ b/deps/vendor/react/promise/src/FulfilledPromise.php @@ -0,0 +1,71 @@ +value = $value; + } + + public function then(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null) + { + if (null === $onFulfilled) { + return $this; + } + + try { + return resolve($onFulfilled($this->value)); + } catch (\Throwable $exception) { + return new RejectedPromise($exception); + } catch (\Exception $exception) { + return new RejectedPromise($exception); + } + } + + public function done(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null) + { + if (null === $onFulfilled) { + return; + } + + $result = $onFulfilled($this->value); + + if ($result instanceof ExtendedPromiseInterface) { + $result->done(); + } + } + + public function otherwise(callable $onRejected) + { + return $this; + } + + public function always(callable $onFulfilledOrRejected) + { + return $this->then(function ($value) use ($onFulfilledOrRejected) { + return resolve($onFulfilledOrRejected())->then(function () use ($value) { + return $value; + }); + }); + } + + public function progress(callable $onProgress) + { + return $this; + } + + public function cancel() + { + } +} diff --git a/deps/vendor/react/promise/src/Internal/FulfilledPromise.php b/deps/vendor/react/promise/src/Internal/FulfilledPromise.php deleted file mode 100644 index 8664ffdb6..000000000 --- a/deps/vendor/react/promise/src/Internal/FulfilledPromise.php +++ /dev/null @@ -1,89 +0,0 @@ - - */ -final class FulfilledPromise implements PromiseInterface -{ - /** @var T */ - private $value; - - /** - * @param T $value - * @throws \InvalidArgumentException - */ - public function __construct($value = null) - { - if ($value instanceof PromiseInterface) { - throw new \InvalidArgumentException('You cannot create React\Promise\FulfilledPromise with a promise. Use React\Promise\resolve($promiseOrValue) instead.'); - } - - $this->value = $value; - } - - /** - * @template TFulfilled - * @param ?(callable((T is void ? null : T)): (PromiseInterface|TFulfilled)) $onFulfilled - * @return PromiseInterface<($onFulfilled is null ? T : TFulfilled)> - */ - public function then(?callable $onFulfilled = null, ?callable $onRejected = null): PromiseInterface - { - if (null === $onFulfilled) { - return $this; - } - - try { - /** - * @var PromiseInterface|T $result - */ - $result = $onFulfilled($this->value); - return resolve($result); - } catch (\Throwable $exception) { - return new RejectedPromise($exception); - } - } - - public function catch(callable $onRejected): PromiseInterface - { - return $this; - } - - public function finally(callable $onFulfilledOrRejected): PromiseInterface - { - return $this->then(function ($value) use ($onFulfilledOrRejected): PromiseInterface { - return resolve($onFulfilledOrRejected())->then(function () use ($value) { - return $value; - }); - }); - } - - public function cancel(): void - { - } - - /** - * @deprecated 3.0.0 Use `catch()` instead - * @see self::catch() - */ - public function otherwise(callable $onRejected): PromiseInterface - { - return $this->catch($onRejected); - } - - /** - * @deprecated 3.0.0 Use `finally()` instead - * @see self::finally() - */ - public function always(callable $onFulfilledOrRejected): PromiseInterface - { - return $this->finally($onFulfilledOrRejected); - } -} diff --git a/deps/vendor/react/promise/src/Internal/RejectedPromise.php b/deps/vendor/react/promise/src/Internal/RejectedPromise.php deleted file mode 100644 index aa1dff308..000000000 --- a/deps/vendor/react/promise/src/Internal/RejectedPromise.php +++ /dev/null @@ -1,128 +0,0 @@ - - */ -final class RejectedPromise implements PromiseInterface -{ - /** @var \Throwable */ - private $reason; - - /** @var bool */ - private $handled = false; - - /** - * @param \Throwable $reason - */ - public function __construct(\Throwable $reason) - { - $this->reason = $reason; - } - - /** @throws void */ - public function __destruct() - { - if ($this->handled) { - return; - } - - $handler = set_rejection_handler(null); - if ($handler === null) { - $message = 'Unhandled promise rejection with ' . $this->reason; - - \error_log($message); - return; - } - - try { - $handler($this->reason); - } catch (\Throwable $e) { - \preg_match('/^([^:\s]++)(.*+)$/sm', (string) $e, $match); - \assert(isset($match[1], $match[2])); - $message = 'Fatal error: Uncaught ' . $match[1] . ' from unhandled promise rejection handler' . $match[2]; - - \error_log($message); - exit(255); - } - } - - /** - * @template TRejected - * @param ?callable $onFulfilled - * @param ?(callable(\Throwable): (PromiseInterface|TRejected)) $onRejected - * @return PromiseInterface<($onRejected is null ? never : TRejected)> - */ - public function then(?callable $onFulfilled = null, ?callable $onRejected = null): PromiseInterface - { - if (null === $onRejected) { - return $this; - } - - $this->handled = true; - - try { - return resolve($onRejected($this->reason)); - } catch (\Throwable $exception) { - return new RejectedPromise($exception); - } - } - - /** - * @template TThrowable of \Throwable - * @template TRejected - * @param callable(TThrowable): (PromiseInterface|TRejected) $onRejected - * @return PromiseInterface - */ - public function catch(callable $onRejected): PromiseInterface - { - if (!_checkTypehint($onRejected, $this->reason)) { - return $this; - } - - /** - * @var callable(\Throwable):(PromiseInterface|TRejected) $onRejected - */ - return $this->then(null, $onRejected); - } - - public function finally(callable $onFulfilledOrRejected): PromiseInterface - { - return $this->then(null, function (\Throwable $reason) use ($onFulfilledOrRejected): PromiseInterface { - return resolve($onFulfilledOrRejected())->then(function () use ($reason): PromiseInterface { - return new RejectedPromise($reason); - }); - }); - } - - public function cancel(): void - { - $this->handled = true; - } - - /** - * @deprecated 3.0.0 Use `catch()` instead - * @see self::catch() - */ - public function otherwise(callable $onRejected): PromiseInterface - { - return $this->catch($onRejected); - } - - /** - * @deprecated 3.0.0 Use `always()` instead - * @see self::always() - */ - public function always(callable $onFulfilledOrRejected): PromiseInterface - { - return $this->finally($onFulfilledOrRejected); - } -} diff --git a/deps/vendor/react/promise/src/LazyPromise.php b/deps/vendor/react/promise/src/LazyPromise.php new file mode 100644 index 000000000..bbe9293e1 --- /dev/null +++ b/deps/vendor/react/promise/src/LazyPromise.php @@ -0,0 +1,66 @@ +factory = $factory; + } + + public function then(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null) + { + return $this->promise()->then($onFulfilled, $onRejected, $onProgress); + } + + public function done(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null) + { + return $this->promise()->done($onFulfilled, $onRejected, $onProgress); + } + + public function otherwise(callable $onRejected) + { + return $this->promise()->otherwise($onRejected); + } + + public function always(callable $onFulfilledOrRejected) + { + return $this->promise()->always($onFulfilledOrRejected); + } + + public function progress(callable $onProgress) + { + return $this->promise()->progress($onProgress); + } + + public function cancel() + { + return $this->promise()->cancel(); + } + + /** + * @internal + * @see Promise::settle() + */ + public function promise() + { + if (null === $this->promise) { + try { + $this->promise = resolve(\call_user_func($this->factory)); + } catch (\Throwable $exception) { + $this->promise = new RejectedPromise($exception); + } catch (\Exception $exception) { + $this->promise = new RejectedPromise($exception); + } + } + + return $this->promise; + } +} diff --git a/deps/vendor/react/promise/src/Promise.php b/deps/vendor/react/promise/src/Promise.php index 4ac27007c..33759e6fe 100644 --- a/deps/vendor/react/promise/src/Promise.php +++ b/deps/vendor/react/promise/src/Promise.php @@ -2,34 +2,18 @@ namespace React\Promise; -use React\Promise\Internal\RejectedPromise; - -/** - * @template T - * @template-implements PromiseInterface - */ -final class Promise implements PromiseInterface +class Promise implements ExtendedPromiseInterface, CancellablePromiseInterface { - /** @var (callable(callable(T):void,callable(\Throwable):void):void)|null */ private $canceller; - - /** @var ?PromiseInterface */ private $result; - /** @var list):void> */ private $handlers = []; + private $progressHandlers = []; - /** @var int */ private $requiredCancelRequests = 0; + private $cancelRequests = 0; - /** @var bool */ - private $cancelled = false; - - /** - * @param callable(callable(T):void,callable(\Throwable):void):void $resolver - * @param (callable(callable(T):void,callable(\Throwable):void):void)|null $canceller - */ - public function __construct(callable $resolver, ?callable $canceller = null) + public function __construct(callable $resolver, callable $canceller = null) { $this->canceller = $canceller; @@ -41,14 +25,14 @@ public function __construct(callable $resolver, ?callable $canceller = null) $this->call($cb); } - public function then(?callable $onFulfilled = null, ?callable $onRejected = null): PromiseInterface + public function then(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null) { if (null !== $this->result) { - return $this->result->then($onFulfilled, $onRejected); + return $this->result->then($onFulfilled, $onRejected, $onProgress); } if (null === $this->canceller) { - return new static($this->resolver($onFulfilled, $onRejected)); + return new static($this->resolver($onFulfilled, $onRejected, $onProgress)); } // This promise has a canceller, so we create a new child promise which @@ -60,12 +44,9 @@ public function then(?callable $onFulfilled = null, ?callable $onRejected = null ++$parent->requiredCancelRequests; return new static( - $this->resolver($onFulfilled, $onRejected), - static function () use (&$parent): void { - assert($parent instanceof self); - --$parent->requiredCancelRequests; - - if ($parent->requiredCancelRequests <= 0) { + $this->resolver($onFulfilled, $onRejected, $onProgress), + static function () use (&$parent) { + if (++$parent->cancelRequests >= $parent->requiredCancelRequests) { $parent->cancel(); } @@ -74,116 +55,91 @@ static function () use (&$parent): void { ); } - /** - * @template TThrowable of \Throwable - * @template TRejected - * @param callable(TThrowable): (PromiseInterface|TRejected) $onRejected - * @return PromiseInterface - */ - public function catch(callable $onRejected): PromiseInterface + public function done(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null) + { + if (null !== $this->result) { + return $this->result->done($onFulfilled, $onRejected, $onProgress); + } + + $this->handlers[] = static function (ExtendedPromiseInterface $promise) use ($onFulfilled, $onRejected) { + $promise + ->done($onFulfilled, $onRejected); + }; + + if ($onProgress) { + $this->progressHandlers[] = $onProgress; + } + } + + public function otherwise(callable $onRejected) { - return $this->then(null, static function (\Throwable $reason) use ($onRejected) { + return $this->then(null, static function ($reason) use ($onRejected) { if (!_checkTypehint($onRejected, $reason)) { return new RejectedPromise($reason); } - /** - * @var callable(\Throwable):(PromiseInterface|TRejected) $onRejected - */ return $onRejected($reason); }); } - public function finally(callable $onFulfilledOrRejected): PromiseInterface + public function always(callable $onFulfilledOrRejected) { - return $this->then(static function ($value) use ($onFulfilledOrRejected): PromiseInterface { + return $this->then(static function ($value) use ($onFulfilledOrRejected) { return resolve($onFulfilledOrRejected())->then(function () use ($value) { return $value; }); - }, static function (\Throwable $reason) use ($onFulfilledOrRejected): PromiseInterface { - return resolve($onFulfilledOrRejected())->then(function () use ($reason): RejectedPromise { + }, static function ($reason) use ($onFulfilledOrRejected) { + return resolve($onFulfilledOrRejected())->then(function () use ($reason) { return new RejectedPromise($reason); }); }); } - public function cancel(): void + public function progress(callable $onProgress) { - $this->cancelled = true; - $canceller = $this->canceller; - $this->canceller = null; - - $parentCanceller = null; - - if (null !== $this->result) { - // Forward cancellation to rejected promise to avoid reporting unhandled rejection - if ($this->result instanceof RejectedPromise) { - $this->result->cancel(); - } - - // Go up the promise chain and reach the top most promise which is - // itself not following another promise - $root = $this->unwrap($this->result); - - // Return if the root promise is already resolved or a - // FulfilledPromise or RejectedPromise - if (!$root instanceof self || null !== $root->result) { - return; - } - - $root->requiredCancelRequests--; - - if ($root->requiredCancelRequests <= 0) { - $parentCanceller = [$root, 'cancel']; - } - } + return $this->then(null, null, $onProgress); + } - if (null !== $canceller) { - $this->call($canceller); + public function cancel() + { + if (null === $this->canceller || null !== $this->result) { + return; } - // For BC, we call the parent canceller after our own canceller - if ($parentCanceller) { - $parentCanceller(); - } - } + $canceller = $this->canceller; + $this->canceller = null; - /** - * @deprecated 3.0.0 Use `catch()` instead - * @see self::catch() - */ - public function otherwise(callable $onRejected): PromiseInterface - { - return $this->catch($onRejected); + $this->call($canceller); } - /** - * @deprecated 3.0.0 Use `finally()` instead - * @see self::finally() - */ - public function always(callable $onFulfilledOrRejected): PromiseInterface + private function resolver(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null) { - return $this->finally($onFulfilledOrRejected); - } + return function ($resolve, $reject, $notify) use ($onFulfilled, $onRejected, $onProgress) { + if ($onProgress) { + $progressHandler = static function ($update) use ($notify, $onProgress) { + try { + $notify($onProgress($update)); + } catch (\Throwable $e) { + $notify($e); + } catch (\Exception $e) { + $notify($e); + } + }; + } else { + $progressHandler = $notify; + } - private function resolver(?callable $onFulfilled = null, ?callable $onRejected = null): callable - { - return function (callable $resolve, callable $reject) use ($onFulfilled, $onRejected): void { - $this->handlers[] = static function (PromiseInterface $promise) use ($onFulfilled, $onRejected, $resolve, $reject): void { - $promise = $promise->then($onFulfilled, $onRejected); - - if ($promise instanceof self && $promise->result === null) { - $promise->handlers[] = static function (PromiseInterface $promise) use ($resolve, $reject): void { - $promise->then($resolve, $reject); - }; - } else { - $promise->then($resolve, $reject); - } + $this->handlers[] = static function (ExtendedPromiseInterface $promise) use ($onFulfilled, $onRejected, $resolve, $reject, $progressHandler) { + $promise + ->then($onFulfilled, $onRejected) + ->done($resolve, $reject, $progressHandler); }; + + $this->progressHandlers[] = $progressHandler; }; } - private function reject(\Throwable $reason): void + private function reject($reason = null) { if (null !== $this->result) { return; @@ -192,59 +148,48 @@ private function reject(\Throwable $reason): void $this->settle(reject($reason)); } - /** - * @param PromiseInterface $result - */ - private function settle(PromiseInterface $result): void + private function settle(ExtendedPromiseInterface $promise) { - $result = $this->unwrap($result); + $promise = $this->unwrap($promise); - if ($result === $this) { - $result = new RejectedPromise( + if ($promise === $this) { + $promise = new RejectedPromise( new \LogicException('Cannot resolve a promise with itself.') ); } - if ($result instanceof self) { - $result->requiredCancelRequests++; - } else { - // Unset canceller only when not following a pending promise - $this->canceller = null; - } - $handlers = $this->handlers; - $this->handlers = []; - $this->result = $result; + $this->progressHandlers = $this->handlers = []; + $this->result = $promise; + $this->canceller = null; foreach ($handlers as $handler) { - $handler($result); + $handler($promise); } + } - // Forward cancellation to rejected promise to avoid reporting unhandled rejection - if ($this->cancelled && $result instanceof RejectedPromise) { - $result->cancel(); + private function unwrap($promise) + { + $promise = $this->extract($promise); + + while ($promise instanceof self && null !== $promise->result) { + $promise = $this->extract($promise->result); } + + return $promise; } - /** - * @param PromiseInterface $promise - * @return PromiseInterface - */ - private function unwrap(PromiseInterface $promise): PromiseInterface + private function extract($promise) { - while ($promise instanceof self && null !== $promise->result) { - /** @var PromiseInterface $promise */ - $promise = $promise->result; + if ($promise instanceof LazyPromise) { + $promise = $promise->promise(); } return $promise; } - /** - * @param callable(callable(mixed):void,callable(\Throwable):void):void $cb - */ - private function call(callable $cb): void + private function call(callable $cb) { // Explicitly overwrite argument with null value. This ensure that this // argument does not show up in the stack trace in PHP 7+ only. @@ -261,7 +206,6 @@ private function call(callable $cb): void } elseif (\is_object($callback) && !$callback instanceof \Closure) { $ref = new \ReflectionMethod($callback, '__invoke'); } else { - assert($callback instanceof \Closure || \is_string($callback)); $ref = new \ReflectionFunction($callback); } $args = $ref->getNumberOfParameters(); @@ -279,25 +223,34 @@ private function call(callable $cb): void // These assumptions are covered by the test suite, so if you ever feel like // refactoring this, go ahead, any alternative suggestions are welcome! $target =& $this; + $progressHandlers =& $this->progressHandlers; $callback( - static function ($value) use (&$target): void { + static function ($value = null) use (&$target) { if ($target !== null) { $target->settle(resolve($value)); $target = null; } }, - static function (\Throwable $reason) use (&$target): void { + static function ($reason = null) use (&$target) { if ($target !== null) { $target->reject($reason); $target = null; } + }, + static function ($update = null) use (&$progressHandlers) { + foreach ($progressHandlers as $handler) { + $handler($update); + } } ); } } catch (\Throwable $e) { $target = null; $this->reject($e); + } catch (\Exception $e) { + $target = null; + $this->reject($e); } } } diff --git a/deps/vendor/react/promise/src/PromiseInterface.php b/deps/vendor/react/promise/src/PromiseInterface.php index 5869f76b6..edcb00770 100644 --- a/deps/vendor/react/promise/src/PromiseInterface.php +++ b/deps/vendor/react/promise/src/PromiseInterface.php @@ -2,9 +2,6 @@ namespace React\Promise; -/** - * @template-covariant T - */ interface PromiseInterface { /** @@ -18,6 +15,9 @@ interface PromiseInterface * the result as the first argument. * * `$onRejected` will be invoked once the promise is rejected and passed the * reason as the first argument. + * * `$onProgress` (deprecated) will be invoked whenever the producer of the promise + * triggers progress notifications and passed a single argument (whatever it + * wants) to indicate progress. * * It returns a new promise that will fulfill with the return value of either * `$onFulfilled` or `$onRejected`, whichever is called, or will reject with @@ -30,123 +30,12 @@ interface PromiseInterface * never both. * 2. `$onFulfilled` and `$onRejected` will never be called more * than once. + * 3. `$onProgress` (deprecated) may be called multiple times. * - * @template TFulfilled - * @template TRejected - * @param ?(callable((T is void ? null : T)): (PromiseInterface|TFulfilled)) $onFulfilled - * @param ?(callable(\Throwable): (PromiseInterface|TRejected)) $onRejected - * @return PromiseInterface<($onRejected is null ? ($onFulfilled is null ? T : TFulfilled) : ($onFulfilled is null ? T|TRejected : TFulfilled|TRejected))> + * @param callable|null $onFulfilled + * @param callable|null $onRejected + * @param callable|null $onProgress This argument is deprecated and should not be used anymore. + * @return PromiseInterface */ - public function then(?callable $onFulfilled = null, ?callable $onRejected = null): PromiseInterface; - - /** - * Registers a rejection handler for promise. It is a shortcut for: - * - * ```php - * $promise->then(null, $onRejected); - * ``` - * - * Additionally, you can type hint the `$reason` argument of `$onRejected` to catch - * only specific errors. - * - * @template TThrowable of \Throwable - * @template TRejected - * @param callable(TThrowable): (PromiseInterface|TRejected) $onRejected - * @return PromiseInterface - */ - public function catch(callable $onRejected): PromiseInterface; - - /** - * Allows you to execute "cleanup" type tasks in a promise chain. - * - * It arranges for `$onFulfilledOrRejected` to be called, with no arguments, - * when the promise is either fulfilled or rejected. - * - * * If `$promise` fulfills, and `$onFulfilledOrRejected` returns successfully, - * `$newPromise` will fulfill with the same value as `$promise`. - * * If `$promise` fulfills, and `$onFulfilledOrRejected` throws or returns a - * rejected promise, `$newPromise` will reject with the thrown exception or - * rejected promise's reason. - * * If `$promise` rejects, and `$onFulfilledOrRejected` returns successfully, - * `$newPromise` will reject with the same reason as `$promise`. - * * If `$promise` rejects, and `$onFulfilledOrRejected` throws or returns a - * rejected promise, `$newPromise` will reject with the thrown exception or - * rejected promise's reason. - * - * `finally()` behaves similarly to the synchronous finally statement. When combined - * with `catch()`, `finally()` allows you to write code that is similar to the familiar - * synchronous catch/finally pair. - * - * Consider the following synchronous code: - * - * ```php - * try { - * return doSomething(); - * } catch(\Exception $e) { - * return handleError($e); - * } finally { - * cleanup(); - * } - * ``` - * - * Similar asynchronous code (with `doSomething()` that returns a promise) can be - * written: - * - * ```php - * return doSomething() - * ->catch('handleError') - * ->finally('cleanup'); - * ``` - * - * @param callable(): (void|PromiseInterface) $onFulfilledOrRejected - * @return PromiseInterface - */ - public function finally(callable $onFulfilledOrRejected): PromiseInterface; - - /** - * The `cancel()` method notifies the creator of the promise that there is no - * further interest in the results of the operation. - * - * Once a promise is settled (either fulfilled or rejected), calling `cancel()` on - * a promise has no effect. - * - * @return void - */ - public function cancel(): void; - - /** - * [Deprecated] Registers a rejection handler for a promise. - * - * This method continues to exist only for BC reasons and to ease upgrading - * between versions. It is an alias for: - * - * ```php - * $promise->catch($onRejected); - * ``` - * - * @template TThrowable of \Throwable - * @template TRejected - * @param callable(TThrowable): (PromiseInterface|TRejected) $onRejected - * @return PromiseInterface - * @deprecated 3.0.0 Use catch() instead - * @see self::catch() - */ - public function otherwise(callable $onRejected): PromiseInterface; - - /** - * [Deprecated] Allows you to execute "cleanup" type tasks in a promise chain. - * - * This method continues to exist only for BC reasons and to ease upgrading - * between versions. It is an alias for: - * - * ```php - * $promise->finally($onFulfilledOrRejected); - * ``` - * - * @param callable(): (void|PromiseInterface) $onFulfilledOrRejected - * @return PromiseInterface - * @deprecated 3.0.0 Use finally() instead - * @see self::finally() - */ - public function always(callable $onFulfilledOrRejected): PromiseInterface; + public function then(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null); } diff --git a/deps/vendor/react/promise/src/PromisorInterface.php b/deps/vendor/react/promise/src/PromisorInterface.php new file mode 100644 index 000000000..bd6440086 --- /dev/null +++ b/deps/vendor/react/promise/src/PromisorInterface.php @@ -0,0 +1,13 @@ +reason = $reason; + } + + public function then(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null) + { + if (null === $onRejected) { + return $this; + } + + try { + return resolve($onRejected($this->reason)); + } catch (\Throwable $exception) { + return new RejectedPromise($exception); + } catch (\Exception $exception) { + return new RejectedPromise($exception); + } + } + + public function done(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null) + { + if (null === $onRejected) { + throw UnhandledRejectionException::resolve($this->reason); + } + + $result = $onRejected($this->reason); + + if ($result instanceof self) { + throw UnhandledRejectionException::resolve($result->reason); + } + + if ($result instanceof ExtendedPromiseInterface) { + $result->done(); + } + } + + public function otherwise(callable $onRejected) + { + if (!_checkTypehint($onRejected, $this->reason)) { + return $this; + } + + return $this->then(null, $onRejected); + } + + public function always(callable $onFulfilledOrRejected) + { + return $this->then(null, function ($reason) use ($onFulfilledOrRejected) { + return resolve($onFulfilledOrRejected())->then(function () use ($reason) { + return new RejectedPromise($reason); + }); + }); + } + + public function progress(callable $onProgress) + { + return $this; + } + + public function cancel() + { + } +} diff --git a/deps/vendor/react/promise/src/UnhandledRejectionException.php b/deps/vendor/react/promise/src/UnhandledRejectionException.php new file mode 100644 index 000000000..e7fe2f7a8 --- /dev/null +++ b/deps/vendor/react/promise/src/UnhandledRejectionException.php @@ -0,0 +1,31 @@ +reason = $reason; + + $message = \sprintf('Unhandled Rejection: %s', \json_encode($reason)); + + parent::__construct($message, 0); + } + + public function getReason() + { + return $this->reason; + } +} diff --git a/deps/vendor/react/promise/src/functions.php b/deps/vendor/react/promise/src/functions.php index 2aab877e3..429f0e733 100644 --- a/deps/vendor/react/promise/src/functions.php +++ b/deps/vendor/react/promise/src/functions.php @@ -2,10 +2,6 @@ namespace React\Promise; -use React\Promise\Exception\CompositeException; -use React\Promise\Internal\FulfilledPromise; -use React\Promise\Internal\RejectedPromise; - /** * Creates a promise for the supplied `$promiseOrValue`. * @@ -17,27 +13,26 @@ * * If `$promiseOrValue` is a promise, it will be returned as is. * - * @template T - * @param PromiseInterface|T $promiseOrValue - * @return PromiseInterface + * @param mixed $promiseOrValue + * @return PromiseInterface */ -function resolve($promiseOrValue): PromiseInterface +function resolve($promiseOrValue = null) { - if ($promiseOrValue instanceof PromiseInterface) { + if ($promiseOrValue instanceof ExtendedPromiseInterface) { return $promiseOrValue; } + // Check is_object() first to avoid method_exists() triggering + // class autoloaders if $promiseOrValue is a string. if (\is_object($promiseOrValue) && \method_exists($promiseOrValue, 'then')) { $canceller = null; if (\method_exists($promiseOrValue, 'cancel')) { $canceller = [$promiseOrValue, 'cancel']; - assert(\is_callable($canceller)); } - /** @var Promise */ - return new Promise(function (callable $resolve, callable $reject) use ($promiseOrValue): void { - $promiseOrValue->then($resolve, $reject); + return new Promise(function ($resolve, $reject, $notify) use ($promiseOrValue) { + $promiseOrValue->then($resolve, $reject, $notify); }, $canceller); } @@ -45,23 +40,30 @@ function resolve($promiseOrValue): PromiseInterface } /** - * Creates a rejected promise for the supplied `$reason`. + * Creates a rejected promise for the supplied `$promiseOrValue`. * - * If `$reason` is a value, it will be the rejection value of the + * If `$promiseOrValue` is a value, it will be the rejection value of the * returned promise. * - * If `$reason` is a promise, its completion value will be the rejected + * If `$promiseOrValue` is a promise, its completion value will be the rejected * value of the returned promise. * * This can be useful in situations where you need to reject a promise without * throwing an exception. For example, it allows you to propagate a rejection with * the value of another promise. * - * @return PromiseInterface + * @param mixed $promiseOrValue + * @return PromiseInterface */ -function reject(\Throwable $reason): PromiseInterface +function reject($promiseOrValue = null) { - return new RejectedPromise($reason); + if ($promiseOrValue instanceof PromiseInterface) { + return resolve($promiseOrValue)->then(function ($value) { + return new RejectedPromise($value); + }); + } + + return new RejectedPromise($promiseOrValue); } /** @@ -70,50 +72,14 @@ function reject(\Throwable $reason): PromiseInterface * will be an array containing the resolution values of each of the items in * `$promisesOrValues`. * - * @template T - * @param iterable|T> $promisesOrValues - * @return PromiseInterface> + * @param array $promisesOrValues + * @return PromiseInterface */ -function all(iterable $promisesOrValues): PromiseInterface +function all($promisesOrValues) { - $cancellationQueue = new Internal\CancellationQueue(); - - /** @var Promise> */ - return new Promise(function (callable $resolve, callable $reject) use ($promisesOrValues, $cancellationQueue): void { - $toResolve = 0; - /** @var bool */ - $continue = true; - $values = []; - - foreach ($promisesOrValues as $i => $promiseOrValue) { - $cancellationQueue->enqueue($promiseOrValue); - $values[$i] = null; - ++$toResolve; - - resolve($promiseOrValue)->then( - function ($value) use ($i, &$values, &$toResolve, &$continue, $resolve): void { - $values[$i] = $value; - - if (0 === --$toResolve && !$continue) { - $resolve($values); - } - }, - function (\Throwable $reason) use (&$continue, $reject): void { - $continue = false; - $reject($reason); - } - ); - - if (!$continue && !\is_array($promisesOrValues)) { - break; - } - } - - $continue = false; - if ($toResolve === 0) { - $resolve($values); - } - }, $cancellationQueue); + return map($promisesOrValues, function ($val) { + return $val; + }); } /** @@ -123,29 +89,29 @@ function (\Throwable $reason) use (&$continue, $reject): void { * The returned promise will become **infinitely pending** if `$promisesOrValues` * contains 0 items. * - * @template T - * @param iterable|T> $promisesOrValues - * @return PromiseInterface + * @param array $promisesOrValues + * @return PromiseInterface */ -function race(iterable $promisesOrValues): PromiseInterface +function race($promisesOrValues) { - $cancellationQueue = new Internal\CancellationQueue(); - - /** @var Promise */ - return new Promise(function (callable $resolve, callable $reject) use ($promisesOrValues, $cancellationQueue): void { - $continue = true; - - foreach ($promisesOrValues as $promiseOrValue) { - $cancellationQueue->enqueue($promiseOrValue); + $cancellationQueue = new CancellationQueue(); + $cancellationQueue->enqueue($promisesOrValues); + + return new Promise(function ($resolve, $reject, $notify) use ($promisesOrValues, $cancellationQueue) { + resolve($promisesOrValues) + ->done(function ($array) use ($cancellationQueue, $resolve, $reject, $notify) { + if (!is_array($array) || !$array) { + $resolve(); + return; + } - resolve($promiseOrValue)->then($resolve, $reject)->finally(function () use (&$continue): void { - $continue = false; - }); + foreach ($array as $promiseOrValue) { + $cancellationQueue->enqueue($promiseOrValue); - if (!$continue && !\is_array($promisesOrValues)) { - break; - } - } + resolve($promiseOrValue) + ->done($resolve, $reject, $notify); + } + }, $reject, $notify); }, $cancellationQueue); } @@ -160,118 +126,212 @@ function race(iterable $promisesOrValues): PromiseInterface * The returned promise will also reject with a `React\Promise\Exception\LengthException` * if `$promisesOrValues` contains 0 items. * - * @template T - * @param iterable|T> $promisesOrValues - * @return PromiseInterface + * @param array $promisesOrValues + * @return PromiseInterface */ -function any(iterable $promisesOrValues): PromiseInterface +function any($promisesOrValues) { - $cancellationQueue = new Internal\CancellationQueue(); - - /** @var Promise */ - return new Promise(function (callable $resolve, callable $reject) use ($promisesOrValues, $cancellationQueue): void { - $toReject = 0; - $continue = true; - $reasons = []; - - foreach ($promisesOrValues as $i => $promiseOrValue) { - $cancellationQueue->enqueue($promiseOrValue); - ++$toReject; - - resolve($promiseOrValue)->then( - function ($value) use ($resolve, &$continue): void { - $continue = false; - $resolve($value); - }, - function (\Throwable $reason) use ($i, &$reasons, &$toReject, $reject, &$continue): void { - $reasons[$i] = $reason; - - if (0 === --$toReject && !$continue) { - $reject(new CompositeException( - $reasons, - 'All promises rejected.' - )); - } + return some($promisesOrValues, 1) + ->then(function ($val) { + return \array_shift($val); + }); +} + +/** + * Returns a promise that will resolve when `$howMany` of the supplied items in + * `$promisesOrValues` resolve. The resolution value of the returned promise + * will be an array of length `$howMany` containing the resolution values of the + * triggering items. + * + * The returned promise will reject if it becomes impossible for `$howMany` items + * to resolve (that is, when `(count($promisesOrValues) - $howMany) + 1` items + * reject). The rejection value will be an array of + * `(count($promisesOrValues) - $howMany) + 1` rejection reasons. + * + * The returned promise will also reject with a `React\Promise\Exception\LengthException` + * if `$promisesOrValues` contains less items than `$howMany`. + * + * @param array $promisesOrValues + * @param int $howMany + * @return PromiseInterface + */ +function some($promisesOrValues, $howMany) +{ + $cancellationQueue = new CancellationQueue(); + $cancellationQueue->enqueue($promisesOrValues); + + return new Promise(function ($resolve, $reject, $notify) use ($promisesOrValues, $howMany, $cancellationQueue) { + resolve($promisesOrValues) + ->done(function ($array) use ($howMany, $cancellationQueue, $resolve, $reject, $notify) { + if (!\is_array($array) || $howMany < 1) { + $resolve([]); + return; } - ); - if (!$continue && !\is_array($promisesOrValues)) { - break; - } - } + $len = \count($array); + + if ($len < $howMany) { + throw new Exception\LengthException( + \sprintf( + 'Input array must contain at least %d item%s but contains only %s item%s.', + $howMany, + 1 === $howMany ? '' : 's', + $len, + 1 === $len ? '' : 's' + ) + ); + } - $continue = false; - if ($toReject === 0 && !$reasons) { - $reject(new Exception\LengthException( - 'Must contain at least 1 item but contains only 0 items.' - )); - } elseif ($toReject === 0) { - $reject(new CompositeException( - $reasons, - 'All promises rejected.' - )); - } + $toResolve = $howMany; + $toReject = ($len - $toResolve) + 1; + $values = []; + $reasons = []; + + foreach ($array as $i => $promiseOrValue) { + $fulfiller = function ($val) use ($i, &$values, &$toResolve, $toReject, $resolve) { + if ($toResolve < 1 || $toReject < 1) { + return; + } + + $values[$i] = $val; + + if (0 === --$toResolve) { + $resolve($values); + } + }; + + $rejecter = function ($reason) use ($i, &$reasons, &$toReject, $toResolve, $reject) { + if ($toResolve < 1 || $toReject < 1) { + return; + } + + $reasons[$i] = $reason; + + if (0 === --$toReject) { + $reject($reasons); + } + }; + + $cancellationQueue->enqueue($promiseOrValue); + + resolve($promiseOrValue) + ->done($fulfiller, $rejecter, $notify); + } + }, $reject, $notify); }, $cancellationQueue); } /** - * Sets the global rejection handler for unhandled promise rejections. - * - * Note that rejected promises should always be handled similar to how any - * exceptions should always be caught in a `try` + `catch` block. If you remove - * the last reference to a rejected promise that has not been handled, it will - * report an unhandled promise rejection. See also the [`reject()` function](#reject) - * for more details. - * - * The `?callable $callback` argument MUST be a valid callback function that - * accepts a single `Throwable` argument or a `null` value to restore the - * default promise rejection handler. The return value of the callback function - * will be ignored and has no effect, so you SHOULD return a `void` value. The - * callback function MUST NOT throw or the program will be terminated with a - * fatal error. + * Traditional map function, similar to `array_map()`, but allows input to contain + * promises and/or values, and `$mapFunc` may return either a value or a promise. * - * The function returns the previous rejection handler or `null` if using the - * default promise rejection handler. + * The map function receives each item as argument, where item is a fully resolved + * value of a promise or value in `$promisesOrValues`. * - * The default promise rejection handler will log an error message plus its - * stack trace: - * - * ```php - * // Unhandled promise rejection with RuntimeException: Unhandled in example.php:2 - * React\Promise\reject(new RuntimeException('Unhandled')); - * ``` - * - * The promise rejection handler may be used to use customize the log message or - * write to custom log targets. As a rule of thumb, this function should only be - * used as a last resort and promise rejections are best handled with either the - * [`then()` method](#promiseinterfacethen), the - * [`catch()` method](#promiseinterfacecatch), or the - * [`finally()` method](#promiseinterfacefinally). - * See also the [`reject()` function](#reject) for more details. + * @param array $promisesOrValues + * @param callable $mapFunc + * @return PromiseInterface + */ +function map($promisesOrValues, callable $mapFunc) +{ + $cancellationQueue = new CancellationQueue(); + $cancellationQueue->enqueue($promisesOrValues); + + return new Promise(function ($resolve, $reject, $notify) use ($promisesOrValues, $mapFunc, $cancellationQueue) { + resolve($promisesOrValues) + ->done(function ($array) use ($mapFunc, $cancellationQueue, $resolve, $reject, $notify) { + if (!\is_array($array) || !$array) { + $resolve([]); + return; + } + + $toResolve = \count($array); + $values = []; + + foreach ($array as $i => $promiseOrValue) { + $cancellationQueue->enqueue($promiseOrValue); + $values[$i] = null; + + resolve($promiseOrValue) + ->then($mapFunc) + ->done( + function ($mapped) use ($i, &$values, &$toResolve, $resolve) { + $values[$i] = $mapped; + + if (0 === --$toResolve) { + $resolve($values); + } + }, + $reject, + $notify + ); + } + }, $reject, $notify); + }, $cancellationQueue); +} + +/** + * Traditional reduce function, similar to `array_reduce()`, but input may contain + * promises and/or values, and `$reduceFunc` may return either a value or a + * promise, *and* `$initialValue` may be a promise or a value for the starting + * value. * - * @param callable(\Throwable):void|null $callback - * @return callable(\Throwable):void|null + * @param array $promisesOrValues + * @param callable $reduceFunc + * @param mixed $initialValue + * @return PromiseInterface */ -function set_rejection_handler(?callable $callback): ?callable +function reduce($promisesOrValues, callable $reduceFunc, $initialValue = null) { - static $current = null; - $previous = $current; - $current = $callback; + $cancellationQueue = new CancellationQueue(); + $cancellationQueue->enqueue($promisesOrValues); + + return new Promise(function ($resolve, $reject, $notify) use ($promisesOrValues, $reduceFunc, $initialValue, $cancellationQueue) { + resolve($promisesOrValues) + ->done(function ($array) use ($reduceFunc, $initialValue, $cancellationQueue, $resolve, $reject, $notify) { + if (!\is_array($array)) { + $array = []; + } + + $total = \count($array); + $i = 0; - return $previous; + // Wrap the supplied $reduceFunc with one that handles promises and then + // delegates to the supplied. + $wrappedReduceFunc = function ($current, $val) use ($reduceFunc, $cancellationQueue, $total, &$i) { + $cancellationQueue->enqueue($val); + + return $current + ->then(function ($c) use ($reduceFunc, $total, &$i, $val) { + return resolve($val) + ->then(function ($value) use ($reduceFunc, $total, &$i, $c) { + return $reduceFunc($c, $value, $i++, $total); + }); + }); + }; + + $cancellationQueue->enqueue($initialValue); + + \array_reduce($array, $wrappedReduceFunc, resolve($initialValue)) + ->done($resolve, $reject, $notify); + }, $reject, $notify); + }, $cancellationQueue); } /** * @internal */ -function _checkTypehint(callable $callback, \Throwable $reason): bool +function _checkTypehint(callable $callback, $object) { + if (!\is_object($object)) { + return true; + } + if (\is_array($callback)) { $callbackReflection = new \ReflectionMethod($callback[0], $callback[1]); } elseif (\is_object($callback) && !$callback instanceof \Closure) { $callbackReflection = new \ReflectionMethod($callback, '__invoke'); } else { - assert($callback instanceof \Closure || \is_string($callback)); $callbackReflection = new \ReflectionFunction($callback); } @@ -283,9 +343,18 @@ function _checkTypehint(callable $callback, \Throwable $reason): bool $expectedException = $parameters[0]; + // PHP before v8 used an easy API: + if (\PHP_VERSION_ID < 70100 || \defined('HHVM_VERSION')) { + if (!$expectedException->getClass()) { + return true; + } + + return $expectedException->getClass()->isInstance($object); + } + // Extract the type of the argument and handle different possibilities $type = $expectedException->getType(); - + $isTypeUnion = true; $types = []; @@ -310,22 +379,15 @@ function _checkTypehint(callable $callback, \Throwable $reason): bool } foreach ($types as $type) { - - if ($type instanceof \ReflectionIntersectionType) { - foreach ($type->getTypes() as $typeToMatch) { - assert($typeToMatch instanceof \ReflectionNamedType); - $name = $typeToMatch->getName(); - if (!($matches = (!$typeToMatch->isBuiltin() && $reason instanceof $name))) { - break; - } - } - assert(isset($matches)); - } else { - assert($type instanceof \ReflectionNamedType); - $name = $type->getName(); - $matches = !$type->isBuiltin() && $reason instanceof $name; + if (!$type instanceof \ReflectionNamedType) { + throw new \LogicException('This implementation does not support groups of intersection or union types'); } + // A named-type can be either a class-name or a built-in type like string, int, array, etc. + $matches = ($type->isBuiltin() && \gettype($object) === $type->getName()) + || (new \ReflectionClass($type->getName()))->isInstance($object); + + // If we look for a single match (union), we can return early on match // If we look for a full match (intersection), we can return early on mismatch if ($matches) { diff --git a/deps/vendor/react/socket/CHANGELOG.md b/deps/vendor/react/socket/CHANGELOG.md index 659560f54..76ba85f25 100644 --- a/deps/vendor/react/socket/CHANGELOG.md +++ b/deps/vendor/react/socket/CHANGELOG.md @@ -1,60 +1,5 @@ # Changelog -## 1.16.0 (2024-07-26) - -* Feature: Improve PHP 8.4+ support by avoiding implicitly nullable type declarations. - (#318 by @clue) - -## 1.15.0 (2023-12-15) - -* Feature: Full PHP 8.3 compatibility. - (#310 by @clue) - -* Fix: Fix cancelling during the 50ms resolution delay when DNS is still pending. - (#311 by @clue) - -## 1.14.0 (2023-08-25) - -* Feature: Improve Promise v3 support and use template types. - (#307 and #309 by @clue) - -* Improve test suite and update to collect all garbage cycles. - (#308 by @clue) - -## 1.13.0 (2023-06-07) - -* Feature: Include timeout logic to avoid dependency on reactphp/promise-timer. - (#305 by @clue) - -* Feature: Improve errno detection for failed connections without `ext-sockets`. - (#304 by @clue) - -* Improve test suite, clean up leftover `.sock` files and report failed assertions. - (#299, #300, #301 and #306 by @clue) - -## 1.12.0 (2022-08-25) - -* Feature: Forward compatibility with react/promise 3. - (#214 by @WyriHaximus and @clue) - -* Feature: Full support for PHP 8.2 release. - (#298 by @WyriHaximus) - -* Feature: Avoid unneeded syscall on socket close. - (#292 by @clue) - -* Feature / Fix: Improve error reporting when custom error handler is used. - (#290 by @clue) - -* Fix: Fix invalid references in exception stack trace. - (#284 by @clue) - -* Minor documentation improvements, update to use new reactphp/async package instead of clue/reactphp-block. - (#296 by @clue, #285 by @SimonFrings and #295 by @nhedger) - -* Improve test suite, update macOS and HHVM environment, fix optional tests for `ENETUNREACH`. - (#288, #289 and #297 by @clue) - ## 1.11.0 (2022-01-14) * Feature: Full support for PHP 8.1 release. diff --git a/deps/vendor/react/socket/README.md b/deps/vendor/react/socket/README.md index e77e67645..1b7afc8ac 100644 --- a/deps/vendor/react/socket/README.md +++ b/deps/vendor/react/socket/README.md @@ -1,7 +1,6 @@ # Socket [![CI status](https://github.com/reactphp/socket/workflows/CI/badge.svg)](https://github.com/reactphp/socket/actions) -[![installs on Packagist](https://img.shields.io/packagist/dt/react/socket?color=blue&label=installs%20on%20Packagist)](https://packagist.org/packages/react/socket) Async, streaming plaintext TCP/IP and secure TLS socket server and client connections for [ReactPHP](https://reactphp.org/). @@ -860,8 +859,8 @@ The interface only offers a single method: #### connect() -The `connect(string $uri): PromiseInterface` method can be used to -create a streaming connection to the given remote address. +The `connect(string $uri): PromiseInterface` method +can be used to create a streaming connection to the given remote address. It returns a [Promise](https://github.com/reactphp/promise) which either fulfills with a stream implementing [`ConnectionInterface`](#connectioninterface) @@ -1494,7 +1493,7 @@ This project follows [SemVer](https://semver.org/). This will install the latest supported version: ```bash -composer require react/socket:^1.16 +$ composer require react/socket:^1.11 ``` See also the [CHANGELOG](CHANGELOG.md) for details about version upgrades. @@ -1542,13 +1541,13 @@ To run the test suite, you first need to clone this repo and then install all dependencies [through Composer](https://getcomposer.org/): ```bash -composer install +$ composer install ``` To run the test suite, go to the project root and run: ```bash -vendor/bin/phpunit +$ vendor/bin/phpunit ``` The test suite also contains a number of functional integration tests that rely @@ -1556,7 +1555,7 @@ on a stable internet connection. If you do not want to run these, they can simply be skipped like this: ```bash -vendor/bin/phpunit --exclude-group internet +$ vendor/bin/phpunit --exclude-group internet ``` ## License diff --git a/deps/vendor/react/socket/composer.json b/deps/vendor/react/socket/composer.json index b1e1d2535..ec50942e6 100644 --- a/deps/vendor/react/socket/composer.json +++ b/deps/vendor/react/socket/composer.json @@ -28,25 +28,25 @@ "require": { "php": ">=5.3.0", "evenement/evenement": "^3.0 || ^2.0 || ^1.0", - "react/dns": "^1.13", + "react/dns": "^1.8", "react/event-loop": "^1.2", - "react/promise": "^3.2 || ^2.6 || ^1.2.1", - "react/stream": "^1.4" + "react/promise": "^2.6.0 || ^1.2.1", + "react/promise-timer": "^1.8", + "react/stream": "^1.2" }, "require-dev": { - "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", - "react/async": "^4.3 || ^3.3 || ^2", - "react/promise-stream": "^1.4", - "react/promise-timer": "^1.11" + "clue/block-react": "^1.5", + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35", + "react/promise-stream": "^1.2" }, "autoload": { "psr-4": { - "React\\Socket\\": "src/" + "React\\Socket\\": "src" } }, "autoload-dev": { "psr-4": { - "React\\Tests\\Socket\\": "tests/" + "React\\Tests\\Socket\\": "tests" } } } diff --git a/deps/vendor/react/socket/src/Connection.php b/deps/vendor/react/socket/src/Connection.php index 65ae26b48..5e3b00d9b 100644 --- a/deps/vendor/react/socket/src/Connection.php +++ b/deps/vendor/react/socket/src/Connection.php @@ -127,9 +127,13 @@ public function handleClose() } // Try to cleanly shut down socket and ignore any errors in case other - // side already closed. Underlying Stream implementation will take care - // of closing stream resource, so we otherwise keep this open here. + // side already closed. Shutting down may return to blocking mode on + // some legacy versions, so reset to non-blocking just in case before + // continuing to close the socket resource. + // Underlying Stream implementation will take care of closing file + // handle, so we otherwise keep this open here. @\stream_socket_shutdown($this->stream, \STREAM_SHUT_RDWR); + \stream_set_blocking($this->stream, false); } public function getRemoteAddress() diff --git a/deps/vendor/react/socket/src/Connector.php b/deps/vendor/react/socket/src/Connector.php index 15faa4699..93477bd73 100644 --- a/deps/vendor/react/socket/src/Connector.php +++ b/deps/vendor/react/socket/src/Connector.php @@ -170,7 +170,7 @@ public function connect($uri) if (!isset($this->connectors[$scheme])) { return \React\Promise\reject(new \RuntimeException( 'No connector available for URI scheme "' . $scheme . '" (EINVAL)', - \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : (\defined('PCNTL_EINVAL') ? \PCNTL_EINVAL : 22) + \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : 22 )); } diff --git a/deps/vendor/react/socket/src/ConnectorInterface.php b/deps/vendor/react/socket/src/ConnectorInterface.php index 1f07b753e..3dd78f139 100644 --- a/deps/vendor/react/socket/src/ConnectorInterface.php +++ b/deps/vendor/react/socket/src/ConnectorInterface.php @@ -51,8 +51,7 @@ interface ConnectorInterface * ``` * * @param string $uri - * @return \React\Promise\PromiseInterface - * Resolves with a `ConnectionInterface` on success or rejects with an `Exception` on error. + * @return \React\Promise\PromiseInterface resolves with a stream implementing ConnectionInterface on success or rejects with an Exception on error * @see ConnectionInterface */ public function connect($uri); diff --git a/deps/vendor/react/socket/src/DnsConnector.php b/deps/vendor/react/socket/src/DnsConnector.php index d2fb2c7dd..27fc8f8b9 100644 --- a/deps/vendor/react/socket/src/DnsConnector.php +++ b/deps/vendor/react/socket/src/DnsConnector.php @@ -4,7 +4,7 @@ use React\Dns\Resolver\ResolverInterface; use React\Promise; -use React\Promise\PromiseInterface; +use React\Promise\CancellablePromiseInterface; final class DnsConnector implements ConnectorInterface { @@ -33,7 +33,7 @@ public function connect($uri) if (!$parts || !isset($parts['host'])) { return Promise\reject(new \InvalidArgumentException( 'Given URI "' . $original . '" is invalid (EINVAL)', - \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : (\defined('PCNTL_EINVAL') ? \PCNTL_EINVAL : 22) + \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : 22 )); } @@ -73,11 +73,11 @@ function ($resolve, $reject) use (&$promise, &$resolved, $uri, $connector, $host // Exception trace arguments are not available on some PHP 7.4 installs // @codeCoverageIgnoreStart - foreach ($trace as $ti => $one) { + foreach ($trace as &$one) { if (isset($one['args'])) { - foreach ($one['args'] as $ai => $arg) { + foreach ($one['args'] as &$arg) { if ($arg instanceof \Closure) { - $trace[$ti]['args'][$ai] = 'Object(' . \get_class($arg) . ')'; + $arg = 'Object(' . \get_class($arg) . ')'; } } } @@ -103,7 +103,7 @@ function ($_, $reject) use (&$promise, &$resolved, $uri) { } // (try to) cancel pending DNS lookup / connection attempt - if ($promise instanceof PromiseInterface && \method_exists($promise, 'cancel')) { + if ($promise instanceof CancellablePromiseInterface) { // overwrite callback arguments for PHP7+ only, so they do not show // up in the Exception trace and do not cause a possible cyclic reference. $_ = $reject = null; diff --git a/deps/vendor/react/socket/src/FdServer.php b/deps/vendor/react/socket/src/FdServer.php index 8e46719aa..2c7a6c4de 100644 --- a/deps/vendor/react/socket/src/FdServer.php +++ b/deps/vendor/react/socket/src/FdServer.php @@ -75,7 +75,7 @@ final class FdServer extends EventEmitter implements ServerInterface * @throws \InvalidArgumentException if the listening address is invalid * @throws \RuntimeException if listening on this address fails (already in use etc.) */ - public function __construct($fd, $loop = null) + public function __construct($fd, LoopInterface $loop = null) { if (\preg_match('#^php://fd/(\d+)$#', $fd, $m)) { $fd = (int) $m[1]; @@ -83,31 +83,21 @@ public function __construct($fd, $loop = null) if (!\is_int($fd) || $fd < 0 || $fd >= \PHP_INT_MAX) { throw new \InvalidArgumentException( 'Invalid FD number given (EINVAL)', - \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : (\defined('PCNTL_EINVAL') ? \PCNTL_EINVAL : 22) + \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : 22 ); } - if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1 - throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface'); - } - $this->loop = $loop ?: Loop::get(); - $errno = 0; - $errstr = ''; - \set_error_handler(function ($_, $error) use (&$errno, &$errstr) { + $this->master = @\fopen('php://fd/' . $fd, 'r+'); + if (false === $this->master) { // Match errstr from PHP's warning message. // fopen(php://fd/3): Failed to open stream: Error duping file descriptor 3; possibly it doesn't exist: [9]: Bad file descriptor - \preg_match('/\[(\d+)\]: (.*)/', $error, $m); + $error = \error_get_last(); + \preg_match('/\[(\d+)\]: (.*)/', $error['message'], $m); $errno = isset($m[1]) ? (int) $m[1] : 0; - $errstr = isset($m[2]) ? $m[2] : $error; - }); + $errstr = isset($m[2]) ? $m[2] : $error['message']; - $this->master = \fopen('php://fd/' . $fd, 'r+'); - - \restore_error_handler(); - - if (false === $this->master) { throw new \RuntimeException( 'Failed to listen on FD ' . $fd . ': ' . $errstr . SocketServer::errconst($errno), $errno diff --git a/deps/vendor/react/socket/src/HappyEyeBallsConnectionBuilder.php b/deps/vendor/react/socket/src/HappyEyeBallsConnectionBuilder.php index d4f05e857..6bd071682 100644 --- a/deps/vendor/react/socket/src/HappyEyeBallsConnectionBuilder.php +++ b/deps/vendor/react/socket/src/HappyEyeBallsConnectionBuilder.php @@ -7,7 +7,7 @@ use React\EventLoop\LoopInterface; use React\EventLoop\TimerInterface; use React\Promise; -use React\Promise\PromiseInterface; +use React\Promise\CancellablePromiseInterface; /** * @internal @@ -65,8 +65,9 @@ public function __construct(LoopInterface $loop, ConnectorInterface $connector, public function connect() { + $timer = null; $that = $this; - return new Promise\Promise(function ($resolve, $reject) use ($that) { + return new Promise\Promise(function ($resolve, $reject) use ($that, &$timer) { $lookupResolve = function ($type) use ($that, $resolve, $reject) { return function (array $ips) use ($that, $type, $resolve, $reject) { unset($that->resolverPromises[$type]); @@ -82,29 +83,26 @@ public function connect() }; $that->resolverPromises[Message::TYPE_AAAA] = $that->resolve(Message::TYPE_AAAA, $reject)->then($lookupResolve(Message::TYPE_AAAA)); - $that->resolverPromises[Message::TYPE_A] = $that->resolve(Message::TYPE_A, $reject)->then(function (array $ips) use ($that) { + $that->resolverPromises[Message::TYPE_A] = $that->resolve(Message::TYPE_A, $reject)->then(function (array $ips) use ($that, &$timer) { // happy path: IPv6 has resolved already (or could not resolve), continue with IPv4 addresses if ($that->resolved[Message::TYPE_AAAA] === true || !$ips) { return $ips; } // Otherwise delay processing IPv4 lookup until short timer passes or IPv6 resolves in the meantime - $deferred = new Promise\Deferred(function () use (&$ips) { - // discard all IPv4 addresses if cancelled - $ips = array(); - }); + $deferred = new Promise\Deferred(); $timer = $that->loop->addTimer($that::RESOLUTION_DELAY, function () use ($deferred, $ips) { $deferred->resolve($ips); }); - $that->resolverPromises[Message::TYPE_AAAA]->then(function () use ($that, $timer, $deferred, &$ips) { + $that->resolverPromises[Message::TYPE_AAAA]->then(function () use ($that, $timer, $deferred, $ips) { $that->loop->cancelTimer($timer); $deferred->resolve($ips); }); return $deferred->promise(); })->then($lookupResolve(Message::TYPE_A)); - }, function ($_, $reject) use ($that) { + }, function ($_, $reject) use ($that, &$timer) { $reject(new \RuntimeException( 'Connection to ' . $that->uri . ' cancelled' . (!$that->connectionPromises ? ' during DNS lookup' : '') . ' (ECONNABORTED)', \defined('SOCKET_ECONNABORTED') ? \SOCKET_ECONNABORTED : 103 @@ -112,6 +110,9 @@ public function connect() $_ = $reject = null; $that->cleanUp(); + if ($timer instanceof TimerInterface) { + $that->loop->cancelTimer($timer); + } }); } @@ -246,16 +247,14 @@ public function cleanUp() // clear list of outstanding IPs to avoid creating new connections $this->connectQueue = array(); - // cancel pending connection attempts foreach ($this->connectionPromises as $connectionPromise) { - if ($connectionPromise instanceof PromiseInterface && \method_exists($connectionPromise, 'cancel')) { + if ($connectionPromise instanceof CancellablePromiseInterface) { $connectionPromise->cancel(); } } - // cancel pending DNS resolution (cancel IPv4 first in case it is awaiting IPv6 resolution delay) - foreach (\array_reverse($this->resolverPromises) as $resolverPromise) { - if ($resolverPromise instanceof PromiseInterface && \method_exists($resolverPromise, 'cancel')) { + foreach ($this->resolverPromises as $resolverPromise) { + if ($resolverPromise instanceof CancellablePromiseInterface) { $resolverPromise->cancel(); } } diff --git a/deps/vendor/react/socket/src/HappyEyeBallsConnector.php b/deps/vendor/react/socket/src/HappyEyeBallsConnector.php index a5511ac9e..4b04f7738 100644 --- a/deps/vendor/react/socket/src/HappyEyeBallsConnector.php +++ b/deps/vendor/react/socket/src/HappyEyeBallsConnector.php @@ -13,26 +13,15 @@ final class HappyEyeBallsConnector implements ConnectorInterface private $connector; private $resolver; - /** - * @param ?LoopInterface $loop - * @param ConnectorInterface $connector - * @param ResolverInterface $resolver - */ - public function __construct($loop = null, $connector = null, $resolver = null) + public function __construct(LoopInterface $loop = null, ConnectorInterface $connector = null, ResolverInterface $resolver = null) { // $connector and $resolver arguments are actually required, marked // optional for technical reasons only. Nullable $loop without default // requires PHP 7.1, null default is also supported in legacy PHP // versions, but required parameters are not allowed after arguments // with null default. Mark all parameters optional and check accordingly. - if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1 - throw new \InvalidArgumentException('Argument #1 ($loop) expected null|React\EventLoop\LoopInterface'); - } - if (!$connector instanceof ConnectorInterface) { // manual type check to support legacy PHP < 7.1 - throw new \InvalidArgumentException('Argument #2 ($connector) expected React\Socket\ConnectorInterface'); - } - if (!$resolver instanceof ResolverInterface) { // manual type check to support legacy PHP < 7.1 - throw new \InvalidArgumentException('Argument #3 ($resolver) expected React\Dns\Resolver\ResolverInterface'); + if ($connector === null || $resolver === null) { + throw new \InvalidArgumentException('Missing required $connector or $resolver argument'); } $this->loop = $loop ?: Loop::get(); @@ -56,7 +45,7 @@ public function connect($uri) if (!$parts || !isset($parts['host'])) { return Promise\reject(new \InvalidArgumentException( 'Given URI "' . $original . '" is invalid (EINVAL)', - \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : (\defined('PCNTL_EINVAL') ? \PCNTL_EINVAL : 22) + \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : 22 )); } diff --git a/deps/vendor/react/socket/src/SecureConnector.php b/deps/vendor/react/socket/src/SecureConnector.php index 08255ac92..03c6e361f 100644 --- a/deps/vendor/react/socket/src/SecureConnector.php +++ b/deps/vendor/react/socket/src/SecureConnector.php @@ -15,17 +15,8 @@ final class SecureConnector implements ConnectorInterface private $streamEncryption; private $context; - /** - * @param ConnectorInterface $connector - * @param ?LoopInterface $loop - * @param array $context - */ - public function __construct(ConnectorInterface $connector, $loop = null, array $context = array()) + public function __construct(ConnectorInterface $connector, LoopInterface $loop = null, array $context = array()) { - if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1 - throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface'); - } - $this->connector = $connector; $this->streamEncryption = new StreamEncryption($loop ?: Loop::get(), false); $this->context = $context; @@ -45,14 +36,13 @@ public function connect($uri) if (!$parts || !isset($parts['scheme']) || $parts['scheme'] !== 'tls') { return Promise\reject(new \InvalidArgumentException( 'Given URI "' . $uri . '" is invalid (EINVAL)', - \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : (\defined('PCNTL_EINVAL') ? \PCNTL_EINVAL : 22) + \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : 22 )); } $context = $this->context; $encryption = $this->streamEncryption; $connected = false; - /** @var \React\Promise\PromiseInterface $promise */ $promise = $this->connector->connect( \str_replace('tls://', '', $uri) )->then(function (ConnectionInterface $connection) use ($context, $encryption, $uri, &$promise, &$connected) { @@ -96,11 +86,11 @@ public function connect($uri) // Exception trace arguments are not available on some PHP 7.4 installs // @codeCoverageIgnoreStart - foreach ($trace as $ti => $one) { + foreach ($trace as &$one) { if (isset($one['args'])) { - foreach ($one['args'] as $ai => $arg) { + foreach ($one['args'] as &$arg) { if ($arg instanceof \Closure) { - $trace[$ti]['args'][$ai] = 'Object(' . \get_class($arg) . ')'; + $arg = 'Object(' . \get_class($arg) . ')'; } } } diff --git a/deps/vendor/react/socket/src/SecureServer.php b/deps/vendor/react/socket/src/SecureServer.php index 5a202d27b..d0525c942 100644 --- a/deps/vendor/react/socket/src/SecureServer.php +++ b/deps/vendor/react/socket/src/SecureServer.php @@ -122,12 +122,8 @@ final class SecureServer extends EventEmitter implements ServerInterface * @see TcpServer * @link https://www.php.net/manual/en/context.ssl.php for TLS context options */ - public function __construct(ServerInterface $tcp, $loop = null, array $context = array()) + public function __construct(ServerInterface $tcp, LoopInterface $loop = null, array $context = array()) { - if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1 - throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface'); - } - if (!\function_exists('stream_socket_enable_crypto')) { throw new \BadMethodCallException('Encryption not supported on your platform (HHVM < 3.8?)'); // @codeCoverageIgnore } diff --git a/deps/vendor/react/socket/src/Server.php b/deps/vendor/react/socket/src/Server.php index b24c55648..7d4111e8e 100644 --- a/deps/vendor/react/socket/src/Server.php +++ b/deps/vendor/react/socket/src/Server.php @@ -43,18 +43,14 @@ final class Server extends EventEmitter implements ServerInterface * For BC reasons, you can also pass the TCP socket context options as a simple * array without wrapping this in another array under the `tcp` key. * - * @param string|int $uri - * @param ?LoopInterface $loop - * @param array $context + * @param string|int $uri + * @param LoopInterface $loop + * @param array $context * @deprecated 1.9.0 See `SocketServer` instead * @see SocketServer */ - public function __construct($uri, $loop = null, array $context = array()) + public function __construct($uri, LoopInterface $loop = null, array $context = array()) { - if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1 - throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface'); - } - $loop = $loop ?: Loop::get(); // sanitize TCP context options if not properly wrapped diff --git a/deps/vendor/react/socket/src/SocketServer.php b/deps/vendor/react/socket/src/SocketServer.php index e987f5f6a..2ea03baea 100644 --- a/deps/vendor/react/socket/src/SocketServer.php +++ b/deps/vendor/react/socket/src/SocketServer.php @@ -31,12 +31,8 @@ final class SocketServer extends EventEmitter implements ServerInterface * @throws \InvalidArgumentException if the listening address is invalid * @throws \RuntimeException if listening on this address fails (already in use etc.) */ - public function __construct($uri, array $context = array(), $loop = null) + public function __construct($uri, array $context = array(), LoopInterface $loop = null) { - if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1 - throw new \InvalidArgumentException('Argument #3 ($loop) expected null|React\EventLoop\LoopInterface'); - } - // apply default options if not explicitly given $context += array( 'tcp' => array(), @@ -58,7 +54,7 @@ public function __construct($uri, array $context = array(), $loop = null) if (preg_match('#^(?:\w+://)?\d+$#', $uri)) { throw new \InvalidArgumentException( 'Invalid URI given (EINVAL)', - \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : (\defined('PCNTL_EINVAL') ? \PCNTL_EINVAL : 22) + \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : 22 ); } @@ -110,20 +106,15 @@ public function close() */ public static function accept($socket) { - $errno = 0; - $errstr = ''; - \set_error_handler(function ($_, $error) use (&$errno, &$errstr) { + $newSocket = @\stream_socket_accept($socket, 0); + + if (false === $newSocket) { // Match errstr from PHP's warning message. // stream_socket_accept(): accept failed: Connection timed out - $errstr = \preg_replace('#.*: #', '', $error); - $errno = SocketServer::errno($errstr); - }); - - $newSocket = \stream_socket_accept($socket, 0); - - \restore_error_handler(); + $error = \error_get_last(); + $errstr = \preg_replace('#.*: #', '', $error['message']); + $errno = self::errno($errstr); - if (false === $newSocket) { throw new \RuntimeException( 'Unable to accept new connection: ' . $errstr . self::errconst($errno), $errno @@ -139,42 +130,25 @@ public static function accept($socket) * The errno and errstr values describes the type of error that has been * encountered. This method tries to look up the given errstr and find a * matching errno value which can be useful to provide more context to error - * messages. It goes through the list of known errno constants when either - * `ext-sockets`, `ext-posix` or `ext-pcntl` is available to find an errno - * matching the given errstr. + * messages. It goes through the list of known errno constants when + * ext-sockets is available to find an errno matching the given errstr. * * @param string $errstr * @return int errno value (e.g. value of `SOCKET_ECONNREFUSED`) or 0 if not found * @internal - * @copyright Copyright (c) 2023 Christian Lück, taken from https://github.com/clue/errno with permission + * @copyright Copyright (c) 2018 Christian Lück, taken from https://github.com/clue/errno with permission * @codeCoverageIgnore */ public static function errno($errstr) { - // PHP defines the required `strerror()` function through either `ext-sockets`, `ext-posix` or `ext-pcntl` - $strerror = \function_exists('socket_strerror') ? 'socket_strerror' : (\function_exists('posix_strerror') ? 'posix_strerror' : (\function_exists('pcntl_strerror') ? 'pcntl_strerror' : null)); - if ($strerror !== null) { - assert(\is_string($strerror) && \is_callable($strerror)); - - // PHP defines most useful errno constants like `ECONNREFUSED` through constants in `ext-sockets` like `SOCKET_ECONNREFUSED` - // PHP also defines a hand full of errno constants like `EMFILE` through constants in `ext-pcntl` like `PCNTL_EMFILE` - // go through list of all defined constants like `SOCKET_E*` and `PCNTL_E*` and see if they match the given `$errstr` + if (\function_exists('socket_strerror')) { foreach (\get_defined_constants(false) as $name => $value) { - if (\is_int($value) && (\strpos($name, 'SOCKET_E') === 0 || \strpos($name, 'PCNTL_E') === 0) && $strerror($value) === $errstr) { + if (\strpos($name, 'SOCKET_E') === 0 && \socket_strerror($value) === $errstr) { return $value; } } - - // if we reach this, no matching errno constant could be found (unlikely when `ext-sockets` is available) - // go through list of all possible errno values from 1 to `MAX_ERRNO` and see if they match the given `$errstr` - for ($errno = 1, $max = \defined('MAX_ERRNO') ? \MAX_ERRNO : 4095; $errno <= $max; ++$errno) { - if ($strerror($errno) === $errstr) { - return $errno; - } - } } - // if we reach this, no matching errno value could be found (unlikely when either `ext-sockets`, `ext-posix` or `ext-pcntl` is available) return 0; } @@ -185,8 +159,8 @@ public static function errno($errstr) * This method tries to look up the given errno value and find a matching * errno constant name which can be useful to provide more context and more * descriptive error messages. It goes through the list of known errno - * constants when either `ext-sockets` or `ext-pcntl` is available to find - * the matching errno constant name. + * constants when ext-sockets is available to find the matching errno + * constant name. * * Because this method is used to append more context to error messages, the * constant name will be prefixed with a space and put between parenthesis @@ -195,21 +169,19 @@ public static function errno($errstr) * @param int $errno * @return string e.g. ` (ECONNREFUSED)` or empty string if no matching const for the given errno could be found * @internal - * @copyright Copyright (c) 2023 Christian Lück, taken from https://github.com/clue/errno with permission + * @copyright Copyright (c) 2018 Christian Lück, taken from https://github.com/clue/errno with permission * @codeCoverageIgnore */ public static function errconst($errno) { - // PHP defines most useful errno constants like `ECONNREFUSED` through constants in `ext-sockets` like `SOCKET_ECONNREFUSED` - // PHP also defines a hand full of errno constants like `EMFILE` through constants in `ext-pcntl` like `PCNTL_EMFILE` - // go through list of all defined constants like `SOCKET_E*` and `PCNTL_E*` and see if they match the given `$errno` - foreach (\get_defined_constants(false) as $name => $value) { - if ($value === $errno && (\strpos($name, 'SOCKET_E') === 0 || \strpos($name, 'PCNTL_E') === 0)) { - return ' (' . \substr($name, \strpos($name, '_') + 1) . ')'; + if (\function_exists('socket_strerror')) { + foreach (\get_defined_constants(false) as $name => $value) { + if ($value === $errno && \strpos($name, 'SOCKET_E') === 0) { + return ' (' . \substr($name, 7) . ')'; + } } } - // if we reach this, no matching errno constant could be found (unlikely when `ext-sockets` is available) return ''; } } diff --git a/deps/vendor/react/socket/src/StreamEncryption.php b/deps/vendor/react/socket/src/StreamEncryption.php index f91a3597e..4aa7fca0b 100644 --- a/deps/vendor/react/socket/src/StreamEncryption.php +++ b/deps/vendor/react/socket/src/StreamEncryption.php @@ -44,20 +44,11 @@ public function __construct(LoopInterface $loop, $server = true) } } - /** - * @param Connection $stream - * @return \React\Promise\PromiseInterface - */ public function enable(Connection $stream) { return $this->toggle($stream, true); } - /** - * @param Connection $stream - * @param bool $toggle - * @return \React\Promise\PromiseInterface - */ public function toggle(Connection $stream, $toggle) { // pause actual stream instance to continue operation on raw stream socket @@ -107,14 +98,6 @@ public function toggle(Connection $stream, $toggle) }); } - /** - * @internal - * @param resource $socket - * @param Deferred $deferred - * @param bool $toggle - * @param int $method - * @return void - */ public function toggleCrypto($socket, Deferred $deferred, $toggle, $method) { $error = null; @@ -132,7 +115,7 @@ public function toggleCrypto($socket, Deferred $deferred, $toggle, $method) \restore_error_handler(); if (true === $result) { - $deferred->resolve(null); + $deferred->resolve(); } else if (false === $result) { // overwrite callback arguments for PHP7+ only, so they do not show // up in the Exception trace and do not cause a possible cyclic reference. diff --git a/deps/vendor/react/socket/src/TcpConnector.php b/deps/vendor/react/socket/src/TcpConnector.php index 9d2599e81..a4d3b5ba6 100644 --- a/deps/vendor/react/socket/src/TcpConnector.php +++ b/deps/vendor/react/socket/src/TcpConnector.php @@ -13,16 +13,8 @@ final class TcpConnector implements ConnectorInterface private $loop; private $context; - /** - * @param ?LoopInterface $loop - * @param array $context - */ - public function __construct($loop = null, array $context = array()) + public function __construct(LoopInterface $loop = null, array $context = array()) { - if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1 - throw new \InvalidArgumentException('Argument #1 ($loop) expected null|React\EventLoop\LoopInterface'); - } - $this->loop = $loop ?: Loop::get(); $this->context = $context; } @@ -37,7 +29,7 @@ public function connect($uri) if (!$parts || !isset($parts['scheme'], $parts['host'], $parts['port']) || $parts['scheme'] !== 'tcp') { return Promise\reject(new \InvalidArgumentException( 'Given URI "' . $uri . '" is invalid (EINVAL)', - \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : (\defined('PCNTL_EINVAL') ? \PCNTL_EINVAL : 22) + \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : 22 )); } @@ -45,7 +37,7 @@ public function connect($uri) if (@\inet_pton($ip) === false) { return Promise\reject(new \InvalidArgumentException( 'Given URI "' . $uri . '" does not contain a valid host IP (EINVAL)', - \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : (\defined('PCNTL_EINVAL') ? \PCNTL_EINVAL : 22) + \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : 22 )); } @@ -124,19 +116,13 @@ public function connect($uri) // Linux reports socket errno and errstr again when trying to write to the dead socket. // Suppress error reporting to get error message below and close dead socket before rejecting. // This is only known to work on Linux, Mac and Windows are known to not support this. - $errno = 0; - $errstr = ''; - \set_error_handler(function ($_, $error) use (&$errno, &$errstr) { - // Match errstr from PHP's warning message. - // fwrite(): send of 1 bytes failed with errno=111 Connection refused - \preg_match('/errno=(\d+) (.+)/', $error, $m); - $errno = isset($m[1]) ? (int) $m[1] : 0; - $errstr = isset($m[2]) ? $m[2] : $error; - }); - - \fwrite($stream, \PHP_EOL); - - \restore_error_handler(); + @\fwrite($stream, \PHP_EOL); + $error = \error_get_last(); + + // fwrite(): send of 2 bytes failed with errno=111 Connection refused + \preg_match('/errno=(\d+) (.+)/', $error['message'], $m); + $errno = isset($m[1]) ? (int) $m[1] : 0; + $errstr = isset($m[2]) ? $m[2] : $error['message']; } else { // Not on Linux and ext-sockets not available? Too bad. $errno = \defined('SOCKET_ECONNREFUSED') ? \SOCKET_ECONNREFUSED : 111; diff --git a/deps/vendor/react/socket/src/TcpServer.php b/deps/vendor/react/socket/src/TcpServer.php index 01b2b46dc..442af702b 100644 --- a/deps/vendor/react/socket/src/TcpServer.php +++ b/deps/vendor/react/socket/src/TcpServer.php @@ -128,12 +128,8 @@ final class TcpServer extends EventEmitter implements ServerInterface * @throws InvalidArgumentException if the listening address is invalid * @throws RuntimeException if listening on this address fails (already in use etc.) */ - public function __construct($uri, $loop = null, array $context = array()) + public function __construct($uri, LoopInterface $loop = null, array $context = array()) { - if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1 - throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface'); - } - $this->loop = $loop ?: Loop::get(); // a single port has been given => assume localhost @@ -160,14 +156,14 @@ public function __construct($uri, $loop = null, array $context = array()) if (!$parts || !isset($parts['scheme'], $parts['host'], $parts['port']) || $parts['scheme'] !== 'tcp') { throw new \InvalidArgumentException( 'Invalid URI "' . $uri . '" given (EINVAL)', - \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : (\defined('PCNTL_EINVAL') ? \PCNTL_EINVAL : 22) + \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : 22 ); } if (@\inet_pton(\trim($parts['host'], '[]')) === false) { throw new \InvalidArgumentException( 'Given URI "' . $uri . '" does not contain a valid host IP (EINVAL)', - \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : (\defined('PCNTL_EINVAL') ? \PCNTL_EINVAL : 22) + \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : 22 ); } diff --git a/deps/vendor/react/socket/src/TimeoutConnector.php b/deps/vendor/react/socket/src/TimeoutConnector.php index 9ef252f7d..332369f84 100644 --- a/deps/vendor/react/socket/src/TimeoutConnector.php +++ b/deps/vendor/react/socket/src/TimeoutConnector.php @@ -4,7 +4,8 @@ use React\EventLoop\Loop; use React\EventLoop\LoopInterface; -use React\Promise\Promise; +use React\Promise\Timer; +use React\Promise\Timer\TimeoutException; final class TimeoutConnector implements ConnectorInterface { @@ -12,17 +13,8 @@ final class TimeoutConnector implements ConnectorInterface private $timeout; private $loop; - /** - * @param ConnectorInterface $connector - * @param float $timeout - * @param ?LoopInterface $loop - */ - public function __construct(ConnectorInterface $connector, $timeout, $loop = null) + public function __construct(ConnectorInterface $connector, $timeout, LoopInterface $loop = null) { - if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1 - throw new \InvalidArgumentException('Argument #3 ($loop) expected null|React\EventLoop\LoopInterface'); - } - $this->connector = $connector; $this->timeout = $timeout; $this->loop = $loop ?: Loop::get(); @@ -30,50 +22,30 @@ public function __construct(ConnectorInterface $connector, $timeout, $loop = nul public function connect($uri) { - $promise = $this->connector->connect($uri); - - $loop = $this->loop; - $time = $this->timeout; - return new Promise(function ($resolve, $reject) use ($loop, $time, $promise, $uri) { - $timer = null; - $promise = $promise->then(function ($v) use (&$timer, $loop, $resolve) { - if ($timer) { - $loop->cancelTimer($timer); - } - $timer = false; - $resolve($v); - }, function ($v) use (&$timer, $loop, $reject) { - if ($timer) { - $loop->cancelTimer($timer); - } - $timer = false; - $reject($v); - }); - - // promise already resolved => no need to start timer - if ($timer === false) { - return; - } + return Timer\timeout($this->connector->connect($uri), $this->timeout, $this->loop)->then(null, self::handler($uri)); + } - // start timeout timer which will cancel the pending promise - $timer = $loop->addTimer($time, function () use ($time, &$promise, $reject, $uri) { - $reject(new \RuntimeException( - 'Connection to ' . $uri . ' timed out after ' . $time . ' seconds (ETIMEDOUT)', + /** + * Creates a static rejection handler that reports a proper error message in case of a timeout. + * + * This uses a private static helper method to ensure this closure is not + * bound to this instance and the exception trace does not include a + * reference to this instance and its connector stack as a result. + * + * @param string $uri + * @return callable + */ + private static function handler($uri) + { + return function (\Exception $e) use ($uri) { + if ($e instanceof TimeoutException) { + throw new \RuntimeException( + 'Connection to ' . $uri . ' timed out after ' . $e->getTimeout() . ' seconds (ETIMEDOUT)', \defined('SOCKET_ETIMEDOUT') ? \SOCKET_ETIMEDOUT : 110 - )); + ); + } - // Cancel pending connection to clean up any underlying resources and references. - // Avoid garbage references in call stack by passing pending promise by reference. - assert(\method_exists($promise, 'cancel')); - $promise->cancel(); - $promise = null; - }); - }, function () use (&$promise) { - // Cancelling this promise will cancel the pending connection, thus triggering the rejection logic above. - // Avoid garbage references in call stack by passing pending promise by reference. - assert(\method_exists($promise, 'cancel')); - $promise->cancel(); - $promise = null; - }); + throw $e; + }; } } diff --git a/deps/vendor/react/socket/src/UnixConnector.php b/deps/vendor/react/socket/src/UnixConnector.php index 95f932cb0..513fb51b9 100644 --- a/deps/vendor/react/socket/src/UnixConnector.php +++ b/deps/vendor/react/socket/src/UnixConnector.php @@ -18,15 +18,8 @@ final class UnixConnector implements ConnectorInterface { private $loop; - /** - * @param ?LoopInterface $loop - */ - public function __construct($loop = null) + public function __construct(LoopInterface $loop = null) { - if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1 - throw new \InvalidArgumentException('Argument #1 ($loop) expected null|React\EventLoop\LoopInterface'); - } - $this->loop = $loop ?: Loop::get(); } @@ -37,7 +30,7 @@ public function connect($path) } elseif (\substr($path, 0, 7) !== 'unix://') { return Promise\reject(new \InvalidArgumentException( 'Given URI "' . $path . '" is invalid (EINVAL)', - \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : (\defined('PCNTL_EINVAL') ? \PCNTL_EINVAL : 22) + \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : 22 )); } diff --git a/deps/vendor/react/socket/src/UnixServer.php b/deps/vendor/react/socket/src/UnixServer.php index 27b014d15..668e8cb3a 100644 --- a/deps/vendor/react/socket/src/UnixServer.php +++ b/deps/vendor/react/socket/src/UnixServer.php @@ -50,12 +50,8 @@ final class UnixServer extends EventEmitter implements ServerInterface * @throws InvalidArgumentException if the listening address is invalid * @throws RuntimeException if listening on this address fails (already in use etc.) */ - public function __construct($path, $loop = null, array $context = array()) + public function __construct($path, LoopInterface $loop = null, array $context = array()) { - if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1 - throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface'); - } - $this->loop = $loop ?: Loop::get(); if (\strpos($path, '://') === false) { @@ -63,33 +59,29 @@ public function __construct($path, $loop = null, array $context = array()) } elseif (\substr($path, 0, 7) !== 'unix://') { throw new \InvalidArgumentException( 'Given URI "' . $path . '" is invalid (EINVAL)', - \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : (\defined('PCNTL_EINVAL') ? \PCNTL_EINVAL : 22) + \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : 22 ); } - $errno = 0; - $errstr = ''; - \set_error_handler(function ($_, $error) use (&$errno, &$errstr) { - // PHP does not seem to report errno/errstr for Unix domain sockets (UDS) right now. - // This only applies to UDS server sockets, see also https://3v4l.org/NAhpr. - // Parse PHP warning message containing unknown error, HHVM reports proper info at least. - if (\preg_match('/\(([^\)]+)\)|\[(\d+)\]: (.*)/', $error, $match)) { - $errstr = isset($match[3]) ? $match['3'] : $match[1]; - $errno = isset($match[2]) ? (int)$match[2] : 0; - } - }); - - $this->master = \stream_socket_server( + $this->master = @\stream_socket_server( $path, $errno, $errstr, \STREAM_SERVER_BIND | \STREAM_SERVER_LISTEN, \stream_context_create(array('socket' => $context)) ); - - \restore_error_handler(); - if (false === $this->master) { + // PHP does not seem to report errno/errstr for Unix domain sockets (UDS) right now. + // This only applies to UDS server sockets, see also https://3v4l.org/NAhpr. + // Parse PHP warning message containing unknown error, HHVM reports proper info at least. + if ($errno === 0 && $errstr === '') { + $error = \error_get_last(); + if (\preg_match('/\(([^\)]+)\)|\[(\d+)\]: (.*)/', $error['message'], $match)) { + $errstr = isset($match[3]) ? $match['3'] : $match[1]; + $errno = isset($match[2]) ? (int)$match[2] : 0; + } + } + throw new \RuntimeException( 'Failed to listen on Unix domain socket "' . $path . '": ' . $errstr . SocketServer::errconst($errno), $errno diff --git a/deps/vendor/react/stream/CHANGELOG.md b/deps/vendor/react/stream/CHANGELOG.md index 639db6585..9bafba707 100644 --- a/deps/vendor/react/stream/CHANGELOG.md +++ b/deps/vendor/react/stream/CHANGELOG.md @@ -1,30 +1,5 @@ # Changelog -## 1.4.0 (2024-06-11) - -* Feature: Improve PHP 8.4+ support by avoiding implicitly nullable type declarations. - (#179 by @clue) - -* Feature: Full PHP 8.3 compatibility. - (#172 by @clue) - -* Fix: Fix `drain` event of `ThroughStream` to handle potential race condition. - (#171 by @clue) - -## 1.3.0 (2023-06-16) - -* Feature: Full PHP 8.1 and PHP 8.2 compatibility. - (#160 by @SimonFrings, #165 by @clue and #169 by @WyriHaximus) - -* Feature: Avoid unneeded syscall when creating non-blocking `DuplexResourceStream`. - (#164 by @clue) - -* Minor documentation improvements. - (#161 by @mrsimonbennett, #162 by @SimonFrings and #166 by @nhedger) - -* Improve test suite and project setup and report failed assertions. - (#168 and #170 by @clue and #163 by @SimonFrings) - ## 1.2.0 (2021-07-11) A major new feature release, see [**release announcement**](https://clue.engineering/2021/announcing-reactphp-default-loop). diff --git a/deps/vendor/react/stream/README.md b/deps/vendor/react/stream/README.md index 9c0468a65..460f51a9f 100644 --- a/deps/vendor/react/stream/README.md +++ b/deps/vendor/react/stream/README.md @@ -1,7 +1,6 @@ # Stream -[![CI status](https://github.com/reactphp/stream/actions/workflows/ci.yml/badge.svg)](https://github.com/reactphp/stream/actions) -[![installs on Packagist](https://img.shields.io/packagist/dt/react/stream?color=blue&label=installs%20on%20Packagist)](https://packagist.org/packages/react/stream) +[![CI status](https://github.com/reactphp/stream/workflows/CI/badge.svg)](https://github.com/reactphp/stream/actions) Event-driven readable and writable streams for non-blocking I/O in [ReactPHP](https://reactphp.org/). @@ -610,7 +609,7 @@ data until the buffer drains. The stream SHOULD send a `drain` event once the buffer is ready to accept more data. -Similarly, if the stream is not writable (already in a closed state) +Similarly, if the the stream is not writable (already in a closed state) it MUST NOT process the given `$data` and SHOULD return `false`, indicating that the caller should stop sending data. @@ -1203,7 +1202,7 @@ This project follows [SemVer](https://semver.org/). This will install the latest supported version: ```bash -composer require react/stream:^1.4 +$ composer require react/stream:^1.2 ``` See also the [CHANGELOG](CHANGELOG.md) for details about version upgrades. @@ -1219,13 +1218,13 @@ To run the test suite, you first need to clone this repo and then install all dependencies [through Composer](https://getcomposer.org): ```bash -composer install +$ composer install ``` To run the test suite, go to the project root and run: ```bash -vendor/bin/phpunit +$ php vendor/bin/phpunit ``` The test suite also contains a number of functional integration tests that rely @@ -1233,7 +1232,7 @@ on a stable internet connection. If you do not want to run these, they can simply be skipped like this: ```bash -vendor/bin/phpunit --exclude-group internet +$ php vendor/bin/phpunit --exclude-group internet ``` ## License diff --git a/deps/vendor/react/stream/composer.json b/deps/vendor/react/stream/composer.json index 09d8b71e0..b235f5a50 100644 --- a/deps/vendor/react/stream/composer.json +++ b/deps/vendor/react/stream/composer.json @@ -31,17 +31,17 @@ "evenement/evenement": "^3.0 || ^2.0 || ^1.0" }, "require-dev": { - "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35", "clue/stream-filter": "~1.2" }, "autoload": { "psr-4": { - "React\\Stream\\": "src/" + "React\\Stream\\": "src" } }, "autoload-dev": { "psr-4": { - "React\\Tests\\Stream\\": "tests/" + "React\\Tests\\Stream\\": "tests" } } } diff --git a/deps/vendor/react/stream/src/DuplexResourceStream.php b/deps/vendor/react/stream/src/DuplexResourceStream.php index d6de55c07..c3163c639 100644 --- a/deps/vendor/react/stream/src/DuplexResourceStream.php +++ b/deps/vendor/react/stream/src/DuplexResourceStream.php @@ -38,13 +38,7 @@ final class DuplexResourceStream extends EventEmitter implements DuplexStreamInt private $closing = false; private $listening = false; - /** - * @param resource $stream - * @param ?LoopInterface $loop - * @param ?int $readChunkSize - * @param ?WritableStreamInterface $buffer - */ - public function __construct($stream, $loop = null, $readChunkSize = null, $buffer = null) + public function __construct($stream, LoopInterface $loop = null, $readChunkSize = null, WritableStreamInterface $buffer = null) { if (!\is_resource($stream) || \get_resource_type($stream) !== "stream") { throw new InvalidArgumentException('First parameter must be a valid stream resource'); @@ -58,17 +52,10 @@ public function __construct($stream, $loop = null, $readChunkSize = null, $buffe // this class relies on non-blocking I/O in order to not interrupt the event loop // e.g. pipes on Windows do not support this: https://bugs.php.net/bug.php?id=47918 - if ($buffer !== null && !$buffer instanceof WritableResourceStream && \stream_set_blocking($stream, false) !== true) { + if (\stream_set_blocking($stream, false) !== true) { throw new \RuntimeException('Unable to set stream resource to non-blocking mode'); } - if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1 - throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface'); - } - if ($buffer !== null && !$buffer instanceof WritableStreamInterface) { // manual type check to support legacy PHP < 7.1 - throw new \InvalidArgumentException('Argument #4 ($buffer) expected null|React\Stream\WritableStreamInterface'); - } - // Use unbuffered read operations on the underlying stream resource. // Reading chunks from the stream may otherwise leave unread bytes in // PHP's stream buffers which some event loop implementations do not diff --git a/deps/vendor/react/stream/src/ReadableResourceStream.php b/deps/vendor/react/stream/src/ReadableResourceStream.php index 823360a63..1b0b08c99 100644 --- a/deps/vendor/react/stream/src/ReadableResourceStream.php +++ b/deps/vendor/react/stream/src/ReadableResourceStream.php @@ -40,12 +40,7 @@ final class ReadableResourceStream extends EventEmitter implements ReadableStrea private $closed = false; private $listening = false; - /** - * @param resource $stream - * @param ?LoopInterface $loop - * @param ?int $readChunkSize - */ - public function __construct($stream, $loop = null, $readChunkSize = null) + public function __construct($stream, LoopInterface $loop = null, $readChunkSize = null) { if (!\is_resource($stream) || \get_resource_type($stream) !== "stream") { throw new InvalidArgumentException('First parameter must be a valid stream resource'); @@ -63,10 +58,6 @@ public function __construct($stream, $loop = null, $readChunkSize = null) throw new \RuntimeException('Unable to set stream resource to non-blocking mode'); } - if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1 - throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface'); - } - // Use unbuffered read operations on the underlying stream resource. // Reading chunks from the stream may otherwise leave unread bytes in // PHP's stream buffers which some event loop implementations do not diff --git a/deps/vendor/react/stream/src/ThroughStream.php b/deps/vendor/react/stream/src/ThroughStream.php index 3b4fbb780..6f73fb8f0 100644 --- a/deps/vendor/react/stream/src/ThroughStream.php +++ b/deps/vendor/react/stream/src/ThroughStream.php @@ -93,19 +93,16 @@ public function __construct($callback = null) public function pause() { - // only allow pause if still readable, false otherwise - $this->paused = $this->readable; + $this->paused = true; } public function resume() { - $this->paused = false; - - // emit drain event if previous write was paused (throttled) if ($this->drain) { $this->drain = false; $this->emit('drain'); } + $this->paused = false; } public function pipe(WritableStreamInterface $dest, array $options = array()) @@ -142,13 +139,12 @@ public function write($data) $this->emit('data', array($data)); - // emit drain event on next resume if currently paused (throttled) if ($this->paused) { $this->drain = true; + return false; } - // continue writing if still writable and not paused (throttled), false otherwise - return $this->writable && !$this->paused; + return true; } public function end($data = null) @@ -168,7 +164,7 @@ public function end($data = null) $this->readable = false; $this->writable = false; - $this->paused = false; + $this->paused = true; $this->drain = false; $this->emit('end'); @@ -183,10 +179,9 @@ public function close() $this->readable = false; $this->writable = false; - $this->paused = false; - $this->drain = false; - $this->closed = true; + $this->paused = true; + $this->drain = false; $this->callback = null; $this->emit('close'); diff --git a/deps/vendor/react/stream/src/WritableResourceStream.php b/deps/vendor/react/stream/src/WritableResourceStream.php index e3a7e74da..1af16b145 100644 --- a/deps/vendor/react/stream/src/WritableResourceStream.php +++ b/deps/vendor/react/stream/src/WritableResourceStream.php @@ -28,13 +28,7 @@ final class WritableResourceStream extends EventEmitter implements WritableStrea private $closed = false; private $data = ''; - /** - * @param resource $stream - * @param ?LoopInterface $loop - * @param ?int $writeBufferSoftLimit - * @param ?int $writeChunkSize - */ - public function __construct($stream, $loop = null, $writeBufferSoftLimit = null, $writeChunkSize = null) + public function __construct($stream, LoopInterface $loop = null, $writeBufferSoftLimit = null, $writeChunkSize = null) { if (!\is_resource($stream) || \get_resource_type($stream) !== "stream") { throw new \InvalidArgumentException('First parameter must be a valid stream resource'); @@ -52,10 +46,6 @@ public function __construct($stream, $loop = null, $writeBufferSoftLimit = null, throw new \RuntimeException('Unable to set stream resource to non-blocking mode'); } - if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1 - throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface'); - } - $this->stream = $stream; $this->loop = $loop ?: Loop::get(); $this->softLimit = ($writeBufferSoftLimit === null) ? 65536 : (int)$writeBufferSoftLimit; diff --git a/deps/vendor/react/stream/src/WritableStreamInterface.php b/deps/vendor/react/stream/src/WritableStreamInterface.php index e2625928c..9b5468023 100644 --- a/deps/vendor/react/stream/src/WritableStreamInterface.php +++ b/deps/vendor/react/stream/src/WritableStreamInterface.php @@ -196,7 +196,7 @@ public function isWritable(); * The stream SHOULD send a `drain` event once the buffer is ready to accept * more data. * - * Similarly, if the stream is not writable (already in a closed state) + * Similarly, if the the stream is not writable (already in a closed state) * it MUST NOT process the given `$data` and SHOULD return `false`, * indicating that the caller should stop sending data. * diff --git a/deps/vendor/ringcentral/psr7/.gitignore b/deps/vendor/ringcentral/psr7/.gitignore new file mode 100644 index 000000000..83ec41e24 --- /dev/null +++ b/deps/vendor/ringcentral/psr7/.gitignore @@ -0,0 +1,11 @@ +phpunit.xml +composer.phar +composer.lock +composer-test.lock +vendor/ +build/artifacts/ +artifacts/ +docs/_build +docs/*.pyc +.idea +.DS_STORE diff --git a/deps/vendor/ringcentral/psr7/.travis.yml b/deps/vendor/ringcentral/psr7/.travis.yml new file mode 100644 index 000000000..08f372132 --- /dev/null +++ b/deps/vendor/ringcentral/psr7/.travis.yml @@ -0,0 +1,21 @@ +language: php + +sudo: false + +install: + - travis_retry composer install --no-interaction --prefer-source + +script: make test + +matrix: + include: + - php: 5.3 + dist: precise + - php: 5.4 + - php: 5.5 + - php: 5.6 + - php: 7.0 + - php: hhvm + allow_failures: + - php: hhvm + fast_finish: true diff --git a/deps/vendor/ringcentral/psr7/CHANGELOG.md b/deps/vendor/ringcentral/psr7/CHANGELOG.md new file mode 100644 index 000000000..642dc9a4b --- /dev/null +++ b/deps/vendor/ringcentral/psr7/CHANGELOG.md @@ -0,0 +1,28 @@ +# CHANGELOG + +## 1.2.0 - 2015-08-15 + +* Body as `"0"` is now properly added to a response. +* Now allowing forward seeking in CachingStream. +* Now properly parsing HTTP requests that contain proxy targets in + `parse_request`. +* functions.php is now conditionally required. +* user-info is no longer dropped when resolving URIs. + +## 1.1.0 - 2015-06-24 + +* URIs can now be relative. +* `multipart/form-data` headers are now overridden case-insensitively. +* URI paths no longer encode the following characters because they are allowed + in URIs: "(", ")", "*", "!", "'" +* A port is no longer added to a URI when the scheme is missing and no port is + present. + +## 1.0.0 - 2015-05-19 + +Initial release. + +Currently unsupported: + +- `Psr\Http\Message\ServerRequestInterface` +- `Psr\Http\Message\UploadedFileInterface` diff --git a/deps/vendor/ringcentral/psr7/Dockerfile b/deps/vendor/ringcentral/psr7/Dockerfile new file mode 100644 index 000000000..846e8cfe7 --- /dev/null +++ b/deps/vendor/ringcentral/psr7/Dockerfile @@ -0,0 +1,5 @@ +FROM greensheep/dockerfiles-php-5.3 +RUN apt-get update -y +RUN apt-get install -y curl +RUN curl -sS https://getcomposer.org/installer | php +RUN mv composer.phar /usr/local/bin/composer \ No newline at end of file diff --git a/deps/vendor/ringcentral/psr7/LICENSE b/deps/vendor/ringcentral/psr7/LICENSE new file mode 100644 index 000000000..581d95f92 --- /dev/null +++ b/deps/vendor/ringcentral/psr7/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2015 Michael Dowling, https://github.com/mtdowling + +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: + +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, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/deps/vendor/ringcentral/psr7/Makefile b/deps/vendor/ringcentral/psr7/Makefile new file mode 100644 index 000000000..73a5c5b75 --- /dev/null +++ b/deps/vendor/ringcentral/psr7/Makefile @@ -0,0 +1,21 @@ +all: clean test + +test: + vendor/bin/phpunit $(TEST) + +coverage: + vendor/bin/phpunit --coverage-html=artifacts/coverage $(TEST) + +view-coverage: + open artifacts/coverage/index.html + +clean: + rm -rf artifacts/* + +.PHONY: docker-login +docker-login: + docker run -t -i -v $(shell pwd):/opt/psr7 ringcentral-psr7 /bin/bash + +.PHONY: docker-build +docker-build: + docker build -t ringcentral-psr7 . \ No newline at end of file diff --git a/deps/vendor/ringcentral/psr7/README.md b/deps/vendor/ringcentral/psr7/README.md new file mode 100644 index 000000000..b4a6061e7 --- /dev/null +++ b/deps/vendor/ringcentral/psr7/README.md @@ -0,0 +1,587 @@ +# PSR-7 Message Implementation + +This repository contains a partial [PSR-7](http://www.php-fig.org/psr/psr-7/) +message implementation, several stream decorators, and some helpful +functionality like query string parsing. Currently missing +ServerRequestInterface and UploadedFileInterface; a pull request for these features is welcome. + + +# Stream implementation + +This package comes with a number of stream implementations and stream +decorators. + + +## AppendStream + +`RingCentral\Psr7\AppendStream` + +Reads from multiple streams, one after the other. + +```php +use RingCentral\Psr7; + +$a = Psr7\stream_for('abc, '); +$b = Psr7\stream_for('123.'); +$composed = new Psr7\AppendStream([$a, $b]); + +$composed->addStream(Psr7\stream_for(' Above all listen to me'). + +echo $composed(); // abc, 123. Above all listen to me. +``` + + +## BufferStream + +`RingCentral\Psr7\BufferStream` + +Provides a buffer stream that can be written to to fill a buffer, and read +from to remove bytes from the buffer. + +This stream returns a "hwm" metadata value that tells upstream consumers +what the configured high water mark of the stream is, or the maximum +preferred size of the buffer. + +```php +use RingCentral\Psr7; + +// When more than 1024 bytes are in the buffer, it will begin returning +// false to writes. This is an indication that writers should slow down. +$buffer = new Psr7\BufferStream(1024); +``` + + +## CachingStream + +The CachingStream is used to allow seeking over previously read bytes on +non-seekable streams. This can be useful when transferring a non-seekable +entity body fails due to needing to rewind the stream (for example, resulting +from a redirect). Data that is read from the remote stream will be buffered in +a PHP temp stream so that previously read bytes are cached first in memory, +then on disk. + +```php +use RingCentral\Psr7; + +$original = Psr7\stream_for(fopen('http://www.google.com', 'r')); +$stream = new Psr7\CachingStream($original); + +$stream->read(1024); +echo $stream->tell(); +// 1024 + +$stream->seek(0); +echo $stream->tell(); +// 0 +``` + + +## DroppingStream + +`RingCentral\Psr7\DroppingStream` + +Stream decorator that begins dropping data once the size of the underlying +stream becomes too full. + +```php +use RingCentral\Psr7; + +// Create an empty stream +$stream = Psr7\stream_for(); + +// Start dropping data when the stream has more than 10 bytes +$dropping = new Psr7\DroppingStream($stream, 10); + +$stream->write('01234567890123456789'); +echo $stream; // 0123456789 +``` + + +## FnStream + +`RingCentral\Psr7\FnStream` + +Compose stream implementations based on a hash of functions. + +Allows for easy testing and extension of a provided stream without needing to +to create a concrete class for a simple extension point. + +```php + +use RingCentral\Psr7; + +$stream = Psr7\stream_for('hi'); +$fnStream = Psr7\FnStream::decorate($stream, [ + 'rewind' => function () use ($stream) { + echo 'About to rewind - '; + $stream->rewind(); + echo 'rewound!'; + } +]); + +$fnStream->rewind(); +// Outputs: About to rewind - rewound! +``` + + +## InflateStream + +`RingCentral\Psr7\InflateStream` + +Uses PHP's zlib.inflate filter to inflate deflate or gzipped content. + +This stream decorator skips the first 10 bytes of the given stream to remove +the gzip header, converts the provided stream to a PHP stream resource, +then appends the zlib.inflate filter. The stream is then converted back +to a Guzzle stream resource to be used as a Guzzle stream. + + +## LazyOpenStream + +`RingCentral\Psr7\LazyOpenStream` + +Lazily reads or writes to a file that is opened only after an IO operation +take place on the stream. + +```php +use RingCentral\Psr7; + +$stream = new Psr7\LazyOpenStream('/path/to/file', 'r'); +// The file has not yet been opened... + +echo $stream->read(10); +// The file is opened and read from only when needed. +``` + + +## LimitStream + +`RingCentral\Psr7\LimitStream` + +LimitStream can be used to read a subset or slice of an existing stream object. +This can be useful for breaking a large file into smaller pieces to be sent in +chunks (e.g. Amazon S3's multipart upload API). + +```php +use RingCentral\Psr7; + +$original = Psr7\stream_for(fopen('/tmp/test.txt', 'r+')); +echo $original->getSize(); +// >>> 1048576 + +// Limit the size of the body to 1024 bytes and start reading from byte 2048 +$stream = new Psr7\LimitStream($original, 1024, 2048); +echo $stream->getSize(); +// >>> 1024 +echo $stream->tell(); +// >>> 0 +``` + + +## MultipartStream + +`RingCentral\Psr7\MultipartStream` + +Stream that when read returns bytes for a streaming multipart or +multipart/form-data stream. + + +## NoSeekStream + +`RingCentral\Psr7\NoSeekStream` + +NoSeekStream wraps a stream and does not allow seeking. + +```php +use RingCentral\Psr7; + +$original = Psr7\stream_for('foo'); +$noSeek = new Psr7\NoSeekStream($original); + +echo $noSeek->read(3); +// foo +var_export($noSeek->isSeekable()); +// false +$noSeek->seek(0); +var_export($noSeek->read(3)); +// NULL +``` + + +## PumpStream + +`RingCentral\Psr7\PumpStream` + +Provides a read only stream that pumps data from a PHP callable. + +When invoking the provided callable, the PumpStream will pass the amount of +data requested to read to the callable. The callable can choose to ignore +this value and return fewer or more bytes than requested. Any extra data +returned by the provided callable is buffered internally until drained using +the read() function of the PumpStream. The provided callable MUST return +false when there is no more data to read. + + +## Implementing stream decorators + +Creating a stream decorator is very easy thanks to the +`RingCentral\Psr7\StreamDecoratorTrait`. This trait provides methods that +implement `Psr\Http\Message\StreamInterface` by proxying to an underlying +stream. Just `use` the `StreamDecoratorTrait` and implement your custom +methods. + +For example, let's say we wanted to call a specific function each time the last +byte is read from a stream. This could be implemented by overriding the +`read()` method. + +```php +use Psr\Http\Message\StreamInterface; +use RingCentral\Psr7\StreamDecoratorTrait; + +class EofCallbackStream implements StreamInterface +{ + use StreamDecoratorTrait; + + private $callback; + + public function __construct(StreamInterface $stream, callable $cb) + { + $this->stream = $stream; + $this->callback = $cb; + } + + public function read($length) + { + $result = $this->stream->read($length); + + // Invoke the callback when EOF is hit. + if ($this->eof()) { + call_user_func($this->callback); + } + + return $result; + } +} +``` + +This decorator could be added to any existing stream and used like so: + +```php +use RingCentral\Psr7; + +$original = Psr7\stream_for('foo'); + +$eofStream = new EofCallbackStream($original, function () { + echo 'EOF!'; +}); + +$eofStream->read(2); +$eofStream->read(1); +// echoes "EOF!" +$eofStream->seek(0); +$eofStream->read(3); +// echoes "EOF!" +``` + + +## PHP StreamWrapper + +You can use the `RingCentral\Psr7\StreamWrapper` class if you need to use a +PSR-7 stream as a PHP stream resource. + +Use the `RingCentral\Psr7\StreamWrapper::getResource()` method to create a PHP +stream from a PSR-7 stream. + +```php +use RingCentral\Psr7\StreamWrapper; + +$stream = RingCentral\Psr7\stream_for('hello!'); +$resource = StreamWrapper::getResource($stream); +echo fread($resource, 6); // outputs hello! +``` + + +# Function API + +There are various functions available under the `RingCentral\Psr7` namespace. + + +## `function str` + +`function str(MessageInterface $message)` + +Returns the string representation of an HTTP message. + +```php +$request = new RingCentral\Psr7\Request('GET', 'http://example.com'); +echo RingCentral\Psr7\str($request); +``` + + +## `function uri_for` + +`function uri_for($uri)` + +This function accepts a string or `Psr\Http\Message\UriInterface` and returns a +UriInterface for the given value. If the value is already a `UriInterface`, it +is returned as-is. + +```php +$uri = RingCentral\Psr7\uri_for('http://example.com'); +assert($uri === RingCentral\Psr7\uri_for($uri)); +``` + + +## `function stream_for` + +`function stream_for($resource = '', array $options = [])` + +Create a new stream based on the input type. + +Options is an associative array that can contain the following keys: + +* - metadata: Array of custom metadata. +* - size: Size of the stream. + +This method accepts the following `$resource` types: + +- `Psr\Http\Message\StreamInterface`: Returns the value as-is. +- `string`: Creates a stream object that uses the given string as the contents. +- `resource`: Creates a stream object that wraps the given PHP stream resource. +- `Iterator`: If the provided value implements `Iterator`, then a read-only + stream object will be created that wraps the given iterable. Each time the + stream is read from, data from the iterator will fill a buffer and will be + continuously called until the buffer is equal to the requested read size. + Subsequent read calls will first read from the buffer and then call `next` + on the underlying iterator until it is exhausted. +- `object` with `__toString()`: If the object has the `__toString()` method, + the object will be cast to a string and then a stream will be returned that + uses the string value. +- `NULL`: When `null` is passed, an empty stream object is returned. +- `callable` When a callable is passed, a read-only stream object will be + created that invokes the given callable. The callable is invoked with the + number of suggested bytes to read. The callable can return any number of + bytes, but MUST return `false` when there is no more data to return. The + stream object that wraps the callable will invoke the callable until the + number of requested bytes are available. Any additional bytes will be + buffered and used in subsequent reads. + +```php +$stream = RingCentral\Psr7\stream_for('foo'); +$stream = RingCentral\Psr7\stream_for(fopen('/path/to/file', 'r')); + +$generator function ($bytes) { + for ($i = 0; $i < $bytes; $i++) { + yield ' '; + } +} + +$stream = RingCentral\Psr7\stream_for($generator(100)); +``` + + +## `function parse_header` + +`function parse_header($header)` + +Parse an array of header values containing ";" separated data into an array of +associative arrays representing the header key value pair data of the header. +When a parameter does not contain a value, but just contains a key, this +function will inject a key with a '' string value. + + +## `function normalize_header` + +`function normalize_header($header)` + +Converts an array of header values that may contain comma separated headers +into an array of headers with no comma separated values. + + +## `function modify_request` + +`function modify_request(RequestInterface $request, array $changes)` + +Clone and modify a request with the given changes. This method is useful for +reducing the number of clones needed to mutate a message. + +The changes can be one of: + +- method: (string) Changes the HTTP method. +- set_headers: (array) Sets the given headers. +- remove_headers: (array) Remove the given headers. +- body: (mixed) Sets the given body. +- uri: (UriInterface) Set the URI. +- query: (string) Set the query string value of the URI. +- version: (string) Set the protocol version. + + +## `function rewind_body` + +`function rewind_body(MessageInterface $message)` + +Attempts to rewind a message body and throws an exception on failure. The body +of the message will only be rewound if a call to `tell()` returns a value other +than `0`. + + +## `function try_fopen` + +`function try_fopen($filename, $mode)` + +Safely opens a PHP stream resource using a filename. + +When fopen fails, PHP normally raises a warning. This function adds an error +handler that checks for errors and throws an exception instead. + + +## `function copy_to_string` + +`function copy_to_string(StreamInterface $stream, $maxLen = -1)` + +Copy the contents of a stream into a string until the given number of bytes +have been read. + + +## `function copy_to_stream` + +`function copy_to_stream(StreamInterface $source, StreamInterface $dest, $maxLen = -1)` + +Copy the contents of a stream into another stream until the given number of +bytes have been read. + + +## `function hash` + +`function hash(StreamInterface $stream, $algo, $rawOutput = false)` + +Calculate a hash of a Stream. This method reads the entire stream to calculate +a rolling hash (based on PHP's hash_init functions). + + +## `function readline` + +`function readline(StreamInterface $stream, $maxLength = null)` + +Read a line from the stream up to the maximum allowed buffer length. + + +## `function parse_request` + +`function parse_request($message)` + +Parses a request message string into a request object. + + +## `function parse_server_request` + +`function parse_server_request($message, array $serverParams = array())` + +Parses a request message string into a server-side request object. + + +## `function parse_response` + +`function parse_response($message)` + +Parses a response message string into a response object. + + +## `function parse_query` + +`function parse_query($str, $urlEncoding = true)` + +Parse a query string into an associative array. + +If multiple values are found for the same key, the value of that key value pair +will become an array. This function does not parse nested PHP style arrays into +an associative array (e.g., `foo[a]=1&foo[b]=2` will be parsed into +`['foo[a]' => '1', 'foo[b]' => '2']`). + + +## `function build_query` + +`function build_query(array $params, $encoding = PHP_QUERY_RFC3986)` + +Build a query string from an array of key value pairs. + +This function can use the return value of parseQuery() to build a query string. +This function does not modify the provided keys when an array is encountered +(like http_build_query would). + + +## `function mimetype_from_filename` + +`function mimetype_from_filename($filename)` + +Determines the mimetype of a file by looking at its extension. + + +## `function mimetype_from_extension` + +`function mimetype_from_extension($extension)` + +Maps a file extensions to a mimetype. + + +# Static URI methods + +The `RingCentral\Psr7\Uri` class has several static methods to manipulate URIs. + + +## `RingCentral\Psr7\Uri::removeDotSegments` + +`public static function removeDotSegments($path) -> UriInterface` + +Removes dot segments from a path and returns the new path. + +See http://tools.ietf.org/html/rfc3986#section-5.2.4 + + +## `RingCentral\Psr7\Uri::resolve` + +`public static function resolve(UriInterface $base, $rel) -> UriInterface` + +Resolve a base URI with a relative URI and return a new URI. + +See http://tools.ietf.org/html/rfc3986#section-5 + + +## `RingCentral\Psr7\Uri::withQueryValue` + +`public static function withQueryValue(UriInterface $uri, $key, $value) -> UriInterface` + +Create a new URI with a specific query string value. + +Any existing query string values that exactly match the provided key are +removed and replaced with the given key value pair. + +Note: this function will convert "=" to "%3D" and "&" to "%26". + + +## `RingCentral\Psr7\Uri::withoutQueryValue` + +`public static function withoutQueryValue(UriInterface $uri, $key, $value) -> UriInterface` + +Create a new URI with a specific query string value removed. + +Any existing query string values that exactly match the provided key are +removed. + +Note: this function will convert "=" to "%3D" and "&" to "%26". + + +## `RingCentral\Psr7\Uri::fromParts` + +`public static function fromParts(array $parts) -> UriInterface` + +Create a `RingCentral\Psr7\Uri` object from a hash of `parse_url` parts. + + +# Not Implemented + +A few aspects of PSR-7 are not implemented in this project. A pull request for +any of these features is welcome: + +- `Psr\Http\Message\ServerRequestInterface` +- `Psr\Http\Message\UploadedFileInterface` diff --git a/deps/vendor/ringcentral/psr7/composer.json b/deps/vendor/ringcentral/psr7/composer.json new file mode 100644 index 000000000..4955053e9 --- /dev/null +++ b/deps/vendor/ringcentral/psr7/composer.json @@ -0,0 +1,35 @@ +{ + "name": "ringcentral/psr7", + "type": "library", + "description": "PSR-7 message implementation", + "keywords": ["message", "stream", "http", "uri"], + "license": "MIT", + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "require": { + "php": ">=5.3", + "psr/http-message": "~1.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "autoload": { + "psr-4": { + "RingCentral\\Psr7\\": "src/" + }, + "files": ["src/functions_include.php"] + }, + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + } +} diff --git a/deps/vendor/ringcentral/psr7/phpunit.xml.dist b/deps/vendor/ringcentral/psr7/phpunit.xml.dist new file mode 100644 index 000000000..500cd53a0 --- /dev/null +++ b/deps/vendor/ringcentral/psr7/phpunit.xml.dist @@ -0,0 +1,17 @@ + + + + + tests + + + + + src + + src/ + + + + diff --git a/deps/vendor/ringcentral/psr7/src/AppendStream.php b/deps/vendor/ringcentral/psr7/src/AppendStream.php new file mode 100644 index 000000000..8b8df6f4c --- /dev/null +++ b/deps/vendor/ringcentral/psr7/src/AppendStream.php @@ -0,0 +1,233 @@ +addStream($stream); + } + } + + public function __toString() + { + try { + $this->rewind(); + return $this->getContents(); + } catch (\Exception $e) { + return ''; + } + } + + /** + * Add a stream to the AppendStream + * + * @param StreamInterface $stream Stream to append. Must be readable. + * + * @throws \InvalidArgumentException if the stream is not readable + */ + public function addStream(StreamInterface $stream) + { + if (!$stream->isReadable()) { + throw new \InvalidArgumentException('Each stream must be readable'); + } + + // The stream is only seekable if all streams are seekable + if (!$stream->isSeekable()) { + $this->seekable = false; + } + + $this->streams[] = $stream; + } + + public function getContents() + { + return copy_to_string($this); + } + + /** + * Closes each attached stream. + * + * {@inheritdoc} + */ + public function close() + { + $this->pos = $this->current = 0; + + foreach ($this->streams as $stream) { + $stream->close(); + } + + $this->streams = array(); + } + + /** + * Detaches each attached stream + * + * {@inheritdoc} + */ + public function detach() + { + $this->close(); + $this->detached = true; + } + + public function tell() + { + return $this->pos; + } + + /** + * Tries to calculate the size by adding the size of each stream. + * + * If any of the streams do not return a valid number, then the size of the + * append stream cannot be determined and null is returned. + * + * {@inheritdoc} + */ + public function getSize() + { + $size = 0; + + foreach ($this->streams as $stream) { + $s = $stream->getSize(); + if ($s === null) { + return null; + } + $size += $s; + } + + return $size; + } + + public function eof() + { + return !$this->streams || + ($this->current >= count($this->streams) - 1 && + $this->streams[$this->current]->eof()); + } + + public function rewind() + { + $this->seek(0); + } + + /** + * Attempts to seek to the given position. Only supports SEEK_SET. + * + * {@inheritdoc} + */ + public function seek($offset, $whence = SEEK_SET) + { + if (!$this->seekable) { + throw new \RuntimeException('This AppendStream is not seekable'); + } elseif ($whence !== SEEK_SET) { + throw new \RuntimeException('The AppendStream can only seek with SEEK_SET'); + } + + $this->pos = $this->current = 0; + + // Rewind each stream + foreach ($this->streams as $i => $stream) { + try { + $stream->rewind(); + } catch (\Exception $e) { + throw new \RuntimeException('Unable to seek stream ' + . $i . ' of the AppendStream', 0, $e); + } + } + + // Seek to the actual position by reading from each stream + while ($this->pos < $offset && !$this->eof()) { + $result = $this->read(min(8096, $offset - $this->pos)); + if ($result === '') { + break; + } + } + } + + /** + * Reads from all of the appended streams until the length is met or EOF. + * + * {@inheritdoc} + */ + public function read($length) + { + $buffer = ''; + $total = count($this->streams) - 1; + $remaining = $length; + $progressToNext = false; + + while ($remaining > 0) { + + // Progress to the next stream if needed. + if ($progressToNext || $this->streams[$this->current]->eof()) { + $progressToNext = false; + if ($this->current === $total) { + break; + } + $this->current++; + } + + $result = $this->streams[$this->current]->read($remaining); + + // Using a loose comparison here to match on '', false, and null + if ($result == null) { + $progressToNext = true; + continue; + } + + $buffer .= $result; + $remaining = $length - strlen($buffer); + } + + $this->pos += strlen($buffer); + + return $buffer; + } + + public function isReadable() + { + return true; + } + + public function isWritable() + { + return false; + } + + public function isSeekable() + { + return $this->seekable; + } + + public function write($string) + { + throw new \RuntimeException('Cannot write to an AppendStream'); + } + + public function getMetadata($key = null) + { + return $key ? null : array(); + } +} diff --git a/deps/vendor/ringcentral/psr7/src/BufferStream.php b/deps/vendor/ringcentral/psr7/src/BufferStream.php new file mode 100644 index 000000000..a1e236def --- /dev/null +++ b/deps/vendor/ringcentral/psr7/src/BufferStream.php @@ -0,0 +1,137 @@ +hwm = $hwm; + } + + public function __toString() + { + return $this->getContents(); + } + + public function getContents() + { + $buffer = $this->buffer; + $this->buffer = ''; + + return $buffer; + } + + public function close() + { + $this->buffer = ''; + } + + public function detach() + { + $this->close(); + } + + public function getSize() + { + return strlen($this->buffer); + } + + public function isReadable() + { + return true; + } + + public function isWritable() + { + return true; + } + + public function isSeekable() + { + return false; + } + + public function rewind() + { + $this->seek(0); + } + + public function seek($offset, $whence = SEEK_SET) + { + throw new \RuntimeException('Cannot seek a BufferStream'); + } + + public function eof() + { + return strlen($this->buffer) === 0; + } + + public function tell() + { + throw new \RuntimeException('Cannot determine the position of a BufferStream'); + } + + /** + * Reads data from the buffer. + */ + public function read($length) + { + $currentLength = strlen($this->buffer); + + if ($length >= $currentLength) { + // No need to slice the buffer because we don't have enough data. + $result = $this->buffer; + $this->buffer = ''; + } else { + // Slice up the result to provide a subset of the buffer. + $result = substr($this->buffer, 0, $length); + $this->buffer = substr($this->buffer, $length); + } + + return $result; + } + + /** + * Writes data to the buffer. + */ + public function write($string) + { + $this->buffer .= $string; + + // TODO: What should happen here? + if (strlen($this->buffer) >= $this->hwm) { + return false; + } + + return strlen($string); + } + + public function getMetadata($key = null) + { + if ($key == 'hwm') { + return $this->hwm; + } + + return $key ? null : array(); + } +} diff --git a/deps/vendor/ringcentral/psr7/src/CachingStream.php b/deps/vendor/ringcentral/psr7/src/CachingStream.php new file mode 100644 index 000000000..ce3aca8bb --- /dev/null +++ b/deps/vendor/ringcentral/psr7/src/CachingStream.php @@ -0,0 +1,135 @@ +remoteStream = $stream; + parent::__construct($target ?: new Stream(fopen('php://temp', 'r+'))); + } + + public function getSize() + { + return max($this->stream->getSize(), $this->remoteStream->getSize()); + } + + public function rewind() + { + $this->seek(0); + } + + public function seek($offset, $whence = SEEK_SET) + { + if ($whence == SEEK_SET) { + $byte = $offset; + } elseif ($whence == SEEK_CUR) { + $byte = $offset + $this->tell(); + } elseif ($whence == SEEK_END) { + $size = $this->remoteStream->getSize(); + if ($size === null) { + $size = $this->cacheEntireStream(); + } + // Because 0 is the first byte, we seek to size - 1. + $byte = $size - 1 - $offset; + } else { + throw new \InvalidArgumentException('Invalid whence'); + } + + $diff = $byte - $this->stream->getSize(); + + if ($diff > 0) { + // If the seek byte is greater the number of read bytes, then read + // the difference of bytes to cache the bytes and inherently seek. + $this->read($diff); + } else { + // We can just do a normal seek since we've already seen this byte. + $this->stream->seek($byte); + } + } + + public function read($length) + { + // Perform a regular read on any previously read data from the buffer + $data = $this->stream->read($length); + $remaining = $length - strlen($data); + + // More data was requested so read from the remote stream + if ($remaining) { + // If data was written to the buffer in a position that would have + // been filled from the remote stream, then we must skip bytes on + // the remote stream to emulate overwriting bytes from that + // position. This mimics the behavior of other PHP stream wrappers. + $remoteData = $this->remoteStream->read( + $remaining + $this->skipReadBytes + ); + + if ($this->skipReadBytes) { + $len = strlen($remoteData); + $remoteData = substr($remoteData, $this->skipReadBytes); + $this->skipReadBytes = max(0, $this->skipReadBytes - $len); + } + + $data .= $remoteData; + $this->stream->write($remoteData); + } + + return $data; + } + + public function write($string) + { + // When appending to the end of the currently read stream, you'll want + // to skip bytes from being read from the remote stream to emulate + // other stream wrappers. Basically replacing bytes of data of a fixed + // length. + $overflow = (strlen($string) + $this->tell()) - $this->remoteStream->tell(); + if ($overflow > 0) { + $this->skipReadBytes += $overflow; + } + + return $this->stream->write($string); + } + + public function eof() + { + return $this->stream->eof() && $this->remoteStream->eof(); + } + + /** + * Close both the remote stream and buffer stream + */ + public function close() + { + $this->remoteStream->close() && $this->stream->close(); + } + + private function cacheEntireStream() + { + $target = new FnStream(array('write' => 'strlen')); + copy_to_stream($this, $target); + + return $this->tell(); + } +} diff --git a/deps/vendor/ringcentral/psr7/src/DroppingStream.php b/deps/vendor/ringcentral/psr7/src/DroppingStream.php new file mode 100644 index 000000000..3a34d38fd --- /dev/null +++ b/deps/vendor/ringcentral/psr7/src/DroppingStream.php @@ -0,0 +1,41 @@ +maxLength = $maxLength; + } + + public function write($string) + { + $diff = $this->maxLength - $this->stream->getSize(); + + // Begin returning 0 when the underlying stream is too large. + if ($diff <= 0) { + return 0; + } + + // Write the stream or a subset of the stream if needed. + if (strlen($string) < $diff) { + return $this->stream->write($string); + } + + return $this->stream->write(substr($string, 0, $diff)); + } +} diff --git a/deps/vendor/ringcentral/psr7/src/FnStream.php b/deps/vendor/ringcentral/psr7/src/FnStream.php new file mode 100644 index 000000000..f78dc8bab --- /dev/null +++ b/deps/vendor/ringcentral/psr7/src/FnStream.php @@ -0,0 +1,163 @@ +methods = $methods; + + // Create the functions on the class + foreach ($methods as $name => $fn) { + $this->{'_fn_' . $name} = $fn; + } + } + + /** + * Lazily determine which methods are not implemented. + * @throws \BadMethodCallException + */ + public function __get($name) + { + throw new \BadMethodCallException(str_replace('_fn_', '', $name) + . '() is not implemented in the FnStream'); + } + + /** + * The close method is called on the underlying stream only if possible. + */ + public function __destruct() + { + if (isset($this->_fn_close)) { + call_user_func($this->_fn_close); + } + } + + /** + * Adds custom functionality to an underlying stream by intercepting + * specific method calls. + * + * @param StreamInterface $stream Stream to decorate + * @param array $methods Hash of method name to a closure + * + * @return FnStream + */ + public static function decorate(StreamInterface $stream, array $methods) + { + // If any of the required methods were not provided, then simply + // proxy to the decorated stream. + foreach (array_diff(self::$slots, array_keys($methods)) as $diff) { + $methods[$diff] = array($stream, $diff); + } + + return new self($methods); + } + + public function __toString() + { + return call_user_func($this->_fn___toString); + } + + public function close() + { + return call_user_func($this->_fn_close); + } + + public function detach() + { + return call_user_func($this->_fn_detach); + } + + public function getSize() + { + return call_user_func($this->_fn_getSize); + } + + public function tell() + { + return call_user_func($this->_fn_tell); + } + + public function eof() + { + return call_user_func($this->_fn_eof); + } + + public function isSeekable() + { + return call_user_func($this->_fn_isSeekable); + } + + public function rewind() + { + call_user_func($this->_fn_rewind); + } + + public function seek($offset, $whence = SEEK_SET) + { + call_user_func($this->_fn_seek, $offset, $whence); + } + + public function isWritable() + { + return call_user_func($this->_fn_isWritable); + } + + public function write($string) + { + return call_user_func($this->_fn_write, $string); + } + + public function isReadable() + { + return call_user_func($this->_fn_isReadable); + } + + public function read($length) + { + return call_user_func($this->_fn_read, $length); + } + + public function getContents() + { + return call_user_func($this->_fn_getContents); + } + + public function getMetadata($key = null) + { + return call_user_func($this->_fn_getMetadata, $key); + } +} diff --git a/deps/vendor/ringcentral/psr7/src/InflateStream.php b/deps/vendor/ringcentral/psr7/src/InflateStream.php new file mode 100644 index 000000000..c718002ba --- /dev/null +++ b/deps/vendor/ringcentral/psr7/src/InflateStream.php @@ -0,0 +1,27 @@ +filename = $filename; + $this->mode = $mode; + parent::__construct(); + } + + /** + * Creates the underlying stream lazily when required. + * + * @return StreamInterface + */ + protected function createStream() + { + return stream_for(try_fopen($this->filename, $this->mode)); + } +} diff --git a/deps/vendor/ringcentral/psr7/src/LimitStream.php b/deps/vendor/ringcentral/psr7/src/LimitStream.php new file mode 100644 index 000000000..57eeca9dc --- /dev/null +++ b/deps/vendor/ringcentral/psr7/src/LimitStream.php @@ -0,0 +1,154 @@ +setLimit($limit); + $this->setOffset($offset); + } + + public function eof() + { + // Always return true if the underlying stream is EOF + if ($this->stream->eof()) { + return true; + } + + // No limit and the underlying stream is not at EOF + if ($this->limit == -1) { + return false; + } + + return $this->stream->tell() >= $this->offset + $this->limit; + } + + /** + * Returns the size of the limited subset of data + * {@inheritdoc} + */ + public function getSize() + { + if (null === ($length = $this->stream->getSize())) { + return null; + } elseif ($this->limit == -1) { + return $length - $this->offset; + } else { + return min($this->limit, $length - $this->offset); + } + } + + /** + * Allow for a bounded seek on the read limited stream + * {@inheritdoc} + */ + public function seek($offset, $whence = SEEK_SET) + { + if ($whence !== SEEK_SET || $offset < 0) { + throw new \RuntimeException(sprintf( + 'Cannot seek to offset % with whence %s', + $offset, + $whence + )); + } + + $offset += $this->offset; + + if ($this->limit !== -1) { + if ($offset > $this->offset + $this->limit) { + $offset = $this->offset + $this->limit; + } + } + + $this->stream->seek($offset); + } + + /** + * Give a relative tell() + * {@inheritdoc} + */ + public function tell() + { + return $this->stream->tell() - $this->offset; + } + + /** + * Set the offset to start limiting from + * + * @param int $offset Offset to seek to and begin byte limiting from + * + * @throws \RuntimeException if the stream cannot be seeked. + */ + public function setOffset($offset) + { + $current = $this->stream->tell(); + + if ($current !== $offset) { + // If the stream cannot seek to the offset position, then read to it + if ($this->stream->isSeekable()) { + $this->stream->seek($offset); + } elseif ($current > $offset) { + throw new \RuntimeException("Could not seek to stream offset $offset"); + } else { + $this->stream->read($offset - $current); + } + } + + $this->offset = $offset; + } + + /** + * Set the limit of bytes that the decorator allows to be read from the + * stream. + * + * @param int $limit Number of bytes to allow to be read from the stream. + * Use -1 for no limit. + */ + public function setLimit($limit) + { + $this->limit = $limit; + } + + public function read($length) + { + if ($this->limit == -1) { + return $this->stream->read($length); + } + + // Check if the current position is less than the total allowed + // bytes + original offset + $remaining = ($this->offset + $this->limit) - $this->stream->tell(); + if ($remaining > 0) { + // Only return the amount of requested data, ensuring that the byte + // limit is not exceeded + return $this->stream->read(min($remaining, $length)); + } + + return ''; + } +} diff --git a/deps/vendor/ringcentral/psr7/src/MessageTrait.php b/deps/vendor/ringcentral/psr7/src/MessageTrait.php new file mode 100644 index 000000000..9330bcba7 --- /dev/null +++ b/deps/vendor/ringcentral/psr7/src/MessageTrait.php @@ -0,0 +1,167 @@ +protocol; + } + + public function withProtocolVersion($version) + { + if ($this->protocol === $version) { + return $this; + } + + $new = clone $this; + $new->protocol = $version; + return $new; + } + + public function getHeaders() + { + return $this->headerLines; + } + + public function hasHeader($header) + { + return isset($this->headers[strtolower($header)]); + } + + public function getHeader($header) + { + $name = strtolower($header); + return isset($this->headers[$name]) ? $this->headers[$name] : array(); + } + + public function getHeaderLine($header) + { + return implode(', ', $this->getHeader($header)); + } + + public function withHeader($header, $value) + { + $new = clone $this; + $header = trim($header); + $name = strtolower($header); + + if (!is_array($value)) { + $new->headers[$name] = array(trim($value)); + } else { + $new->headers[$name] = $value; + foreach ($new->headers[$name] as &$v) { + $v = trim($v); + } + } + + // Remove the header lines. + foreach (array_keys($new->headerLines) as $key) { + if (strtolower($key) === $name) { + unset($new->headerLines[$key]); + } + } + + // Add the header line. + $new->headerLines[$header] = $new->headers[$name]; + + return $new; + } + + public function withAddedHeader($header, $value) + { + if (!$this->hasHeader($header)) { + return $this->withHeader($header, $value); + } + + $header = trim($header); + $name = strtolower($header); + + $value = (array) $value; + foreach ($value as &$v) { + $v = trim($v); + } + + $new = clone $this; + $new->headers[$name] = array_merge($new->headers[$name], $value); + $new->headerLines[$header] = array_merge($new->headerLines[$header], $value); + + return $new; + } + + public function withoutHeader($header) + { + if (!$this->hasHeader($header)) { + return $this; + } + + $new = clone $this; + $name = strtolower($header); + unset($new->headers[$name]); + + foreach (array_keys($new->headerLines) as $key) { + if (strtolower($key) === $name) { + unset($new->headerLines[$key]); + } + } + + return $new; + } + + public function getBody() + { + if (!$this->stream) { + $this->stream = stream_for(''); + } + + return $this->stream; + } + + public function withBody(StreamInterface $body) + { + if ($body === $this->stream) { + return $this; + } + + $new = clone $this; + $new->stream = $body; + return $new; + } + + protected function setHeaders(array $headers) + { + $this->headerLines = $this->headers = array(); + foreach ($headers as $header => $value) { + $header = trim($header); + $name = strtolower($header); + if (!is_array($value)) { + $value = trim($value); + $this->headers[$name][] = $value; + $this->headerLines[$header][] = $value; + } else { + foreach ($value as $v) { + $v = trim($v); + $this->headers[$name][] = $v; + $this->headerLines[$header][] = $v; + } + } + } + } +} diff --git a/deps/vendor/ringcentral/psr7/src/MultipartStream.php b/deps/vendor/ringcentral/psr7/src/MultipartStream.php new file mode 100644 index 000000000..8c5e5bc3d --- /dev/null +++ b/deps/vendor/ringcentral/psr7/src/MultipartStream.php @@ -0,0 +1,152 @@ +boundary = $boundary ?: uniqid(); + parent::__construct($this->createStream($elements)); + } + + /** + * Get the boundary + * + * @return string + */ + public function getBoundary() + { + return $this->boundary; + } + + public function isWritable() + { + return false; + } + + /** + * Get the headers needed before transferring the content of a POST file + */ + private function getHeaders(array $headers) + { + $str = ''; + foreach ($headers as $key => $value) { + $str .= "{$key}: {$value}\r\n"; + } + + return "--{$this->boundary}\r\n" . trim($str) . "\r\n\r\n"; + } + + /** + * Create the aggregate stream that will be used to upload the POST data + */ + protected function createStream(array $elements) + { + $stream = new AppendStream(); + + foreach ($elements as $element) { + $this->addElement($stream, $element); + } + + // Add the trailing boundary with CRLF + $stream->addStream(stream_for("--{$this->boundary}--\r\n")); + + return $stream; + } + + private function addElement(AppendStream $stream, array $element) + { + foreach (array('contents', 'name') as $key) { + if (!array_key_exists($key, $element)) { + throw new \InvalidArgumentException("A '{$key}' key is required"); + } + } + + $element['contents'] = stream_for($element['contents']); + + if (empty($element['filename'])) { + $uri = $element['contents']->getMetadata('uri'); + if (substr($uri, 0, 6) !== 'php://') { + $element['filename'] = $uri; + } + } + + list($body, $headers) = $this->createElement( + $element['name'], + $element['contents'], + isset($element['filename']) ? $element['filename'] : null, + isset($element['headers']) ? $element['headers'] : array() + ); + + $stream->addStream(stream_for($this->getHeaders($headers))); + $stream->addStream($body); + $stream->addStream(stream_for("\r\n")); + } + + /** + * @return array + */ + private function createElement($name, $stream, $filename, array $headers) + { + // Set a default content-disposition header if one was no provided + $disposition = $this->getHeader($headers, 'content-disposition'); + if (!$disposition) { + $headers['Content-Disposition'] = $filename + ? sprintf('form-data; name="%s"; filename="%s"', + $name, + basename($filename)) + : "form-data; name=\"{$name}\""; + } + + // Set a default content-length header if one was no provided + $length = $this->getHeader($headers, 'content-length'); + if (!$length) { + if ($length = $stream->getSize()) { + $headers['Content-Length'] = (string) $length; + } + } + + // Set a default Content-Type if one was not supplied + $type = $this->getHeader($headers, 'content-type'); + if (!$type && $filename) { + if ($type = mimetype_from_filename($filename)) { + $headers['Content-Type'] = $type; + } + } + + return array($stream, $headers); + } + + private function getHeader(array $headers, $key) + { + $lowercaseHeader = strtolower($key); + foreach ($headers as $k => $v) { + if (strtolower($k) === $lowercaseHeader) { + return $v; + } + } + + return null; + } +} diff --git a/deps/vendor/ringcentral/psr7/src/NoSeekStream.php b/deps/vendor/ringcentral/psr7/src/NoSeekStream.php new file mode 100644 index 000000000..328fdda40 --- /dev/null +++ b/deps/vendor/ringcentral/psr7/src/NoSeekStream.php @@ -0,0 +1,21 @@ +source = $source; + $this->size = isset($options['size']) ? $options['size'] : null; + $this->metadata = isset($options['metadata']) ? $options['metadata'] : array(); + $this->buffer = new BufferStream(); + } + + public function __toString() + { + try { + return copy_to_string($this); + } catch (\Exception $e) { + return ''; + } + } + + public function close() + { + $this->detach(); + } + + public function detach() + { + $this->tellPos = false; + $this->source = null; + } + + public function getSize() + { + return $this->size; + } + + public function tell() + { + return $this->tellPos; + } + + public function eof() + { + return !$this->source; + } + + public function isSeekable() + { + return false; + } + + public function rewind() + { + $this->seek(0); + } + + public function seek($offset, $whence = SEEK_SET) + { + throw new \RuntimeException('Cannot seek a PumpStream'); + } + + public function isWritable() + { + return false; + } + + public function write($string) + { + throw new \RuntimeException('Cannot write to a PumpStream'); + } + + public function isReadable() + { + return true; + } + + public function read($length) + { + $data = $this->buffer->read($length); + $readLen = strlen($data); + $this->tellPos += $readLen; + $remaining = $length - $readLen; + + if ($remaining) { + $this->pump($remaining); + $data .= $this->buffer->read($remaining); + $this->tellPos += strlen($data) - $readLen; + } + + return $data; + } + + public function getContents() + { + $result = ''; + while (!$this->eof()) { + $result .= $this->read(1000000); + } + + return $result; + } + + public function getMetadata($key = null) + { + if (!$key) { + return $this->metadata; + } + + return isset($this->metadata[$key]) ? $this->metadata[$key] : null; + } + + private function pump($length) + { + if ($this->source) { + do { + $data = call_user_func($this->source, $length); + if ($data === false || $data === null) { + $this->source = null; + return; + } + $this->buffer->write($data); + $length -= strlen($data); + } while ($length > 0); + } + } +} diff --git a/deps/vendor/ringcentral/psr7/src/Request.php b/deps/vendor/ringcentral/psr7/src/Request.php new file mode 100644 index 000000000..bb0f2fc28 --- /dev/null +++ b/deps/vendor/ringcentral/psr7/src/Request.php @@ -0,0 +1,146 @@ +method = strtoupper($method); + $this->uri = $uri; + $this->setHeaders($headers); + $this->protocol = $protocolVersion; + + $host = $uri->getHost(); + if ($host && !$this->hasHeader('Host')) { + $this->updateHostFromUri($host); + } + + if ($body) { + $this->stream = stream_for($body); + } + } + + public function getRequestTarget() + { + if ($this->requestTarget !== null) { + return $this->requestTarget; + } + + $target = $this->uri->getPath(); + if ($target == null) { + $target = '/'; + } + if ($this->uri->getQuery()) { + $target .= '?' . $this->uri->getQuery(); + } + + return $target; + } + + public function withRequestTarget($requestTarget) + { + if (preg_match('#\s#', $requestTarget)) { + throw new InvalidArgumentException( + 'Invalid request target provided; cannot contain whitespace' + ); + } + + $new = clone $this; + $new->requestTarget = $requestTarget; + return $new; + } + + public function getMethod() + { + return $this->method; + } + + public function withMethod($method) + { + $new = clone $this; + $new->method = strtoupper($method); + return $new; + } + + public function getUri() + { + return $this->uri; + } + + public function withUri(UriInterface $uri, $preserveHost = false) + { + if ($uri === $this->uri) { + return $this; + } + + $new = clone $this; + $new->uri = $uri; + + if (!$preserveHost) { + if ($host = $uri->getHost()) { + $new->updateHostFromUri($host); + } + } + + return $new; + } + + public function withHeader($header, $value) + { + /** @var Request $newInstance */ + $newInstance = parent::withHeader($header, $value); + return $newInstance; + } + + private function updateHostFromUri($host) + { + // Ensure Host is the first header. + // See: http://tools.ietf.org/html/rfc7230#section-5.4 + if ($port = $this->uri->getPort()) { + $host .= ':' . $port; + } + + $this->headerLines = array('Host' => array($host)) + $this->headerLines; + $this->headers = array('host' => array($host)) + $this->headers; + } +} diff --git a/deps/vendor/ringcentral/psr7/src/Response.php b/deps/vendor/ringcentral/psr7/src/Response.php new file mode 100644 index 000000000..a6d94516b --- /dev/null +++ b/deps/vendor/ringcentral/psr7/src/Response.php @@ -0,0 +1,129 @@ + 'Continue', + 101 => 'Switching Protocols', + 102 => 'Processing', + 200 => 'OK', + 201 => 'Created', + 202 => 'Accepted', + 203 => 'Non-Authoritative Information', + 204 => 'No Content', + 205 => 'Reset Content', + 206 => 'Partial Content', + 207 => 'Multi-status', + 208 => 'Already Reported', + 300 => 'Multiple Choices', + 301 => 'Moved Permanently', + 302 => 'Found', + 303 => 'See Other', + 304 => 'Not Modified', + 305 => 'Use Proxy', + 306 => 'Switch Proxy', + 307 => 'Temporary Redirect', + 400 => 'Bad Request', + 401 => 'Unauthorized', + 402 => 'Payment Required', + 403 => 'Forbidden', + 404 => 'Not Found', + 405 => 'Method Not Allowed', + 406 => 'Not Acceptable', + 407 => 'Proxy Authentication Required', + 408 => 'Request Time-out', + 409 => 'Conflict', + 410 => 'Gone', + 411 => 'Length Required', + 412 => 'Precondition Failed', + 413 => 'Request Entity Too Large', + 414 => 'Request-URI Too Large', + 415 => 'Unsupported Media Type', + 416 => 'Requested range not satisfiable', + 417 => 'Expectation Failed', + 418 => 'I\'m a teapot', + 422 => 'Unprocessable Entity', + 423 => 'Locked', + 424 => 'Failed Dependency', + 425 => 'Unordered Collection', + 426 => 'Upgrade Required', + 428 => 'Precondition Required', + 429 => 'Too Many Requests', + 431 => 'Request Header Fields Too Large', + 500 => 'Internal Server Error', + 501 => 'Not Implemented', + 502 => 'Bad Gateway', + 503 => 'Service Unavailable', + 504 => 'Gateway Time-out', + 505 => 'HTTP Version not supported', + 506 => 'Variant Also Negotiates', + 507 => 'Insufficient Storage', + 508 => 'Loop Detected', + 511 => 'Network Authentication Required', + ); + + /** @var null|string */ + private $reasonPhrase = ''; + + /** @var int */ + private $statusCode = 200; + + /** + * @param int $status Status code for the response, if any. + * @param array $headers Headers for the response, if any. + * @param mixed $body Stream body. + * @param string $version Protocol version. + * @param string $reason Reason phrase (a default will be used if possible). + */ + public function __construct( + $status = 200, + array $headers = array(), + $body = null, + $version = '1.1', + $reason = null + ) { + $this->statusCode = (int) $status; + + if ($body !== null) { + $this->stream = stream_for($body); + } + + $this->setHeaders($headers); + if (!$reason && isset(self::$phrases[$this->statusCode])) { + $this->reasonPhrase = self::$phrases[$status]; + } else { + $this->reasonPhrase = (string) $reason; + } + + $this->protocol = $version; + } + + public function getStatusCode() + { + return $this->statusCode; + } + + public function getReasonPhrase() + { + return $this->reasonPhrase; + } + + public function withStatus($code, $reasonPhrase = '') + { + $new = clone $this; + $new->statusCode = (int) $code; + if (!$reasonPhrase && isset(self::$phrases[$new->statusCode])) { + $reasonPhrase = self::$phrases[$new->statusCode]; + } + $new->reasonPhrase = $reasonPhrase; + return $new; + } +} diff --git a/deps/vendor/ringcentral/psr7/src/ServerRequest.php b/deps/vendor/ringcentral/psr7/src/ServerRequest.php new file mode 100644 index 000000000..8408a0936 --- /dev/null +++ b/deps/vendor/ringcentral/psr7/src/ServerRequest.php @@ -0,0 +1,122 @@ +serverParams = $serverParams; + } + + public function getServerParams() + { + return $this->serverParams; + } + + public function getCookieParams() + { + return $this->cookies; + } + + public function withCookieParams(array $cookies) + { + $new = clone $this; + $new->cookies = $cookies; + return $new; + } + + public function getQueryParams() + { + return $this->queryParams; + } + + public function withQueryParams(array $query) + { + $new = clone $this; + $new->queryParams = $query; + return $new; + } + + public function getUploadedFiles() + { + return $this->fileParams; + } + + public function withUploadedFiles(array $uploadedFiles) + { + $new = clone $this; + $new->fileParams = $uploadedFiles; + return $new; + } + + public function getParsedBody() + { + return $this->parsedBody; + } + + public function withParsedBody($data) + { + $new = clone $this; + $new->parsedBody = $data; + return $new; + } + + public function getAttributes() + { + return $this->attributes; + } + + public function getAttribute($name, $default = null) + { + if (!array_key_exists($name, $this->attributes)) { + return $default; + } + return $this->attributes[$name]; + } + + public function withAttribute($name, $value) + { + $new = clone $this; + $new->attributes[$name] = $value; + return $new; + } + + public function withoutAttribute($name) + { + $new = clone $this; + unset($new->attributes[$name]); + return $new; + } +} diff --git a/deps/vendor/ringcentral/psr7/src/Stream.php b/deps/vendor/ringcentral/psr7/src/Stream.php new file mode 100644 index 000000000..0a0157c53 --- /dev/null +++ b/deps/vendor/ringcentral/psr7/src/Stream.php @@ -0,0 +1,245 @@ + array( + 'r' => true, 'w+' => true, 'r+' => true, 'x+' => true, 'c+' => true, + 'rb' => true, 'w+b' => true, 'r+b' => true, 'x+b' => true, + 'c+b' => true, 'rt' => true, 'w+t' => true, 'r+t' => true, + 'x+t' => true, 'c+t' => true, 'a+' => true + ), + 'write' => array( + 'w' => true, 'w+' => true, 'rw' => true, 'r+' => true, 'x+' => true, + 'c+' => true, 'wb' => true, 'w+b' => true, 'r+b' => true, + 'x+b' => true, 'c+b' => true, 'w+t' => true, 'r+t' => true, + 'x+t' => true, 'c+t' => true, 'a' => true, 'a+' => true + ) + ); + + /** + * This constructor accepts an associative array of options. + * + * - size: (int) If a read stream would otherwise have an indeterminate + * size, but the size is known due to foreknownledge, then you can + * provide that size, in bytes. + * - metadata: (array) Any additional metadata to return when the metadata + * of the stream is accessed. + * + * @param resource $stream Stream resource to wrap. + * @param array $options Associative array of options. + * + * @throws \InvalidArgumentException if the stream is not a stream resource + */ + public function __construct($stream, $options = array()) + { + if (!is_resource($stream)) { + throw new \InvalidArgumentException('Stream must be a resource'); + } + + if (isset($options['size'])) { + $this->size = $options['size']; + } + + $this->customMetadata = isset($options['metadata']) + ? $options['metadata'] + : array(); + + $this->stream = $stream; + $meta = stream_get_meta_data($this->stream); + $this->seekable = $meta['seekable']; + $this->readable = isset(self::$readWriteHash['read'][$meta['mode']]); + $this->writable = isset(self::$readWriteHash['write'][$meta['mode']]); + $this->uri = $this->getMetadata('uri'); + } + + public function __get($name) + { + if ($name == 'stream') { + throw new \RuntimeException('The stream is detached'); + } + + throw new \BadMethodCallException('No value for ' . $name); + } + + /** + * Closes the stream when the destructed + */ + public function __destruct() + { + $this->close(); + } + + public function __toString() + { + try { + $this->seek(0); + return (string) stream_get_contents($this->stream); + } catch (\Exception $e) { + return ''; + } + } + + public function getContents() + { + $contents = stream_get_contents($this->stream); + + if ($contents === false) { + throw new \RuntimeException('Unable to read stream contents'); + } + + return $contents; + } + + public function close() + { + if (isset($this->stream)) { + if (is_resource($this->stream)) { + fclose($this->stream); + } + $this->detach(); + } + } + + public function detach() + { + if (!isset($this->stream)) { + return null; + } + + $result = $this->stream; + unset($this->stream); + $this->size = $this->uri = null; + $this->readable = $this->writable = $this->seekable = false; + + return $result; + } + + public function getSize() + { + if ($this->size !== null) { + return $this->size; + } + + if (!isset($this->stream)) { + return null; + } + + // Clear the stat cache if the stream has a URI + if ($this->uri) { + clearstatcache(true, $this->uri); + } + + $stats = fstat($this->stream); + if (isset($stats['size'])) { + $this->size = $stats['size']; + return $this->size; + } + + return null; + } + + public function isReadable() + { + return $this->readable; + } + + public function isWritable() + { + return $this->writable; + } + + public function isSeekable() + { + return $this->seekable; + } + + public function eof() + { + return !$this->stream || feof($this->stream); + } + + public function tell() + { + $result = ftell($this->stream); + + if ($result === false) { + throw new \RuntimeException('Unable to determine stream position'); + } + + return $result; + } + + public function rewind() + { + $this->seek(0); + } + + public function seek($offset, $whence = SEEK_SET) + { + if (!$this->seekable) { + throw new \RuntimeException('Stream is not seekable'); + } elseif (fseek($this->stream, $offset, $whence) === -1) { + throw new \RuntimeException('Unable to seek to stream position ' + . $offset . ' with whence ' . var_export($whence, true)); + } + } + + public function read($length) + { + if (!$this->readable) { + throw new \RuntimeException('Cannot read from non-readable stream'); + } + + return fread($this->stream, $length); + } + + public function write($string) + { + if (!$this->writable) { + throw new \RuntimeException('Cannot write to a non-writable stream'); + } + + // We can't know the size after writing anything + $this->size = null; + $result = fwrite($this->stream, $string); + + if ($result === false) { + throw new \RuntimeException('Unable to write to stream'); + } + + return $result; + } + + public function getMetadata($key = null) + { + if (!isset($this->stream)) { + return $key ? null : array(); + } elseif (!$key) { + return $this->customMetadata + stream_get_meta_data($this->stream); + } elseif (isset($this->customMetadata[$key])) { + return $this->customMetadata[$key]; + } + + $meta = stream_get_meta_data($this->stream); + + return isset($meta[$key]) ? $meta[$key] : null; + } +} diff --git a/deps/vendor/ringcentral/psr7/src/StreamDecoratorTrait.php b/deps/vendor/ringcentral/psr7/src/StreamDecoratorTrait.php new file mode 100644 index 000000000..e22c674bc --- /dev/null +++ b/deps/vendor/ringcentral/psr7/src/StreamDecoratorTrait.php @@ -0,0 +1,139 @@ +stream = $stream; + } + + /** + * Magic method used to create a new stream if streams are not added in + * the constructor of a decorator (e.g., LazyOpenStream). + * + * @param string $name Name of the property (allows "stream" only). + * + * @return StreamInterface + */ + public function __get($name) + { + if ($name == 'stream') { + $this->stream = $this->createStream(); + return $this->stream; + } + + throw new \UnexpectedValueException("$name not found on class"); + } + + public function __toString() + { + try { + if ($this->isSeekable()) { + $this->seek(0); + } + return $this->getContents(); + } catch (\Exception $e) { + // Really, PHP? https://bugs.php.net/bug.php?id=53648 + trigger_error('StreamDecorator::__toString exception: ' + . (string) $e, E_USER_ERROR); + return ''; + } + } + + public function getContents() + { + return copy_to_string($this); + } + + /** + * Allow decorators to implement custom methods + * + * @param string $method Missing method name + * @param array $args Method arguments + * + * @return mixed + */ + public function __call($method, array $args) + { + $result = call_user_func_array(array($this->stream, $method), $args); + + // Always return the wrapped object if the result is a return $this + return $result === $this->stream ? $this : $result; + } + + public function close() + { + $this->stream->close(); + } + + public function getMetadata($key = null) + { + return $this->stream->getMetadata($key); + } + + public function detach() + { + return $this->stream->detach(); + } + + public function getSize() + { + return $this->stream->getSize(); + } + + public function eof() + { + return $this->stream->eof(); + } + + public function tell() + { + return $this->stream->tell(); + } + + public function isReadable() + { + return $this->stream->isReadable(); + } + + public function isWritable() + { + return $this->stream->isWritable(); + } + + public function isSeekable() + { + return $this->stream->isSeekable(); + } + + public function rewind() + { + $this->seek(0); + } + + public function seek($offset, $whence = SEEK_SET) + { + $this->stream->seek($offset, $whence); + } + + public function read($length) + { + return $this->stream->read($length); + } + + public function write($string) + { + return $this->stream->write($string); + } + +} diff --git a/deps/vendor/ringcentral/psr7/src/StreamWrapper.php b/deps/vendor/ringcentral/psr7/src/StreamWrapper.php new file mode 100644 index 000000000..8cc07d792 --- /dev/null +++ b/deps/vendor/ringcentral/psr7/src/StreamWrapper.php @@ -0,0 +1,121 @@ +isReadable()) { + $mode = $stream->isWritable() ? 'r+' : 'r'; + } elseif ($stream->isWritable()) { + $mode = 'w'; + } else { + throw new \InvalidArgumentException('The stream must be readable, ' + . 'writable, or both.'); + } + + return fopen('guzzle://stream', $mode, null, stream_context_create(array( + 'guzzle' => array('stream' => $stream) + ))); + } + + /** + * Registers the stream wrapper if needed + */ + public static function register() + { + if (!in_array('guzzle', stream_get_wrappers())) { + stream_wrapper_register('guzzle', __CLASS__); + } + } + + public function stream_open($path, $mode, $options, &$opened_path) + { + $options = stream_context_get_options($this->context); + + if (!isset($options['guzzle']['stream'])) { + return false; + } + + $this->mode = $mode; + $this->stream = $options['guzzle']['stream']; + + return true; + } + + public function stream_read($count) + { + return $this->stream->read($count); + } + + public function stream_write($data) + { + return (int) $this->stream->write($data); + } + + public function stream_tell() + { + return $this->stream->tell(); + } + + public function stream_eof() + { + return $this->stream->eof(); + } + + public function stream_seek($offset, $whence) + { + $this->stream->seek($offset, $whence); + + return true; + } + + public function stream_stat() + { + static $modeMap = array( + 'r' => 33060, + 'r+' => 33206, + 'w' => 33188 + ); + + return array( + 'dev' => 0, + 'ino' => 0, + 'mode' => $modeMap[$this->mode], + 'nlink' => 0, + 'uid' => 0, + 'gid' => 0, + 'rdev' => 0, + 'size' => $this->stream->getSize() ?: 0, + 'atime' => 0, + 'mtime' => 0, + 'ctime' => 0, + 'blksize' => 0, + 'blocks' => 0 + ); + } +} diff --git a/deps/vendor/ringcentral/psr7/src/Uri.php b/deps/vendor/ringcentral/psr7/src/Uri.php new file mode 100644 index 000000000..5323cdc4a --- /dev/null +++ b/deps/vendor/ringcentral/psr7/src/Uri.php @@ -0,0 +1,601 @@ + 80, + 'https' => 443, + ); + + private static $charUnreserved = 'a-zA-Z0-9_\-\.~'; + private static $charSubDelims = '!\$&\'\(\)\*\+,;='; + private static $replaceQuery = array('=' => '%3D', '&' => '%26'); + + /** @var string Uri scheme. */ + private $scheme = ''; + + /** @var string Uri user info. */ + private $userInfo = ''; + + /** @var string Uri host. */ + private $host = ''; + + /** @var int|null Uri port. */ + private $port; + + /** @var string Uri path. */ + private $path = ''; + + /** @var string Uri query string. */ + private $query = ''; + + /** @var string Uri fragment. */ + private $fragment = ''; + + /** + * @param string $uri URI to parse and wrap. + */ + public function __construct($uri = '') + { + if ($uri != null) { + $parts = parse_url($uri); + if ($parts === false) { + throw new \InvalidArgumentException("Unable to parse URI: $uri"); + } + $this->applyParts($parts); + } + } + + public function __toString() + { + return self::createUriString( + $this->scheme, + $this->getAuthority(), + $this->getPath(), + $this->query, + $this->fragment + ); + } + + /** + * Removes dot segments from a path and returns the new path. + * + * @param string $path + * + * @return string + * @link http://tools.ietf.org/html/rfc3986#section-5.2.4 + */ + public static function removeDotSegments($path) + { + static $noopPaths = array('' => true, '/' => true, '*' => true); + static $ignoreSegments = array('.' => true, '..' => true); + + if (isset($noopPaths[$path])) { + return $path; + } + + $results = array(); + $segments = explode('/', $path); + foreach ($segments as $segment) { + if ($segment == '..') { + array_pop($results); + } elseif (!isset($ignoreSegments[$segment])) { + $results[] = $segment; + } + } + + $newPath = implode('/', $results); + // Add the leading slash if necessary + if (substr($path, 0, 1) === '/' && + substr($newPath, 0, 1) !== '/' + ) { + $newPath = '/' . $newPath; + } + + // Add the trailing slash if necessary + if ($newPath != '/' && isset($ignoreSegments[end($segments)])) { + $newPath .= '/'; + } + + return $newPath; + } + + /** + * Resolve a base URI with a relative URI and return a new URI. + * + * @param UriInterface $base Base URI + * @param string $rel Relative URI + * + * @return UriInterface + */ + public static function resolve(UriInterface $base, $rel) + { + if ($rel === null || $rel === '') { + return $base; + } + + if (!($rel instanceof UriInterface)) { + $rel = new self($rel); + } + + // Return the relative uri as-is if it has a scheme. + if ($rel->getScheme()) { + return $rel->withPath(static::removeDotSegments($rel->getPath())); + } + + $relParts = array( + 'scheme' => $rel->getScheme(), + 'authority' => $rel->getAuthority(), + 'path' => $rel->getPath(), + 'query' => $rel->getQuery(), + 'fragment' => $rel->getFragment() + ); + + $parts = array( + 'scheme' => $base->getScheme(), + 'authority' => $base->getAuthority(), + 'path' => $base->getPath(), + 'query' => $base->getQuery(), + 'fragment' => $base->getFragment() + ); + + if (!empty($relParts['authority'])) { + $parts['authority'] = $relParts['authority']; + $parts['path'] = self::removeDotSegments($relParts['path']); + $parts['query'] = $relParts['query']; + $parts['fragment'] = $relParts['fragment']; + } elseif (!empty($relParts['path'])) { + if (substr($relParts['path'], 0, 1) == '/') { + $parts['path'] = self::removeDotSegments($relParts['path']); + $parts['query'] = $relParts['query']; + $parts['fragment'] = $relParts['fragment']; + } else { + if (!empty($parts['authority']) && empty($parts['path'])) { + $mergedPath = '/'; + } else { + $mergedPath = substr($parts['path'], 0, strrpos($parts['path'], '/') + 1); + } + $parts['path'] = self::removeDotSegments($mergedPath . $relParts['path']); + $parts['query'] = $relParts['query']; + $parts['fragment'] = $relParts['fragment']; + } + } elseif (!empty($relParts['query'])) { + $parts['query'] = $relParts['query']; + } elseif ($relParts['fragment'] != null) { + $parts['fragment'] = $relParts['fragment']; + } + + return new self(static::createUriString( + $parts['scheme'], + $parts['authority'], + $parts['path'], + $parts['query'], + $parts['fragment'] + )); + } + + /** + * Create a new URI with a specific query string value removed. + * + * Any existing query string values that exactly match the provided key are + * removed. + * + * Note: this function will convert "=" to "%3D" and "&" to "%26". + * + * @param UriInterface $uri URI to use as a base. + * @param string $key Query string key value pair to remove. + * + * @return UriInterface + */ + public static function withoutQueryValue(UriInterface $uri, $key) + { + $current = $uri->getQuery(); + if (!$current) { + return $uri; + } + + $result = array(); + foreach (explode('&', $current) as $part) { + $subParts = explode('=', $part); + if ($subParts[0] !== $key) { + $result[] = $part; + }; + } + + return $uri->withQuery(implode('&', $result)); + } + + /** + * Create a new URI with a specific query string value. + * + * Any existing query string values that exactly match the provided key are + * removed and replaced with the given key value pair. + * + * Note: this function will convert "=" to "%3D" and "&" to "%26". + * + * @param UriInterface $uri URI to use as a base. + * @param string $key Key to set. + * @param string $value Value to set. + * + * @return UriInterface + */ + public static function withQueryValue(UriInterface $uri, $key, $value) + { + $current = $uri->getQuery(); + $key = strtr($key, self::$replaceQuery); + + if (!$current) { + $result = array(); + } else { + $result = array(); + foreach (explode('&', $current) as $part) { + $subParts = explode('=', $part); + if ($subParts[0] !== $key) { + $result[] = $part; + }; + } + } + + if ($value !== null) { + $result[] = $key . '=' . strtr($value, self::$replaceQuery); + } else { + $result[] = $key; + } + + return $uri->withQuery(implode('&', $result)); + } + + /** + * Create a URI from a hash of parse_url parts. + * + * @param array $parts + * + * @return self + */ + public static function fromParts(array $parts) + { + $uri = new self(); + $uri->applyParts($parts); + return $uri; + } + + public function getScheme() + { + return $this->scheme; + } + + public function getAuthority() + { + if (empty($this->host)) { + return ''; + } + + $authority = $this->host; + if (!empty($this->userInfo)) { + $authority = $this->userInfo . '@' . $authority; + } + + if ($this->isNonStandardPort($this->scheme, $this->host, $this->port)) { + $authority .= ':' . $this->port; + } + + return $authority; + } + + public function getUserInfo() + { + return $this->userInfo; + } + + public function getHost() + { + return $this->host; + } + + public function getPort() + { + return $this->port; + } + + public function getPath() + { + return $this->path == null ? '' : $this->path; + } + + public function getQuery() + { + return $this->query; + } + + public function getFragment() + { + return $this->fragment; + } + + public function withScheme($scheme) + { + $scheme = $this->filterScheme($scheme); + + if ($this->scheme === $scheme) { + return $this; + } + + $new = clone $this; + $new->scheme = $scheme; + $new->port = $new->filterPort($new->scheme, $new->host, $new->port); + return $new; + } + + public function withUserInfo($user, $password = null) + { + $info = $user; + if ($password) { + $info .= ':' . $password; + } + + if ($this->userInfo === $info) { + return $this; + } + + $new = clone $this; + $new->userInfo = $info; + return $new; + } + + public function withHost($host) + { + if ($this->host === $host) { + return $this; + } + + $new = clone $this; + $new->host = $host; + return $new; + } + + public function withPort($port) + { + $port = $this->filterPort($this->scheme, $this->host, $port); + + if ($this->port === $port) { + return $this; + } + + $new = clone $this; + $new->port = $port; + return $new; + } + + public function withPath($path) + { + if (!is_string($path)) { + throw new \InvalidArgumentException( + 'Invalid path provided; must be a string' + ); + } + + $path = $this->filterPath($path); + + if ($this->path === $path) { + return $this; + } + + $new = clone $this; + $new->path = $path; + return $new; + } + + public function withQuery($query) + { + if (!is_string($query) && !method_exists($query, '__toString')) { + throw new \InvalidArgumentException( + 'Query string must be a string' + ); + } + + $query = (string) $query; + if (substr($query, 0, 1) === '?') { + $query = substr($query, 1); + } + + $query = $this->filterQueryAndFragment($query); + + if ($this->query === $query) { + return $this; + } + + $new = clone $this; + $new->query = $query; + return $new; + } + + public function withFragment($fragment) + { + if (substr($fragment, 0, 1) === '#') { + $fragment = substr($fragment, 1); + } + + $fragment = $this->filterQueryAndFragment($fragment); + + if ($this->fragment === $fragment) { + return $this; + } + + $new = clone $this; + $new->fragment = $fragment; + return $new; + } + + /** + * Apply parse_url parts to a URI. + * + * @param $parts Array of parse_url parts to apply. + */ + private function applyParts(array $parts) + { + $this->scheme = isset($parts['scheme']) + ? $this->filterScheme($parts['scheme']) + : ''; + $this->userInfo = isset($parts['user']) ? $parts['user'] : ''; + $this->host = isset($parts['host']) ? $parts['host'] : ''; + $this->port = !empty($parts['port']) + ? $this->filterPort($this->scheme, $this->host, $parts['port']) + : null; + $this->path = isset($parts['path']) + ? $this->filterPath($parts['path']) + : ''; + $this->query = isset($parts['query']) + ? $this->filterQueryAndFragment($parts['query']) + : ''; + $this->fragment = isset($parts['fragment']) + ? $this->filterQueryAndFragment($parts['fragment']) + : ''; + if (isset($parts['pass'])) { + $this->userInfo .= ':' . $parts['pass']; + } + } + + /** + * Create a URI string from its various parts + * + * @param string $scheme + * @param string $authority + * @param string $path + * @param string $query + * @param string $fragment + * @return string + */ + private static function createUriString($scheme, $authority, $path, $query, $fragment) + { + $uri = ''; + + if (!empty($scheme)) { + $uri .= $scheme . '://'; + } + + if (!empty($authority)) { + $uri .= $authority; + } + + if ($path != null) { + // Add a leading slash if necessary. + if ($uri && substr($path, 0, 1) !== '/') { + $uri .= '/'; + } + $uri .= $path; + } + + if ($query != null) { + $uri .= '?' . $query; + } + + if ($fragment != null) { + $uri .= '#' . $fragment; + } + + return $uri; + } + + /** + * Is a given port non-standard for the current scheme? + * + * @param string $scheme + * @param string $host + * @param int $port + * @return bool + */ + private static function isNonStandardPort($scheme, $host, $port) + { + if (!$scheme && $port) { + return true; + } + + if (!$host || !$port) { + return false; + } + + return !isset(static::$schemes[$scheme]) || $port !== static::$schemes[$scheme]; + } + + /** + * @param string $scheme + * + * @return string + */ + private function filterScheme($scheme) + { + $scheme = strtolower($scheme); + $scheme = rtrim($scheme, ':/'); + + return $scheme; + } + + /** + * @param string $scheme + * @param string $host + * @param int $port + * + * @return int|null + * + * @throws \InvalidArgumentException If the port is invalid. + */ + private function filterPort($scheme, $host, $port) + { + if (null !== $port) { + $port = (int) $port; + if (1 > $port || 0xffff < $port) { + throw new \InvalidArgumentException( + sprintf('Invalid port: %d. Must be between 1 and 65535', $port) + ); + } + } + + return $this->isNonStandardPort($scheme, $host, $port) ? $port : null; + } + + /** + * Filters the path of a URI + * + * @param $path + * + * @return string + */ + private function filterPath($path) + { + return preg_replace_callback( + '/(?:[^' . self::$charUnreserved . self::$charSubDelims . ':@\/%]+|%(?![A-Fa-f0-9]{2}))/', + array($this, 'rawurlencodeMatchZero'), + $path + ); + } + + /** + * Filters the query string or fragment of a URI. + * + * @param $str + * + * @return string + */ + private function filterQueryAndFragment($str) + { + return preg_replace_callback( + '/(?:[^' . self::$charUnreserved . self::$charSubDelims . '%:@\/\?]+|%(?![A-Fa-f0-9]{2}))/', + array($this, 'rawurlencodeMatchZero'), + $str + ); + } + + private function rawurlencodeMatchZero(array $match) + { + return rawurlencode($match[0]); + } +} diff --git a/deps/vendor/ringcentral/psr7/src/functions.php b/deps/vendor/ringcentral/psr7/src/functions.php new file mode 100644 index 000000000..3c4c549fc --- /dev/null +++ b/deps/vendor/ringcentral/psr7/src/functions.php @@ -0,0 +1,835 @@ +getMethod() . ' ' + . $message->getRequestTarget()) + . ' HTTP/' . $message->getProtocolVersion(); + if (!$message->hasHeader('host')) { + $msg .= "\r\nHost: " . $message->getUri()->getHost(); + } + } elseif ($message instanceof ResponseInterface) { + $msg = 'HTTP/' . $message->getProtocolVersion() . ' ' + . $message->getStatusCode() . ' ' + . $message->getReasonPhrase(); + } else { + throw new \InvalidArgumentException('Unknown message type'); + } + + foreach ($message->getHeaders() as $name => $values) { + $msg .= "\r\n{$name}: " . implode(', ', $values); + } + + return "{$msg}\r\n\r\n" . $message->getBody(); +} + +/** + * Returns a UriInterface for the given value. + * + * This function accepts a string or {@see Psr\Http\Message\UriInterface} and + * returns a UriInterface for the given value. If the value is already a + * `UriInterface`, it is returned as-is. + * + * @param string|UriInterface $uri + * + * @return UriInterface + * @throws \InvalidArgumentException + */ +function uri_for($uri) +{ + if ($uri instanceof UriInterface) { + return $uri; + } elseif (is_string($uri)) { + return new Uri($uri); + } + + throw new \InvalidArgumentException('URI must be a string or UriInterface'); +} + +/** + * Create a new stream based on the input type. + * + * Options is an associative array that can contain the following keys: + * - metadata: Array of custom metadata. + * - size: Size of the stream. + * + * @param resource|string|StreamInterface $resource Entity body data + * @param array $options Additional options + * + * @return Stream + * @throws \InvalidArgumentException if the $resource arg is not valid. + */ +function stream_for($resource = '', array $options = array()) +{ + switch (gettype($resource)) { + case 'string': + $stream = fopen('php://temp', 'r+'); + if ($resource !== '') { + fwrite($stream, $resource); + fseek($stream, 0); + } + return new Stream($stream, $options); + case 'resource': + return new Stream($resource, $options); + case 'object': + if ($resource instanceof StreamInterface) { + return $resource; + } elseif ($resource instanceof \Iterator) { + return new PumpStream(function () use ($resource) { + if (!$resource->valid()) { + return false; + } + $result = $resource->current(); + $resource->next(); + return $result; + }, $options); + } elseif (method_exists($resource, '__toString')) { + return stream_for((string) $resource, $options); + } + break; + case 'NULL': + return new Stream(fopen('php://temp', 'r+'), $options); + } + + if (is_callable($resource)) { + return new PumpStream($resource, $options); + } + + throw new \InvalidArgumentException('Invalid resource type: ' . gettype($resource)); +} + +/** + * Parse an array of header values containing ";" separated data into an + * array of associative arrays representing the header key value pair + * data of the header. When a parameter does not contain a value, but just + * contains a key, this function will inject a key with a '' string value. + * + * @param string|array $header Header to parse into components. + * + * @return array Returns the parsed header values. + */ +function parse_header($header) +{ + static $trimmed = "\"' \n\t\r"; + $params = $matches = array(); + + foreach (normalize_header($header) as $val) { + $part = array(); + foreach (preg_split('/;(?=([^"]*"[^"]*")*[^"]*$)/', $val) as $kvp) { + if (preg_match_all('/<[^>]+>|[^=]+/', $kvp, $matches)) { + $m = $matches[0]; + if (isset($m[1])) { + $part[trim($m[0], $trimmed)] = trim($m[1], $trimmed); + } else { + $part[] = trim($m[0], $trimmed); + } + } + } + if ($part) { + $params[] = $part; + } + } + + return $params; +} + +/** + * Converts an array of header values that may contain comma separated + * headers into an array of headers with no comma separated values. + * + * @param string|array $header Header to normalize. + * + * @return array Returns the normalized header field values. + */ +function normalize_header($header) +{ + if (!is_array($header)) { + return array_map('trim', explode(',', $header)); + } + + $result = array(); + foreach ($header as $value) { + foreach ((array) $value as $v) { + if (strpos($v, ',') === false) { + $result[] = $v; + continue; + } + foreach (preg_split('/,(?=([^"]*"[^"]*")*[^"]*$)/', $v) as $vv) { + $result[] = trim($vv); + } + } + } + + return $result; +} + +/** + * Clone and modify a request with the given changes. + * + * The changes can be one of: + * - method: (string) Changes the HTTP method. + * - set_headers: (array) Sets the given headers. + * - remove_headers: (array) Remove the given headers. + * - body: (mixed) Sets the given body. + * - uri: (UriInterface) Set the URI. + * - query: (string) Set the query string value of the URI. + * - version: (string) Set the protocol version. + * + * @param RequestInterface $request Request to clone and modify. + * @param array $changes Changes to apply. + * + * @return RequestInterface + */ +function modify_request(RequestInterface $request, array $changes) +{ + if (!$changes) { + return $request; + } + + $headers = $request->getHeaders(); + + if (!isset($changes['uri'])) { + $uri = $request->getUri(); + } else { + // Remove the host header if one is on the URI + if ($host = $changes['uri']->getHost()) { + $changes['set_headers']['Host'] = $host; + } + $uri = $changes['uri']; + } + + if (!empty($changes['remove_headers'])) { + $headers = _caseless_remove($changes['remove_headers'], $headers); + } + + if (!empty($changes['set_headers'])) { + $headers = _caseless_remove(array_keys($changes['set_headers']), $headers); + $headers = $changes['set_headers'] + $headers; + } + + if (isset($changes['query'])) { + $uri = $uri->withQuery($changes['query']); + } + + return new Request( + isset($changes['method']) ? $changes['method'] : $request->getMethod(), + $uri, + $headers, + isset($changes['body']) ? $changes['body'] : $request->getBody(), + isset($changes['version']) + ? $changes['version'] + : $request->getProtocolVersion() + ); +} + +/** + * Attempts to rewind a message body and throws an exception on failure. + * + * The body of the message will only be rewound if a call to `tell()` returns a + * value other than `0`. + * + * @param MessageInterface $message Message to rewind + * + * @throws \RuntimeException + */ +function rewind_body(MessageInterface $message) +{ + $body = $message->getBody(); + + if ($body->tell()) { + $body->rewind(); + } +} + +/** + * Safely opens a PHP stream resource using a filename. + * + * When fopen fails, PHP normally raises a warning. This function adds an + * error handler that checks for errors and throws an exception instead. + * + * @param string $filename File to open + * @param string $mode Mode used to open the file + * + * @return resource + * @throws \RuntimeException if the file cannot be opened + */ +function try_fopen($filename, $mode) +{ + $ex = null; + $fargs = func_get_args(); + set_error_handler(function () use ($filename, $mode, &$ex, $fargs) { + $ex = new \RuntimeException(sprintf( + 'Unable to open %s using mode %s: %s', + $filename, + $mode, + $fargs[1] + )); + }); + + $handle = fopen($filename, $mode); + restore_error_handler(); + + if ($ex) { + /** @var $ex \RuntimeException */ + throw $ex; + } + + return $handle; +} + +/** + * Copy the contents of a stream into a string until the given number of + * bytes have been read. + * + * @param StreamInterface $stream Stream to read + * @param int $maxLen Maximum number of bytes to read. Pass -1 + * to read the entire stream. + * @return string + * @throws \RuntimeException on error. + */ +function copy_to_string(StreamInterface $stream, $maxLen = -1) +{ + $buffer = ''; + + if ($maxLen === -1) { + while (!$stream->eof()) { + $buf = $stream->read(1048576); + // Using a loose equality here to match on '' and false. + if ($buf == null) { + break; + } + $buffer .= $buf; + } + return $buffer; + } + + $len = 0; + while (!$stream->eof() && $len < $maxLen) { + $buf = $stream->read($maxLen - $len); + // Using a loose equality here to match on '' and false. + if ($buf == null) { + break; + } + $buffer .= $buf; + $len = strlen($buffer); + } + + return $buffer; +} + +/** + * Copy the contents of a stream into another stream until the given number + * of bytes have been read. + * + * @param StreamInterface $source Stream to read from + * @param StreamInterface $dest Stream to write to + * @param int $maxLen Maximum number of bytes to read. Pass -1 + * to read the entire stream. + * + * @throws \RuntimeException on error. + */ +function copy_to_stream( + StreamInterface $source, + StreamInterface $dest, + $maxLen = -1 +) { + if ($maxLen === -1) { + while (!$source->eof()) { + if (!$dest->write($source->read(1048576))) { + break; + } + } + return; + } + + $bytes = 0; + while (!$source->eof()) { + $buf = $source->read($maxLen - $bytes); + if (!($len = strlen($buf))) { + break; + } + $bytes += $len; + $dest->write($buf); + if ($bytes == $maxLen) { + break; + } + } +} + +/** + * Calculate a hash of a Stream + * + * @param StreamInterface $stream Stream to calculate the hash for + * @param string $algo Hash algorithm (e.g. md5, crc32, etc) + * @param bool $rawOutput Whether or not to use raw output + * + * @return string Returns the hash of the stream + * @throws \RuntimeException on error. + */ +function hash( + StreamInterface $stream, + $algo, + $rawOutput = false +) { + $pos = $stream->tell(); + + if ($pos > 0) { + $stream->rewind(); + } + + $ctx = hash_init($algo); + while (!$stream->eof()) { + hash_update($ctx, $stream->read(1048576)); + } + + $out = hash_final($ctx, (bool) $rawOutput); + $stream->seek($pos); + + return $out; +} + +/** + * Read a line from the stream up to the maximum allowed buffer length + * + * @param StreamInterface $stream Stream to read from + * @param int $maxLength Maximum buffer length + * + * @return string|bool + */ +function readline(StreamInterface $stream, $maxLength = null) +{ + $buffer = ''; + $size = 0; + + while (!$stream->eof()) { + // Using a loose equality here to match on '' and false. + if (null == ($byte = $stream->read(1))) { + return $buffer; + } + $buffer .= $byte; + // Break when a new line is found or the max length - 1 is reached + if ($byte == PHP_EOL || ++$size == $maxLength - 1) { + break; + } + } + + return $buffer; +} + +/** + * Parses a request message string into a request object. + * + * @param string $message Request message string. + * + * @return Request + */ +function parse_request($message) +{ + $data = _parse_message($message); + $matches = array(); + if (!preg_match('/^[a-zA-Z]+\s+([a-zA-Z]+:\/\/|\/).*/', $data['start-line'], $matches)) { + throw new \InvalidArgumentException('Invalid request string'); + } + $parts = explode(' ', $data['start-line'], 3); + $subParts = isset($parts[2]) ? explode('/', $parts[2]) : array(); + $version = isset($parts[2]) ? $subParts[1] : '1.1'; + + $request = new Request( + $parts[0], + $matches[1] === '/' ? _parse_request_uri($parts[1], $data['headers']) : $parts[1], + $data['headers'], + $data['body'], + $version + ); + + return $matches[1] === '/' ? $request : $request->withRequestTarget($parts[1]); +} + +/** + * Parses a request message string into a server request object. + * + * @param string $message Request message string. + * @param array $serverParams Server params that will be added to the + * ServerRequest object + * + * @return ServerRequest + */ +function parse_server_request($message, array $serverParams = array()) +{ + $request = parse_request($message); + + return new ServerRequest( + $request->getMethod(), + $request->getUri(), + $request->getHeaders(), + $request->getBody(), + $request->getProtocolVersion(), + $serverParams + ); +} + +/** + * Parses a response message string into a response object. + * + * @param string $message Response message string. + * + * @return Response + */ +function parse_response($message) +{ + $data = _parse_message($message); + // According to https://tools.ietf.org/html/rfc7230#section-3.1.2 the space + // between status-code and reason-phrase is required. But browsers accept + // responses without space and reason as well. + if (!preg_match('/^HTTP\/.* [0-9]{3}( .*|$)/', $data['start-line'])) { + throw new \InvalidArgumentException('Invalid response string'); + } + $parts = explode(' ', $data['start-line'], 3); + $subParts = explode('/', $parts[0]); + + return new Response( + $parts[1], + $data['headers'], + $data['body'], + $subParts[1], + isset($parts[2]) ? $parts[2] : null + ); +} + +/** + * Parse a query string into an associative array. + * + * If multiple values are found for the same key, the value of that key + * value pair will become an array. This function does not parse nested + * PHP style arrays into an associative array (e.g., foo[a]=1&foo[b]=2 will + * be parsed into ['foo[a]' => '1', 'foo[b]' => '2']). + * + * @param string $str Query string to parse + * @param bool|string $urlEncoding How the query string is encoded + * + * @return array + */ +function parse_query($str, $urlEncoding = true) +{ + $result = array(); + + if ($str === '') { + return $result; + } + + if ($urlEncoding === true) { + $decoder = function ($value) { + return rawurldecode(str_replace('+', ' ', $value)); + }; + } elseif ($urlEncoding == PHP_QUERY_RFC3986) { + $decoder = 'rawurldecode'; + } elseif ($urlEncoding == PHP_QUERY_RFC1738) { + $decoder = 'urldecode'; + } else { + $decoder = function ($str) { return $str; }; + } + + foreach (explode('&', $str) as $kvp) { + $parts = explode('=', $kvp, 2); + $key = $decoder($parts[0]); + $value = isset($parts[1]) ? $decoder($parts[1]) : null; + if (!isset($result[$key])) { + $result[$key] = $value; + } else { + if (!is_array($result[$key])) { + $result[$key] = array($result[$key]); + } + $result[$key][] = $value; + } + } + + return $result; +} + +/** + * Build a query string from an array of key value pairs. + * + * This function can use the return value of parseQuery() to build a query + * string. This function does not modify the provided keys when an array is + * encountered (like http_build_query would). + * + * @param array $params Query string parameters. + * @param int|false $encoding Set to false to not encode, PHP_QUERY_RFC3986 + * to encode using RFC3986, or PHP_QUERY_RFC1738 + * to encode using RFC1738. + * @return string + */ +function build_query(array $params, $encoding = PHP_QUERY_RFC3986) +{ + if (!$params) { + return ''; + } + + if ($encoding === false) { + $encoder = function ($str) { return $str; }; + } elseif ($encoding == PHP_QUERY_RFC3986) { + $encoder = 'rawurlencode'; + } elseif ($encoding == PHP_QUERY_RFC1738) { + $encoder = 'urlencode'; + } else { + throw new \InvalidArgumentException('Invalid type'); + } + + $qs = ''; + foreach ($params as $k => $v) { + $k = $encoder($k); + if (!is_array($v)) { + $qs .= $k; + if ($v !== null) { + $qs .= '=' . $encoder($v); + } + $qs .= '&'; + } else { + foreach ($v as $vv) { + $qs .= $k; + if ($vv !== null) { + $qs .= '=' . $encoder($vv); + } + $qs .= '&'; + } + } + } + + return $qs ? (string) substr($qs, 0, -1) : ''; +} + +/** + * Determines the mimetype of a file by looking at its extension. + * + * @param $filename + * + * @return null|string + */ +function mimetype_from_filename($filename) +{ + return mimetype_from_extension(pathinfo($filename, PATHINFO_EXTENSION)); +} + +/** + * Maps a file extensions to a mimetype. + * + * @param $extension string The file extension. + * + * @return string|null + * @link http://svn.apache.org/repos/asf/httpd/httpd/branches/1.3.x/conf/mime.types + */ +function mimetype_from_extension($extension) +{ + static $mimetypes = array( + '7z' => 'application/x-7z-compressed', + 'aac' => 'audio/x-aac', + 'ai' => 'application/postscript', + 'aif' => 'audio/x-aiff', + 'asc' => 'text/plain', + 'asf' => 'video/x-ms-asf', + 'atom' => 'application/atom+xml', + 'avi' => 'video/x-msvideo', + 'bmp' => 'image/bmp', + 'bz2' => 'application/x-bzip2', + 'cer' => 'application/pkix-cert', + 'crl' => 'application/pkix-crl', + 'crt' => 'application/x-x509-ca-cert', + 'css' => 'text/css', + 'csv' => 'text/csv', + 'cu' => 'application/cu-seeme', + 'deb' => 'application/x-debian-package', + 'doc' => 'application/msword', + 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'dvi' => 'application/x-dvi', + 'eot' => 'application/vnd.ms-fontobject', + 'eps' => 'application/postscript', + 'epub' => 'application/epub+zip', + 'etx' => 'text/x-setext', + 'flac' => 'audio/flac', + 'flv' => 'video/x-flv', + 'gif' => 'image/gif', + 'gz' => 'application/gzip', + 'htm' => 'text/html', + 'html' => 'text/html', + 'ico' => 'image/x-icon', + 'ics' => 'text/calendar', + 'ini' => 'text/plain', + 'iso' => 'application/x-iso9660-image', + 'jar' => 'application/java-archive', + 'jpe' => 'image/jpeg', + 'jpeg' => 'image/jpeg', + 'jpg' => 'image/jpeg', + 'js' => 'text/javascript', + 'json' => 'application/json', + 'latex' => 'application/x-latex', + 'log' => 'text/plain', + 'm4a' => 'audio/mp4', + 'm4v' => 'video/mp4', + 'mid' => 'audio/midi', + 'midi' => 'audio/midi', + 'mov' => 'video/quicktime', + 'mp3' => 'audio/mpeg', + 'mp4' => 'video/mp4', + 'mp4a' => 'audio/mp4', + 'mp4v' => 'video/mp4', + 'mpe' => 'video/mpeg', + 'mpeg' => 'video/mpeg', + 'mpg' => 'video/mpeg', + 'mpg4' => 'video/mp4', + 'oga' => 'audio/ogg', + 'ogg' => 'audio/ogg', + 'ogv' => 'video/ogg', + 'ogx' => 'application/ogg', + 'pbm' => 'image/x-portable-bitmap', + 'pdf' => 'application/pdf', + 'pgm' => 'image/x-portable-graymap', + 'png' => 'image/png', + 'pnm' => 'image/x-portable-anymap', + 'ppm' => 'image/x-portable-pixmap', + 'ppt' => 'application/vnd.ms-powerpoint', + 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + 'ps' => 'application/postscript', + 'qt' => 'video/quicktime', + 'rar' => 'application/x-rar-compressed', + 'ras' => 'image/x-cmu-raster', + 'rss' => 'application/rss+xml', + 'rtf' => 'application/rtf', + 'sgm' => 'text/sgml', + 'sgml' => 'text/sgml', + 'svg' => 'image/svg+xml', + 'swf' => 'application/x-shockwave-flash', + 'tar' => 'application/x-tar', + 'tif' => 'image/tiff', + 'tiff' => 'image/tiff', + 'torrent' => 'application/x-bittorrent', + 'ttf' => 'application/x-font-ttf', + 'txt' => 'text/plain', + 'wav' => 'audio/x-wav', + 'webm' => 'video/webm', + 'wma' => 'audio/x-ms-wma', + 'wmv' => 'video/x-ms-wmv', + 'woff' => 'application/x-font-woff', + 'wsdl' => 'application/wsdl+xml', + 'xbm' => 'image/x-xbitmap', + 'xls' => 'application/vnd.ms-excel', + 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'xml' => 'application/xml', + 'xpm' => 'image/x-xpixmap', + 'xwd' => 'image/x-xwindowdump', + 'yaml' => 'text/yaml', + 'yml' => 'text/yaml', + 'zip' => 'application/zip', + ); + + $extension = strtolower($extension); + + return isset($mimetypes[$extension]) + ? $mimetypes[$extension] + : null; +} + +/** + * Parses an HTTP message into an associative array. + * + * The array contains the "start-line" key containing the start line of + * the message, "headers" key containing an associative array of header + * array values, and a "body" key containing the body of the message. + * + * @param string $message HTTP request or response to parse. + * + * @return array + * @internal + */ +function _parse_message($message) +{ + if (!$message) { + throw new \InvalidArgumentException('Invalid message'); + } + + // Iterate over each line in the message, accounting for line endings + $lines = preg_split('/(\\r?\\n)/', $message, -1, PREG_SPLIT_DELIM_CAPTURE); + $result = array('start-line' => array_shift($lines), 'headers' => array(), 'body' => ''); + array_shift($lines); + + for ($i = 0, $totalLines = count($lines); $i < $totalLines; $i += 2) { + $line = $lines[$i]; + // If two line breaks were encountered, then this is the end of body + if (empty($line)) { + if ($i < $totalLines - 1) { + $result['body'] = implode('', array_slice($lines, $i + 2)); + } + break; + } + if (strpos($line, ':')) { + $parts = explode(':', $line, 2); + $key = trim($parts[0]); + $value = isset($parts[1]) ? trim($parts[1]) : ''; + $result['headers'][$key][] = $value; + } + } + + return $result; +} + +/** + * Constructs a URI for an HTTP request message. + * + * @param string $path Path from the start-line + * @param array $headers Array of headers (each value an array). + * + * @return string + * @internal + */ +function _parse_request_uri($path, array $headers) +{ + $hostKey = array_filter(array_keys($headers), function ($k) { + return strtolower($k) === 'host'; + }); + + // If no host is found, then a full URI cannot be constructed. + if (!$hostKey) { + return $path; + } + + $host = $headers[reset($hostKey)][0]; + $scheme = substr($host, -4) === ':443' ? 'https' : 'http'; + + return $scheme . '://' . $host . '/' . ltrim($path, '/'); +} + +/** @internal */ +function _caseless_remove($keys, array $data) +{ + $result = array(); + + foreach ($keys as &$key) { + $key = strtolower($key); + } + + foreach ($data as $k => $v) { + if (!in_array(strtolower($k), $keys)) { + $result[$k] = $v; + } + } + + return $result; +} diff --git a/deps/vendor/ringcentral/psr7/src/functions_include.php b/deps/vendor/ringcentral/psr7/src/functions_include.php new file mode 100644 index 000000000..252e0cfd1 --- /dev/null +++ b/deps/vendor/ringcentral/psr7/src/functions_include.php @@ -0,0 +1,6 @@ +getMockBuilder('Psr\Http\Message\StreamInterface') + ->setMethods(array('isReadable')) + ->getMockForAbstractClass(); + $s->expects($this->once()) + ->method('isReadable') + ->will($this->returnValue(false)); + $a->addStream($s); + } + + /** + * @expectedException \RuntimeException + * @expectedExceptionMessage The AppendStream can only seek with SEEK_SET + */ + public function testValidatesSeekType() + { + $a = new AppendStream(); + $a->seek(100, SEEK_CUR); + } + + /** + * @expectedException \RuntimeException + * @expectedExceptionMessage Unable to seek stream 0 of the AppendStream + */ + public function testTriesToRewindOnSeek() + { + $a = new AppendStream(); + $s = $this->getMockBuilder('Psr\Http\Message\StreamInterface') + ->setMethods(array('isReadable', 'rewind', 'isSeekable')) + ->getMockForAbstractClass(); + $s->expects($this->once()) + ->method('isReadable') + ->will($this->returnValue(true)); + $s->expects($this->once()) + ->method('isSeekable') + ->will($this->returnValue(true)); + $s->expects($this->once()) + ->method('rewind') + ->will($this->throwException(new \RuntimeException())); + $a->addStream($s); + $a->seek(10); + } + + public function testSeeksToPositionByReading() + { + $a = new AppendStream(array( + Psr7\stream_for('foo'), + Psr7\stream_for('bar'), + Psr7\stream_for('baz'), + )); + + $a->seek(3); + $this->assertEquals(3, $a->tell()); + $this->assertEquals('bar', $a->read(3)); + + $a->seek(6); + $this->assertEquals(6, $a->tell()); + $this->assertEquals('baz', $a->read(3)); + } + + public function testDetachesEachStream() + { + $s1 = Psr7\stream_for('foo'); + $s2 = Psr7\stream_for('bar'); + $a = new AppendStream(array($s1, $s2)); + $this->assertSame('foobar', (string) $a); + $a->detach(); + $this->assertSame('', (string) $a); + $this->assertSame(0, $a->getSize()); + } + + public function testClosesEachStream() + { + $s1 = Psr7\stream_for('foo'); + $a = new AppendStream(array($s1)); + $a->close(); + $this->assertSame('', (string) $a); + } + + /** + * @expectedExceptionMessage Cannot write to an AppendStream + * @expectedException \RuntimeException + */ + public function testIsNotWritable() + { + $a = new AppendStream(array(Psr7\stream_for('foo'))); + $this->assertFalse($a->isWritable()); + $this->assertTrue($a->isSeekable()); + $this->assertTrue($a->isReadable()); + $a->write('foo'); + } + + public function testDoesNotNeedStreams() + { + $a = new AppendStream(); + $this->assertEquals('', (string) $a); + } + + public function testCanReadFromMultipleStreams() + { + $a = new AppendStream(array( + Psr7\stream_for('foo'), + Psr7\stream_for('bar'), + Psr7\stream_for('baz'), + )); + $this->assertFalse($a->eof()); + $this->assertSame(0, $a->tell()); + $this->assertEquals('foo', $a->read(3)); + $this->assertEquals('bar', $a->read(3)); + $this->assertEquals('baz', $a->read(3)); + $this->assertSame('', $a->read(1)); + $this->assertTrue($a->eof()); + $this->assertSame(9, $a->tell()); + $this->assertEquals('foobarbaz', (string) $a); + } + + public function testCanDetermineSizeFromMultipleStreams() + { + $a = new AppendStream(array( + Psr7\stream_for('foo'), + Psr7\stream_for('bar') + )); + $this->assertEquals(6, $a->getSize()); + + $s = $this->getMockBuilder('Psr\Http\Message\StreamInterface') + ->setMethods(array('isSeekable', 'isReadable')) + ->getMockForAbstractClass(); + $s->expects($this->once()) + ->method('isSeekable') + ->will($this->returnValue(null)); + $s->expects($this->once()) + ->method('isReadable') + ->will($this->returnValue(true)); + $a->addStream($s); + $this->assertNull($a->getSize()); + } + + public function testCatchesExceptionsWhenCastingToString() + { + $s = $this->getMockBuilder('Psr\Http\Message\StreamInterface') + ->setMethods(array('isSeekable', 'read', 'isReadable', 'eof')) + ->getMockForAbstractClass(); + $s->expects($this->once()) + ->method('isSeekable') + ->will($this->returnValue(true)); + $s->expects($this->once()) + ->method('read') + ->will($this->throwException(new \RuntimeException('foo'))); + $s->expects($this->once()) + ->method('isReadable') + ->will($this->returnValue(true)); + $s->expects($this->any()) + ->method('eof') + ->will($this->returnValue(false)); + $a = new AppendStream(array($s)); + $this->assertFalse($a->eof()); + $this->assertSame('', (string) $a); + } + + public function testCanDetach() + { + $s = new AppendStream(); + $s->detach(); + } + + public function testReturnsEmptyMetadata() + { + $s = new AppendStream(); + $this->assertEquals(array(), $s->getMetadata()); + $this->assertNull($s->getMetadata('foo')); + } +} diff --git a/deps/vendor/ringcentral/psr7/tests/BufferStreamTest.php b/deps/vendor/ringcentral/psr7/tests/BufferStreamTest.php new file mode 100644 index 000000000..79f907aa2 --- /dev/null +++ b/deps/vendor/ringcentral/psr7/tests/BufferStreamTest.php @@ -0,0 +1,63 @@ +assertTrue($b->isReadable()); + $this->assertTrue($b->isWritable()); + $this->assertFalse($b->isSeekable()); + $this->assertEquals(null, $b->getMetadata('foo')); + $this->assertEquals(10, $b->getMetadata('hwm')); + $this->assertEquals(array(), $b->getMetadata()); + } + + public function testRemovesReadDataFromBuffer() + { + $b = new BufferStream(); + $this->assertEquals(3, $b->write('foo')); + $this->assertEquals(3, $b->getSize()); + $this->assertFalse($b->eof()); + $this->assertEquals('foo', $b->read(10)); + $this->assertTrue($b->eof()); + $this->assertEquals('', $b->read(10)); + } + + /** + * @expectedException \RuntimeException + * @expectedExceptionMessage Cannot determine the position of a BufferStream + */ + public function testCanCastToStringOrGetContents() + { + $b = new BufferStream(); + $b->write('foo'); + $b->write('baz'); + $this->assertEquals('foo', $b->read(3)); + $b->write('bar'); + $this->assertEquals('bazbar', (string) $b); + $b->tell(); + } + + public function testDetachClearsBuffer() + { + $b = new BufferStream(); + $b->write('foo'); + $b->detach(); + $this->assertTrue($b->eof()); + $this->assertEquals(3, $b->write('abc')); + $this->assertEquals('abc', $b->read(10)); + } + + public function testExceedingHighwaterMarkReturnsFalseButStillBuffers() + { + $b = new BufferStream(5); + $this->assertEquals(3, $b->write('hi ')); + $this->assertFalse($b->write('hello')); + $this->assertEquals('hi hello', (string) $b); + $this->assertEquals(4, $b->write('test')); + } +} diff --git a/deps/vendor/ringcentral/psr7/tests/CachingStreamTest.php b/deps/vendor/ringcentral/psr7/tests/CachingStreamTest.php new file mode 100644 index 000000000..f394fc9a1 --- /dev/null +++ b/deps/vendor/ringcentral/psr7/tests/CachingStreamTest.php @@ -0,0 +1,166 @@ +decorated = Psr7\stream_for('testing'); + $this->body = new CachingStream($this->decorated); + } + + public function tearDown() + { + $this->decorated->close(); + $this->body->close(); + } + + public function testUsesRemoteSizeIfPossible() + { + $body = Psr7\stream_for('test'); + $caching = new CachingStream($body); + $this->assertEquals(4, $caching->getSize()); + } + + public function testReadsUntilCachedToByte() + { + $this->body->seek(5); + $this->assertEquals('n', $this->body->read(1)); + $this->body->seek(0); + $this->assertEquals('t', $this->body->read(1)); + } + + public function testCanSeekNearEndWithSeekEnd() + { + $baseStream = Psr7\stream_for(implode('', range('a', 'z'))); + $cached = new CachingStream($baseStream); + $cached->seek(1, SEEK_END); + $this->assertEquals(24, $baseStream->tell()); + $this->assertEquals('y', $cached->read(1)); + $this->assertEquals(26, $cached->getSize()); + } + + public function testCanSeekToEndWithSeekEnd() + { + $baseStream = Psr7\stream_for(implode('', range('a', 'z'))); + $cached = new CachingStream($baseStream); + $cached->seek(0, SEEK_END); + $this->assertEquals(25, $baseStream->tell()); + $this->assertEquals('z', $cached->read(1)); + $this->assertEquals(26, $cached->getSize()); + } + + public function testCanUseSeekEndWithUnknownSize() + { + $baseStream = Psr7\stream_for('testing'); + $decorated = Psr7\FnStream::decorate($baseStream, array( + 'getSize' => function () { return null; } + )); + $cached = new CachingStream($decorated); + $cached->seek(1, SEEK_END); + $this->assertEquals('ng', $cached->read(2)); + } + + public function testRewindUsesSeek() + { + $a = Psr7\stream_for('foo'); + $d = $this->getMockBuilder('RingCentral\Psr7\CachingStream') + ->setMethods(array('seek')) + ->setConstructorArgs(array($a)) + ->getMock(); + $d->expects($this->once()) + ->method('seek') + ->with(0) + ->will($this->returnValue(true)); + $d->seek(0); + } + + public function testCanSeekToReadBytes() + { + $this->assertEquals('te', $this->body->read(2)); + $this->body->seek(0); + $this->assertEquals('test', $this->body->read(4)); + $this->assertEquals(4, $this->body->tell()); + $this->body->seek(2); + $this->assertEquals(2, $this->body->tell()); + $this->body->seek(2, SEEK_CUR); + $this->assertEquals(4, $this->body->tell()); + $this->assertEquals('ing', $this->body->read(3)); + } + + public function testWritesToBufferStream() + { + $this->body->read(2); + $this->body->write('hi'); + $this->body->seek(0); + $this->assertEquals('tehiing', (string) $this->body); + } + + public function testSkipsOverwrittenBytes() + { + $decorated = Psr7\stream_for( + implode("\n", array_map(function ($n) { + return str_pad($n, 4, '0', STR_PAD_LEFT); + }, range(0, 25))) + ); + + $body = new CachingStream($decorated); + + $this->assertEquals("0000\n", Psr7\readline($body)); + $this->assertEquals("0001\n", Psr7\readline($body)); + // Write over part of the body yet to be read, so skip some bytes + $this->assertEquals(5, $body->write("TEST\n")); + $this->assertEquals(5, $this->readAttribute($body, 'skipReadBytes')); + // Read, which skips bytes, then reads + $this->assertEquals("0003\n", Psr7\readline($body)); + $this->assertEquals(0, $this->readAttribute($body, 'skipReadBytes')); + $this->assertEquals("0004\n", Psr7\readline($body)); + $this->assertEquals("0005\n", Psr7\readline($body)); + + // Overwrite part of the cached body (so don't skip any bytes) + $body->seek(5); + $this->assertEquals(5, $body->write("ABCD\n")); + $this->assertEquals(0, $this->readAttribute($body, 'skipReadBytes')); + $this->assertEquals("TEST\n", Psr7\readline($body)); + $this->assertEquals("0003\n", Psr7\readline($body)); + $this->assertEquals("0004\n", Psr7\readline($body)); + $this->assertEquals("0005\n", Psr7\readline($body)); + $this->assertEquals("0006\n", Psr7\readline($body)); + $this->assertEquals(5, $body->write("1234\n")); + $this->assertEquals(5, $this->readAttribute($body, 'skipReadBytes')); + + // Seek to 0 and ensure the overwritten bit is replaced + $body->seek(0); + $this->assertEquals("0000\nABCD\nTEST\n0003\n0004\n0005\n0006\n1234\n0008\n0009\n", $body->read(50)); + + // Ensure that casting it to a string does not include the bit that was overwritten + $this->assertContains("0000\nABCD\nTEST\n0003\n0004\n0005\n0006\n1234\n0008\n0009\n", (string) $body); + } + + public function testClosesBothStreams() + { + $s = fopen('php://temp', 'r'); + $a = Psr7\stream_for($s); + $d = new CachingStream($a); + $d->close(); + $this->assertFalse(is_resource($s)); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testEnsuresValidWhence() + { + $this->body->seek(10, -123456); + } +} diff --git a/deps/vendor/ringcentral/psr7/tests/DroppingStreamTest.php b/deps/vendor/ringcentral/psr7/tests/DroppingStreamTest.php new file mode 100644 index 000000000..1ae944364 --- /dev/null +++ b/deps/vendor/ringcentral/psr7/tests/DroppingStreamTest.php @@ -0,0 +1,26 @@ +assertEquals(3, $drop->write('hel')); + $this->assertEquals(2, $drop->write('lo')); + $this->assertEquals(5, $drop->getSize()); + $this->assertEquals('hello', $drop->read(5)); + $this->assertEquals(0, $drop->getSize()); + $drop->write('12345678910'); + $this->assertEquals(5, $stream->getSize()); + $this->assertEquals(5, $drop->getSize()); + $this->assertEquals('12345', (string) $drop); + $this->assertEquals(0, $drop->getSize()); + $drop->write('hello'); + $this->assertSame(0, $drop->write('test')); + } +} diff --git a/deps/vendor/ringcentral/psr7/tests/FnStreamTest.php b/deps/vendor/ringcentral/psr7/tests/FnStreamTest.php new file mode 100644 index 000000000..def436cd9 --- /dev/null +++ b/deps/vendor/ringcentral/psr7/tests/FnStreamTest.php @@ -0,0 +1,92 @@ +seek(1); + } + + public function testProxiesToFunction() + { + $self = $this; + $s = new FnStream(array( + 'read' => function ($len) use ($self) { + $self->assertEquals(3, $len); + return 'foo'; + } + )); + + $this->assertEquals('foo', $s->read(3)); + } + + public function testCanCloseOnDestruct() + { + $called = false; + $s = new FnStream(array( + 'close' => function () use (&$called) { + $called = true; + } + )); + unset($s); + $this->assertTrue($called); + } + + public function testDoesNotRequireClose() + { + $s = new FnStream(array()); + unset($s); + } + + public function testDecoratesStream() + { + $a = Psr7\stream_for('foo'); + $b = FnStream::decorate($a, array()); + $this->assertEquals(3, $b->getSize()); + $this->assertEquals($b->isWritable(), true); + $this->assertEquals($b->isReadable(), true); + $this->assertEquals($b->isSeekable(), true); + $this->assertEquals($b->read(3), 'foo'); + $this->assertEquals($b->tell(), 3); + $this->assertEquals($a->tell(), 3); + $this->assertSame('', $a->read(1)); + $this->assertEquals($b->eof(), true); + $this->assertEquals($a->eof(), true); + $b->seek(0); + $this->assertEquals('foo', (string) $b); + $b->seek(0); + $this->assertEquals('foo', $b->getContents()); + $this->assertEquals($a->getMetadata(), $b->getMetadata()); + $b->seek(0, SEEK_END); + $b->write('bar'); + $this->assertEquals('foobar', (string) $b); + $this->assertInternalType('resource', $b->detach()); + $b->close(); + } + + public function testDecoratesWithCustomizations() + { + $called = false; + $a = Psr7\stream_for('foo'); + $b = FnStream::decorate($a, array( + 'read' => function ($len) use (&$called, $a) { + $called = true; + return $a->read($len); + } + )); + $this->assertEquals('foo', $b->read(3)); + $this->assertTrue($called); + } +} diff --git a/deps/vendor/ringcentral/psr7/tests/FunctionsTest.php b/deps/vendor/ringcentral/psr7/tests/FunctionsTest.php new file mode 100644 index 000000000..032fc5644 --- /dev/null +++ b/deps/vendor/ringcentral/psr7/tests/FunctionsTest.php @@ -0,0 +1,604 @@ +assertEquals('foobaz', Psr7\copy_to_string($s)); + $s->seek(0); + $this->assertEquals('foo', Psr7\copy_to_string($s, 3)); + $this->assertEquals('baz', Psr7\copy_to_string($s, 3)); + $this->assertEquals('', Psr7\copy_to_string($s)); + } + + public function testCopiesToStringStopsWhenReadFails() + { + $s1 = Psr7\stream_for('foobaz'); + $s1 = FnStream::decorate($s1, array( + 'read' => function () { return ''; } + )); + $result = Psr7\copy_to_string($s1); + $this->assertEquals('', $result); + } + + public function testCopiesToStream() + { + $s1 = Psr7\stream_for('foobaz'); + $s2 = Psr7\stream_for(''); + Psr7\copy_to_stream($s1, $s2); + $this->assertEquals('foobaz', (string) $s2); + $s2 = Psr7\stream_for(''); + $s1->seek(0); + Psr7\copy_to_stream($s1, $s2, 3); + $this->assertEquals('foo', (string) $s2); + Psr7\copy_to_stream($s1, $s2, 3); + $this->assertEquals('foobaz', (string) $s2); + } + + public function testStopsCopyToStreamWhenWriteFails() + { + $s1 = Psr7\stream_for('foobaz'); + $s2 = Psr7\stream_for(''); + $s2 = FnStream::decorate($s2, array('write' => function () { return 0; })); + Psr7\copy_to_stream($s1, $s2); + $this->assertEquals('', (string) $s2); + } + + public function testStopsCopyToSteamWhenWriteFailsWithMaxLen() + { + $s1 = Psr7\stream_for('foobaz'); + $s2 = Psr7\stream_for(''); + $s2 = FnStream::decorate($s2, array('write' => function () { return 0; })); + Psr7\copy_to_stream($s1, $s2, 10); + $this->assertEquals('', (string) $s2); + } + + public function testStopsCopyToSteamWhenReadFailsWithMaxLen() + { + $s1 = Psr7\stream_for('foobaz'); + $s1 = FnStream::decorate($s1, array('read' => function () { return ''; })); + $s2 = Psr7\stream_for(''); + Psr7\copy_to_stream($s1, $s2, 10); + $this->assertEquals('', (string) $s2); + } + + public function testReadsLines() + { + $s = Psr7\stream_for("foo\nbaz\nbar"); + $this->assertEquals("foo\n", Psr7\readline($s)); + $this->assertEquals("baz\n", Psr7\readline($s)); + $this->assertEquals("bar", Psr7\readline($s)); + } + + public function testReadsLinesUpToMaxLength() + { + $s = Psr7\stream_for("12345\n"); + $this->assertEquals("123", Psr7\readline($s, 4)); + $this->assertEquals("45\n", Psr7\readline($s)); + } + + public function testReadsLineUntilFalseReturnedFromRead() + { + $s = $this->getMockBuilder('RingCentral\Psr7\Stream') + ->setMethods(array('read', 'eof')) + ->disableOriginalConstructor() + ->getMock(); + $s->expects($this->exactly(2)) + ->method('read') + ->will($this->returnCallback(function () { + static $c = false; + if ($c) { + return false; + } + $c = true; + return 'h'; + })); + $s->expects($this->exactly(2)) + ->method('eof') + ->will($this->returnValue(false)); + $this->assertEquals("h", Psr7\readline($s)); + } + + public function testCalculatesHash() + { + $s = Psr7\stream_for('foobazbar'); + $this->assertEquals(md5('foobazbar'), Psr7\hash($s, 'md5')); + } + + /** + * @expectedException \RuntimeException + */ + public function testCalculatesHashThrowsWhenSeekFails() + { + $s = new NoSeekStream(Psr7\stream_for('foobazbar')); + $s->read(2); + Psr7\hash($s, 'md5'); + } + + public function testCalculatesHashSeeksToOriginalPosition() + { + $s = Psr7\stream_for('foobazbar'); + $s->seek(4); + $this->assertEquals(md5('foobazbar'), Psr7\hash($s, 'md5')); + $this->assertEquals(4, $s->tell()); + } + + public function testOpensFilesSuccessfully() + { + $r = Psr7\try_fopen(__FILE__, 'r'); + $this->assertInternalType('resource', $r); + fclose($r); + } + + /** + * @expectedException \RuntimeException + * @expectedExceptionMessage Unable to open /path/to/does/not/exist using mode r + */ + public function testThrowsExceptionNotWarning() + { + Psr7\try_fopen('/path/to/does/not/exist', 'r'); + } + + public function parseQueryProvider() + { + return array( + // Does not need to parse when the string is empty + array('', array()), + // Can parse mult-values items + array('q=a&q=b', array('q' => array('a', 'b'))), + // Can parse multi-valued items that use numeric indices + array('q[0]=a&q[1]=b', array('q[0]' => 'a', 'q[1]' => 'b')), + // Can parse duplicates and does not include numeric indices + array('q[]=a&q[]=b', array('q[]' => array('a', 'b'))), + // Ensures that the value of "q" is an array even though one value + array('q[]=a', array('q[]' => 'a')), + // Does not modify "." to "_" like PHP's parse_str() + array('q.a=a&q.b=b', array('q.a' => 'a', 'q.b' => 'b')), + // Can decode %20 to " " + array('q%20a=a%20b', array('q a' => 'a b')), + // Can parse funky strings with no values by assigning each to null + array('q&a', array('q' => null, 'a' => null)), + // Does not strip trailing equal signs + array('data=abc=', array('data' => 'abc=')), + // Can store duplicates without affecting other values + array('foo=a&foo=b&?µ=c', array('foo' => array('a', 'b'), '?µ' => 'c')), + // Sets value to null when no "=" is present + array('foo', array('foo' => null)), + // Preserves "0" keys. + array('0', array('0' => null)), + // Sets the value to an empty string when "=" is present + array('0=', array('0' => '')), + // Preserves falsey keys + array('var=0', array('var' => '0')), + array('a[b][c]=1&a[b][c]=2', array('a[b][c]' => array('1', '2'))), + array('a[b]=c&a[d]=e', array('a[b]' => 'c', 'a[d]' => 'e')), + // Ensure it doesn't leave things behind with repeated values + // Can parse mult-values items + array('q=a&q=b&q=c', array('q' => array('a', 'b', 'c'))), + ); + } + + /** + * @dataProvider parseQueryProvider + */ + public function testParsesQueries($input, $output) + { + $result = Psr7\parse_query($input); + $this->assertSame($output, $result); + } + + public function testDoesNotDecode() + { + $str = 'foo%20=bar'; + $data = Psr7\parse_query($str, false); + $this->assertEquals(array('foo%20' => 'bar'), $data); + } + + /** + * @dataProvider parseQueryProvider + */ + public function testParsesAndBuildsQueries($input, $output) + { + $result = Psr7\parse_query($input, false); + $this->assertSame($input, Psr7\build_query($result, false)); + } + + public function testEncodesWithRfc1738() + { + $str = Psr7\build_query(array('foo bar' => 'baz+'), PHP_QUERY_RFC1738); + $this->assertEquals('foo+bar=baz%2B', $str); + } + + public function testEncodesWithRfc3986() + { + $str = Psr7\build_query(array('foo bar' => 'baz+'), PHP_QUERY_RFC3986); + $this->assertEquals('foo%20bar=baz%2B', $str); + } + + public function testDoesNotEncode() + { + $str = Psr7\build_query(array('foo bar' => 'baz+'), false); + $this->assertEquals('foo bar=baz+', $str); + } + + public function testCanControlDecodingType() + { + $result = Psr7\parse_query('var=foo+bar', PHP_QUERY_RFC3986); + $this->assertEquals('foo+bar', $result['var']); + $result = Psr7\parse_query('var=foo+bar', PHP_QUERY_RFC1738); + $this->assertEquals('foo bar', $result['var']); + } + + public function testParsesRequestMessages() + { + $req = "GET /abc HTTP/1.0\r\nHost: foo.com\r\nFoo: Bar\r\nBaz: Bam\r\nBaz: Qux\r\n\r\nTest"; + $request = Psr7\parse_request($req); + $this->assertEquals('GET', $request->getMethod()); + $this->assertEquals('/abc', $request->getRequestTarget()); + $this->assertEquals('1.0', $request->getProtocolVersion()); + $this->assertEquals('foo.com', $request->getHeaderLine('Host')); + $this->assertEquals('Bar', $request->getHeaderLine('Foo')); + $this->assertEquals('Bam, Qux', $request->getHeaderLine('Baz')); + $this->assertEquals('Test', (string) $request->getBody()); + $this->assertEquals('http://foo.com/abc', (string) $request->getUri()); + } + + public function testParsesRequestMessagesWithHttpsScheme() + { + $req = "PUT /abc?baz=bar HTTP/1.1\r\nHost: foo.com:443\r\n\r\n"; + $request = Psr7\parse_request($req); + $this->assertEquals('PUT', $request->getMethod()); + $this->assertEquals('/abc?baz=bar', $request->getRequestTarget()); + $this->assertEquals('1.1', $request->getProtocolVersion()); + $this->assertEquals('foo.com:443', $request->getHeaderLine('Host')); + $this->assertEquals('', (string) $request->getBody()); + $this->assertEquals('https://foo.com/abc?baz=bar', (string) $request->getUri()); + } + + public function testParsesRequestMessagesWithUriWhenHostIsNotFirst() + { + $req = "PUT / HTTP/1.1\r\nFoo: Bar\r\nHost: foo.com\r\n\r\n"; + $request = Psr7\parse_request($req); + $this->assertEquals('PUT', $request->getMethod()); + $this->assertEquals('/', $request->getRequestTarget()); + $this->assertEquals('http://foo.com/', (string) $request->getUri()); + } + + public function testParsesRequestMessagesWithFullUri() + { + $req = "GET https://www.google.com:443/search?q=foobar HTTP/1.1\r\nHost: www.google.com\r\n\r\n"; + $request = Psr7\parse_request($req); + $this->assertEquals('GET', $request->getMethod()); + $this->assertEquals('https://www.google.com:443/search?q=foobar', $request->getRequestTarget()); + $this->assertEquals('1.1', $request->getProtocolVersion()); + $this->assertEquals('www.google.com', $request->getHeaderLine('Host')); + $this->assertEquals('', (string) $request->getBody()); + $this->assertEquals('https://www.google.com/search?q=foobar', (string) $request->getUri()); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testValidatesRequestMessages() + { + Psr7\parse_request("HTTP/1.1 200 OK\r\n\r\n"); + } + + public function testParsesResponseMessages() + { + $res = "HTTP/1.0 200 OK\r\nFoo: Bar\r\nBaz: Bam\r\nBaz: Qux\r\n\r\nTest"; + $response = Psr7\parse_response($res); + $this->assertEquals(200, $response->getStatusCode()); + $this->assertEquals('OK', $response->getReasonPhrase()); + $this->assertEquals('1.0', $response->getProtocolVersion()); + $this->assertEquals('Bar', $response->getHeaderLine('Foo')); + $this->assertEquals('Bam, Qux', $response->getHeaderLine('Baz')); + $this->assertEquals('Test', (string) $response->getBody()); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testValidatesResponseMessages() + { + Psr7\parse_response("GET / HTTP/1.1\r\n\r\n"); + } + + public function testDetermineMimetype() + { + $this->assertNull(Psr7\mimetype_from_extension('not-a-real-extension')); + $this->assertEquals( + 'application/json', + Psr7\mimetype_from_extension('json') + ); + $this->assertEquals( + 'image/jpeg', + Psr7\mimetype_from_filename('/tmp/images/IMG034821.JPEG') + ); + } + + public function testCreatesUriForValue() + { + $this->assertInstanceOf('RingCentral\Psr7\Uri', Psr7\uri_for('/foo')); + $this->assertInstanceOf( + 'RingCentral\Psr7\Uri', + Psr7\uri_for(new Psr7\Uri('/foo')) + ); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testValidatesUri() + { + Psr7\uri_for(array()); + } + + public function testKeepsPositionOfResource() + { + $h = fopen(__FILE__, 'r'); + fseek($h, 10); + $stream = Psr7\stream_for($h); + $this->assertEquals(10, $stream->tell()); + $stream->close(); + } + + public function testCreatesWithFactory() + { + $stream = Psr7\stream_for('foo'); + $this->assertInstanceOf('RingCentral\Psr7\Stream', $stream); + $this->assertEquals('foo', $stream->getContents()); + $stream->close(); + } + + public function testFactoryCreatesFromEmptyString() + { + $s = Psr7\stream_for(); + $this->assertInstanceOf('RingCentral\Psr7\Stream', $s); + } + + public function testFactoryCreatesFromNull() + { + $s = Psr7\stream_for(null); + $this->assertInstanceOf('RingCentral\Psr7\Stream', $s); + } + + public function testFactoryCreatesFromResource() + { + $r = fopen(__FILE__, 'r'); + $s = Psr7\stream_for($r); + $this->assertInstanceOf('RingCentral\Psr7\Stream', $s); + $this->assertSame(file_get_contents(__FILE__), (string) $s); + } + + public function testFactoryCreatesFromObjectWithToString() + { + $r = new HasToString(); + $s = Psr7\stream_for($r); + $this->assertInstanceOf('RingCentral\Psr7\Stream', $s); + $this->assertEquals('foo', (string) $s); + } + + public function testCreatePassesThrough() + { + $s = Psr7\stream_for('foo'); + $this->assertSame($s, Psr7\stream_for($s)); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testThrowsExceptionForUnknown() + { + Psr7\stream_for(new \stdClass()); + } + + public function testReturnsCustomMetadata() + { + $s = Psr7\stream_for('foo', array('metadata' => array('hwm' => 3))); + $this->assertEquals(3, $s->getMetadata('hwm')); + $this->assertArrayHasKey('hwm', $s->getMetadata()); + } + + public function testCanSetSize() + { + $s = Psr7\stream_for('', array('size' => 10)); + $this->assertEquals(10, $s->getSize()); + } + + public function testCanCreateIteratorBasedStream() + { + $a = new \ArrayIterator(array('foo', 'bar', '123')); + $p = Psr7\stream_for($a); + $this->assertInstanceOf('RingCentral\Psr7\PumpStream', $p); + $this->assertEquals('foo', $p->read(3)); + $this->assertFalse($p->eof()); + $this->assertEquals('b', $p->read(1)); + $this->assertEquals('a', $p->read(1)); + $this->assertEquals('r12', $p->read(3)); + $this->assertFalse($p->eof()); + $this->assertEquals('3', $p->getContents()); + $this->assertTrue($p->eof()); + $this->assertEquals(9, $p->tell()); + } + + public function testConvertsRequestsToStrings() + { + $request = new Psr7\Request('PUT', 'http://foo.com/hi?123', array( + 'Baz' => 'bar', + 'Qux' => ' ipsum' + ), 'hello', '1.0'); + $this->assertEquals( + "PUT /hi?123 HTTP/1.0\r\nHost: foo.com\r\nBaz: bar\r\nQux: ipsum\r\n\r\nhello", + Psr7\str($request) + ); + } + + public function testConvertsResponsesToStrings() + { + $response = new Psr7\Response(200, array( + 'Baz' => 'bar', + 'Qux' => ' ipsum' + ), 'hello', '1.0', 'FOO'); + $this->assertEquals( + "HTTP/1.0 200 FOO\r\nBaz: bar\r\nQux: ipsum\r\n\r\nhello", + Psr7\str($response) + ); + } + + public function parseParamsProvider() + { + $res1 = array( + array( + '', + 'rel' => 'front', + 'type' => 'image/jpeg', + ), + array( + '', + 'rel' => 'back', + 'type' => 'image/jpeg', + ), + ); + return array( + array( + '; rel="front"; type="image/jpeg", ; rel=back; type="image/jpeg"', + $res1 + ), + array( + '; rel="front"; type="image/jpeg",; rel=back; type="image/jpeg"', + $res1 + ), + array( + 'foo="baz"; bar=123, boo, test="123", foobar="foo;bar"', + array( + array('foo' => 'baz', 'bar' => '123'), + array('boo'), + array('test' => '123'), + array('foobar' => 'foo;bar') + ) + ), + array( + '; rel="side"; type="image/jpeg",; rel=side; type="image/jpeg"', + array( + array('', 'rel' => 'side', 'type' => 'image/jpeg'), + array('', 'rel' => 'side', 'type' => 'image/jpeg') + ) + ), + array( + '', + array() + ) + ); + } + /** + * @dataProvider parseParamsProvider + */ + public function testParseParams($header, $result) + { + $this->assertEquals($result, Psr7\parse_header($header)); + } + + public function testParsesArrayHeaders() + { + $header = array('a, b', 'c', 'd, e'); + $this->assertEquals(array('a', 'b', 'c', 'd', 'e'), Psr7\normalize_header($header)); + } + + public function testRewindsBody() + { + $body = Psr7\stream_for('abc'); + $res = new Psr7\Response(200, array(), $body); + Psr7\rewind_body($res); + $this->assertEquals(0, $body->tell()); + $body->rewind(1); + Psr7\rewind_body($res); + $this->assertEquals(0, $body->tell()); + } + + /** + * @expectedException \RuntimeException + */ + public function testThrowsWhenBodyCannotBeRewound() + { + $body = Psr7\stream_for('abc'); + $body->read(1); + $body = FnStream::decorate($body, array( + 'rewind' => function () { throw new \RuntimeException('a'); } + )); + $res = new Psr7\Response(200, array(), $body); + Psr7\rewind_body($res); + } + + public function testCanModifyRequestWithUri() + { + $r1 = new Psr7\Request('GET', 'http://foo.com'); + $r2 = Psr7\modify_request($r1, array( + 'uri' => new Psr7\Uri('http://www.foo.com') + )); + $this->assertEquals('http://www.foo.com', (string) $r2->getUri()); + $this->assertEquals('www.foo.com', (string) $r2->getHeaderLine('host')); + } + + public function testCanModifyRequestWithCaseInsensitiveHeader() + { + $r1 = new Psr7\Request('GET', 'http://foo.com', array('User-Agent' => 'foo')); + $r2 = Psr7\modify_request($r1, array('set_headers' => array('User-agent' => 'bar'))); + $this->assertEquals('bar', $r2->getHeaderLine('User-Agent')); + $this->assertEquals('bar', $r2->getHeaderLine('User-agent')); + } + + public function testReturnsAsIsWhenNoChanges() + { + $request = new Psr7\Request('GET', 'http://foo.com'); + $this->assertSame($request, Psr7\modify_request($request, array())); + } + + public function testReturnsUriAsIsWhenNoChanges() + { + $r1 = new Psr7\Request('GET', 'http://foo.com'); + $r2 = Psr7\modify_request($r1, array('set_headers' => array('foo' => 'bar'))); + $this->assertNotSame($r1, $r2); + $this->assertEquals('bar', $r2->getHeaderLine('foo')); + } + + public function testRemovesHeadersFromMessage() + { + $r1 = new Psr7\Request('GET', 'http://foo.com', array('foo' => 'bar')); + $r2 = Psr7\modify_request($r1, array('remove_headers' => array('foo'))); + $this->assertNotSame($r1, $r2); + $this->assertFalse($r2->hasHeader('foo')); + } + + public function testAddsQueryToUri() + { + $r1 = new Psr7\Request('GET', 'http://foo.com'); + $r2 = Psr7\modify_request($r1, array('query' => 'foo=bar')); + $this->assertNotSame($r1, $r2); + $this->assertEquals('foo=bar', $r2->getUri()->getQuery()); + } + + public function testServerRequestWithServerParams() + { + $requestString = "GET /abc HTTP/1.1\r\nHost: foo.com\r\n\r\n"; + $request = Psr7\parse_server_request($requestString); + + $this->assertEquals(array(), $request->getServerParams()); + } + + public function testServerRequestWithoutServerParams() + { + $requestString = "GET /abc HTTP/1.1\r\nHost: foo.com\r\n\r\n"; + $serverParams = array('server_address' => '127.0.0.1', 'server_port' => 80); + + $request = Psr7\parse_server_request($requestString, $serverParams); + + $this->assertEquals(array('server_address' => '127.0.0.1', 'server_port' => 80), $request->getServerParams()); + } +} diff --git a/deps/vendor/ringcentral/psr7/tests/InflateStreamTest.php b/deps/vendor/ringcentral/psr7/tests/InflateStreamTest.php new file mode 100644 index 000000000..cd699eb34 --- /dev/null +++ b/deps/vendor/ringcentral/psr7/tests/InflateStreamTest.php @@ -0,0 +1,21 @@ +assertEquals('test', (string) $b); + } +} diff --git a/deps/vendor/ringcentral/psr7/tests/LazyOpenStreamTest.php b/deps/vendor/ringcentral/psr7/tests/LazyOpenStreamTest.php new file mode 100644 index 000000000..ca0c18e78 --- /dev/null +++ b/deps/vendor/ringcentral/psr7/tests/LazyOpenStreamTest.php @@ -0,0 +1,64 @@ +fname = tempnam('/tmp', 'tfile'); + + if (file_exists($this->fname)) { + unlink($this->fname); + } + } + + public function tearDown() + { + if (file_exists($this->fname)) { + unlink($this->fname); + } + } + + public function testOpensLazily() + { + $l = new LazyOpenStream($this->fname, 'w+'); + $l->write('foo'); + $this->assertInternalType('array', $l->getMetadata()); + $this->assertFileExists($this->fname); + $this->assertEquals('foo', file_get_contents($this->fname)); + $this->assertEquals('foo', (string) $l); + } + + public function testProxiesToFile() + { + file_put_contents($this->fname, 'foo'); + $l = new LazyOpenStream($this->fname, 'r'); + $this->assertEquals('foo', $l->read(4)); + $this->assertTrue($l->eof()); + $this->assertEquals(3, $l->tell()); + $this->assertTrue($l->isReadable()); + $this->assertTrue($l->isSeekable()); + $this->assertFalse($l->isWritable()); + $l->seek(1); + $this->assertEquals('oo', $l->getContents()); + $this->assertEquals('foo', (string) $l); + $this->assertEquals(3, $l->getSize()); + $this->assertInternalType('array', $l->getMetadata()); + $l->close(); + } + + public function testDetachesUnderlyingStream() + { + file_put_contents($this->fname, 'foo'); + $l = new LazyOpenStream($this->fname, 'r'); + $r = $l->detach(); + $this->assertInternalType('resource', $r); + fseek($r, 0); + $this->assertEquals('foo', stream_get_contents($r)); + fclose($r); + } +} diff --git a/deps/vendor/ringcentral/psr7/tests/LimitStreamTest.php b/deps/vendor/ringcentral/psr7/tests/LimitStreamTest.php new file mode 100644 index 000000000..7053300ee --- /dev/null +++ b/deps/vendor/ringcentral/psr7/tests/LimitStreamTest.php @@ -0,0 +1,166 @@ +decorated = Psr7\stream_for(fopen(__FILE__, 'r')); + $this->body = new LimitStream($this->decorated, 10, 3); + } + + public function testReturnsSubset() + { + $body = new LimitStream(Psr7\stream_for('foo'), -1, 1); + $this->assertEquals('oo', (string) $body); + $this->assertTrue($body->eof()); + $body->seek(0); + $this->assertFalse($body->eof()); + $this->assertEquals('oo', $body->read(100)); + $this->assertSame('', $body->read(1)); + $this->assertTrue($body->eof()); + } + + public function testReturnsSubsetWhenCastToString() + { + $body = Psr7\stream_for('foo_baz_bar'); + $limited = new LimitStream($body, 3, 4); + $this->assertEquals('baz', (string) $limited); + } + + /** + * @expectedException \RuntimeException + * @expectedExceptionMessage Unable to seek to stream position 10 with whence 0 + */ + public function testEnsuresPositionCanBeekSeekedTo() + { + new LimitStream(Psr7\stream_for(''), 0, 10); + } + + public function testReturnsSubsetOfEmptyBodyWhenCastToString() + { + $body = Psr7\stream_for('01234567891234'); + $limited = new LimitStream($body, 0, 10); + $this->assertEquals('', (string) $limited); + } + + public function testReturnsSpecificSubsetOBodyWhenCastToString() + { + $body = Psr7\stream_for('0123456789abcdef'); + $limited = new LimitStream($body, 3, 10); + $this->assertEquals('abc', (string) $limited); + } + + public function testSeeksWhenConstructed() + { + $this->assertEquals(0, $this->body->tell()); + $this->assertEquals(3, $this->decorated->tell()); + } + + public function testAllowsBoundedSeek() + { + $this->body->seek(100); + $this->assertEquals(10, $this->body->tell()); + $this->assertEquals(13, $this->decorated->tell()); + $this->body->seek(0); + $this->assertEquals(0, $this->body->tell()); + $this->assertEquals(3, $this->decorated->tell()); + try { + $this->body->seek(-10); + $this->fail(); + } catch (\RuntimeException $e) {} + $this->assertEquals(0, $this->body->tell()); + $this->assertEquals(3, $this->decorated->tell()); + $this->body->seek(5); + $this->assertEquals(5, $this->body->tell()); + $this->assertEquals(8, $this->decorated->tell()); + // Fail + try { + $this->body->seek(1000, SEEK_END); + $this->fail(); + } catch (\RuntimeException $e) {} + } + + public function testReadsOnlySubsetOfData() + { + $data = $this->body->read(100); + $this->assertEquals(10, strlen($data)); + $this->assertSame('', $this->body->read(1000)); + + $this->body->setOffset(10); + $newData = $this->body->read(100); + $this->assertEquals(10, strlen($newData)); + $this->assertNotSame($data, $newData); + } + + /** + * @expectedException \RuntimeException + * @expectedExceptionMessage Could not seek to stream offset 2 + */ + public function testThrowsWhenCurrentGreaterThanOffsetSeek() + { + $a = Psr7\stream_for('foo_bar'); + $b = new NoSeekStream($a); + $c = new LimitStream($b); + $a->getContents(); + $c->setOffset(2); + } + + public function testCanGetContentsWithoutSeeking() + { + $a = Psr7\stream_for('foo_bar'); + $b = new NoSeekStream($a); + $c = new LimitStream($b); + $this->assertEquals('foo_bar', $c->getContents()); + } + + public function testClaimsConsumedWhenReadLimitIsReached() + { + $this->assertFalse($this->body->eof()); + $this->body->read(1000); + $this->assertTrue($this->body->eof()); + } + + public function testContentLengthIsBounded() + { + $this->assertEquals(10, $this->body->getSize()); + } + + public function testGetContentsIsBasedOnSubset() + { + $body = new LimitStream(Psr7\stream_for('foobazbar'), 3, 3); + $this->assertEquals('baz', $body->getContents()); + } + + public function testReturnsNullIfSizeCannotBeDetermined() + { + $a = new FnStream(array( + 'getSize' => function () { return null; }, + 'tell' => function () { return 0; }, + )); + $b = new LimitStream($a); + $this->assertNull($b->getSize()); + } + + public function testLengthLessOffsetWhenNoLimitSize() + { + $a = Psr7\stream_for('foo_bar'); + $b = new LimitStream($a, -1, 4); + $this->assertEquals(3, $b->getSize()); + } +} diff --git a/deps/vendor/ringcentral/psr7/tests/MultipartStreamTest.php b/deps/vendor/ringcentral/psr7/tests/MultipartStreamTest.php new file mode 100644 index 000000000..22edea418 --- /dev/null +++ b/deps/vendor/ringcentral/psr7/tests/MultipartStreamTest.php @@ -0,0 +1,214 @@ +assertNotEmpty($b->getBoundary()); + } + + public function testCanProvideBoundary() + { + $b = new MultipartStream(array(), 'foo'); + $this->assertEquals('foo', $b->getBoundary()); + } + + public function testIsNotWritable() + { + $b = new MultipartStream(); + $this->assertFalse($b->isWritable()); + } + + public function testCanCreateEmptyStream() + { + $b = new MultipartStream(); + $boundary = $b->getBoundary(); + $this->assertSame("--{$boundary}--\r\n", $b->getContents()); + $this->assertSame(strlen($boundary) + 6, $b->getSize()); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testValidatesFilesArrayElement() + { + new MultipartStream(array(array('foo' => 'bar'))); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testEnsuresFileHasName() + { + new MultipartStream(array(array('contents' => 'bar'))); + } + + public function testSerializesFields() + { + $b = new MultipartStream(array( + array( + 'name' => 'foo', + 'contents' => 'bar' + ), + array( + 'name' => 'baz', + 'contents' => 'bam' + ) + ), 'boundary'); + $this->assertEquals( + "--boundary\r\nContent-Disposition: form-data; name=\"foo\"\r\nContent-Length: 3\r\n\r\n" + . "bar\r\n--boundary\r\nContent-Disposition: form-data; name=\"baz\"\r\nContent-Length: 3" + . "\r\n\r\nbam\r\n--boundary--\r\n", (string) $b); + } + + public function testSerializesFiles() + { + $f1 = Psr7\FnStream::decorate(Psr7\stream_for('foo'), array( + 'getMetadata' => function () { + return '/foo/bar.txt'; + } + )); + + $f2 = Psr7\FnStream::decorate(Psr7\stream_for('baz'), array( + 'getMetadata' => function () { + return '/foo/baz.jpg'; + } + )); + + $f3 = Psr7\FnStream::decorate(Psr7\stream_for('bar'), array( + 'getMetadata' => function () { + return '/foo/bar.gif'; + } + )); + + $b = new MultipartStream(array( + array( + 'name' => 'foo', + 'contents' => $f1 + ), + array( + 'name' => 'qux', + 'contents' => $f2 + ), + array( + 'name' => 'qux', + 'contents' => $f3 + ), + ), 'boundary'); + + $expected = <<assertEquals($expected, str_replace("\r", '', $b)); + } + + public function testSerializesFilesWithCustomHeaders() + { + $f1 = Psr7\FnStream::decorate(Psr7\stream_for('foo'), array( + 'getMetadata' => function () { + return '/foo/bar.txt'; + } + )); + + $b = new MultipartStream(array( + array( + 'name' => 'foo', + 'contents' => $f1, + 'headers' => array( + 'x-foo' => 'bar', + 'content-disposition' => 'custom' + ) + ) + ), 'boundary'); + + $expected = <<assertEquals($expected, str_replace("\r", '', $b)); + } + + public function testSerializesFilesWithCustomHeadersAndMultipleValues() + { + $f1 = Psr7\FnStream::decorate(Psr7\stream_for('foo'), array( + 'getMetadata' => function () { + return '/foo/bar.txt'; + } + )); + + $f2 = Psr7\FnStream::decorate(Psr7\stream_for('baz'), array( + 'getMetadata' => function () { + return '/foo/baz.jpg'; + } + )); + + $b = new MultipartStream(array( + array( + 'name' => 'foo', + 'contents' => $f1, + 'headers' => array( + 'x-foo' => 'bar', + 'content-disposition' => 'custom' + ) + ), + array( + 'name' => 'foo', + 'contents' => $f2, + 'headers' => array('cOntenT-Type' => 'custom'), + ) + ), 'boundary'); + + $expected = <<assertEquals($expected, str_replace("\r", '', $b)); + } +} diff --git a/deps/vendor/ringcentral/psr7/tests/NoSeekStreamTest.php b/deps/vendor/ringcentral/psr7/tests/NoSeekStreamTest.php new file mode 100644 index 000000000..a831789b7 --- /dev/null +++ b/deps/vendor/ringcentral/psr7/tests/NoSeekStreamTest.php @@ -0,0 +1,40 @@ +getMockBuilder('Psr\Http\Message\StreamInterface') + ->setMethods(array('isSeekable', 'seek')) + ->getMockForAbstractClass(); + $s->expects($this->never())->method('seek'); + $s->expects($this->never())->method('isSeekable'); + $wrapped = new NoSeekStream($s); + $this->assertFalse($wrapped->isSeekable()); + $wrapped->seek(2); + } + + /** + * @expectedException \RuntimeException + * @expectedExceptionMessage Cannot write to a non-writable stream + */ + public function testHandlesClose() + { + $s = Psr7\stream_for('foo'); + $wrapped = new NoSeekStream($s); + $wrapped->close(); + $wrapped->write('foo'); + } +} diff --git a/deps/vendor/ringcentral/psr7/tests/PumpStreamTest.php b/deps/vendor/ringcentral/psr7/tests/PumpStreamTest.php new file mode 100644 index 000000000..6b146e159 --- /dev/null +++ b/deps/vendor/ringcentral/psr7/tests/PumpStreamTest.php @@ -0,0 +1,72 @@ + array('foo' => 'bar'), + 'size' => 100 + )); + + $this->assertEquals('bar', $p->getMetadata('foo')); + $this->assertEquals(array('foo' => 'bar'), $p->getMetadata()); + $this->assertEquals(100, $p->getSize()); + } + + public function testCanReadFromCallable() + { + $p = Psr7\stream_for(function ($size) { + return 'a'; + }); + $this->assertEquals('a', $p->read(1)); + $this->assertEquals(1, $p->tell()); + $this->assertEquals('aaaaa', $p->read(5)); + $this->assertEquals(6, $p->tell()); + } + + public function testStoresExcessDataInBuffer() + { + $called = array(); + $p = Psr7\stream_for(function ($size) use (&$called) { + $called[] = $size; + return 'abcdef'; + }); + $this->assertEquals('a', $p->read(1)); + $this->assertEquals('b', $p->read(1)); + $this->assertEquals('cdef', $p->read(4)); + $this->assertEquals('abcdefabc', $p->read(9)); + $this->assertEquals(array(1, 9, 3), $called); + } + + public function testInifiniteStreamWrappedInLimitStream() + { + $p = Psr7\stream_for(function () { return 'a'; }); + $s = new LimitStream($p, 5); + $this->assertEquals('aaaaa', (string) $s); + } + + public function testDescribesCapabilities() + { + $p = Psr7\stream_for(function () {}); + $this->assertTrue($p->isReadable()); + $this->assertFalse($p->isSeekable()); + $this->assertFalse($p->isWritable()); + $this->assertNull($p->getSize()); + $this->assertEquals('', $p->getContents()); + $this->assertEquals('', (string) $p); + $p->close(); + $this->assertEquals('', $p->read(10)); + $this->assertTrue($p->eof()); + + try { + $this->assertFalse($p->write('aa')); + $this->fail(); + } catch (\RuntimeException $e) {} + } +} diff --git a/deps/vendor/ringcentral/psr7/tests/RequestTest.php b/deps/vendor/ringcentral/psr7/tests/RequestTest.php new file mode 100644 index 000000000..ad6f0cb52 --- /dev/null +++ b/deps/vendor/ringcentral/psr7/tests/RequestTest.php @@ -0,0 +1,157 @@ +assertEquals('/', (string) $r->getUri()); + } + + public function testRequestUriMayBeUri() + { + $uri = new Uri('/'); + $r = new Request('GET', $uri); + $this->assertSame($uri, $r->getUri()); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testValidateRequestUri() + { + new Request('GET', true); + } + + public function testCanConstructWithBody() + { + $r = new Request('GET', '/', array(), 'baz'); + $this->assertEquals('baz', (string) $r->getBody()); + } + + public function testCapitalizesMethod() + { + $r = new Request('get', '/'); + $this->assertEquals('GET', $r->getMethod()); + } + + public function testCapitalizesWithMethod() + { + $r = new Request('GET', '/'); + $this->assertEquals('PUT', $r->withMethod('put')->getMethod()); + } + + public function testWithUri() + { + $r1 = new Request('GET', '/'); + $u1 = $r1->getUri(); + $u2 = new Uri('http://www.example.com'); + $r2 = $r1->withUri($u2); + $this->assertNotSame($r1, $r2); + $this->assertSame($u2, $r2->getUri()); + $this->assertSame($u1, $r1->getUri()); + } + + public function testSameInstanceWhenSameUri() + { + $r1 = new Request('GET', 'http://foo.com'); + $r2 = $r1->withUri($r1->getUri()); + $this->assertSame($r1, $r2); + } + + public function testWithRequestTarget() + { + $r1 = new Request('GET', '/'); + $r2 = $r1->withRequestTarget('*'); + $this->assertEquals('*', $r2->getRequestTarget()); + $this->assertEquals('/', $r1->getRequestTarget()); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testRequestTargetDoesNotAllowSpaces() + { + $r1 = new Request('GET', '/'); + $r1->withRequestTarget('/foo bar'); + } + + public function testRequestTargetDefaultsToSlash() + { + $r1 = new Request('GET', ''); + $this->assertEquals('/', $r1->getRequestTarget()); + $r2 = new Request('GET', '*'); + $this->assertEquals('*', $r2->getRequestTarget()); + $r3 = new Request('GET', 'http://foo.com/bar baz/'); + $this->assertEquals('/bar%20baz/', $r3->getRequestTarget()); + } + + public function testBuildsRequestTarget() + { + $r1 = new Request('GET', 'http://foo.com/baz?bar=bam'); + $this->assertEquals('/baz?bar=bam', $r1->getRequestTarget()); + } + + public function testHostIsAddedFirst() + { + $r = new Request('GET', 'http://foo.com/baz?bar=bam', array('Foo' => 'Bar')); + $this->assertEquals(array( + 'Host' => array('foo.com'), + 'Foo' => array('Bar') + ), $r->getHeaders()); + } + + public function testCanGetHeaderAsCsv() + { + $r = new Request('GET', 'http://foo.com/baz?bar=bam', array( + 'Foo' => array('a', 'b', 'c') + )); + $this->assertEquals('a, b, c', $r->getHeaderLine('Foo')); + $this->assertEquals('', $r->getHeaderLine('Bar')); + } + + public function testHostIsNotOverwrittenWhenPreservingHost() + { + $r = new Request('GET', 'http://foo.com/baz?bar=bam', array('Host' => 'a.com')); + $this->assertEquals(array('Host' => array('a.com')), $r->getHeaders()); + $r2 = $r->withUri(new Uri('http://www.foo.com/bar'), true); + $this->assertEquals('a.com', $r2->getHeaderLine('Host')); + } + + public function testOverridesHostWithUri() + { + $r = new Request('GET', 'http://foo.com/baz?bar=bam'); + $this->assertEquals(array('Host' => array('foo.com')), $r->getHeaders()); + $r2 = $r->withUri(new Uri('http://www.baz.com/bar')); + $this->assertEquals('www.baz.com', $r2->getHeaderLine('Host')); + } + + public function testAggregatesHeaders() + { + $r = new Request('GET', 'http://foo.com', array( + 'ZOO' => 'zoobar', + 'zoo' => array('foobar', 'zoobar') + )); + $this->assertEquals('zoobar, foobar, zoobar', $r->getHeaderLine('zoo')); + } + + public function testAddsPortToHeader() + { + $r = new Request('GET', 'http://foo.com:8124/bar'); + $this->assertEquals('foo.com:8124', $r->getHeaderLine('host')); + } + + public function testAddsPortToHeaderAndReplacePreviousPort() + { + $r = new Request('GET', 'http://foo.com:8124/bar'); + $r = $r->withUri(new Uri('http://foo.com:8125/bar')); + $this->assertEquals('foo.com:8125', $r->getHeaderLine('host')); + } +} diff --git a/deps/vendor/ringcentral/psr7/tests/ResponseTest.php b/deps/vendor/ringcentral/psr7/tests/ResponseTest.php new file mode 100644 index 000000000..52b7ba12b --- /dev/null +++ b/deps/vendor/ringcentral/psr7/tests/ResponseTest.php @@ -0,0 +1,154 @@ +assertSame(200, $r->getStatusCode()); + $this->assertEquals('OK', $r->getReasonPhrase()); + } + + public function testCanGiveCustomReason() + { + $r = new Response(200, array(), null, '1.1', 'bar'); + $this->assertEquals('bar', $r->getReasonPhrase()); + } + + public function testCanGiveCustomProtocolVersion() + { + $r = new Response(200, array(), null, '1000'); + $this->assertEquals('1000', $r->getProtocolVersion()); + } + + public function testCanCreateNewResponseWithStatusAndNoReason() + { + $r = new Response(200); + $r2 = $r->withStatus(201); + $this->assertEquals(200, $r->getStatusCode()); + $this->assertEquals('OK', $r->getReasonPhrase()); + $this->assertEquals(201, $r2->getStatusCode()); + $this->assertEquals('Created', $r2->getReasonPhrase()); + } + + public function testCanCreateNewResponseWithStatusAndReason() + { + $r = new Response(200); + $r2 = $r->withStatus(201, 'Foo'); + $this->assertEquals(200, $r->getStatusCode()); + $this->assertEquals('OK', $r->getReasonPhrase()); + $this->assertEquals(201, $r2->getStatusCode()); + $this->assertEquals('Foo', $r2->getReasonPhrase()); + } + + public function testCreatesResponseWithAddedHeaderArray() + { + $r = new Response(); + $r2 = $r->withAddedHeader('foo', array('baz', 'bar')); + $this->assertFalse($r->hasHeader('foo')); + $this->assertEquals('baz, bar', $r2->getHeaderLine('foo')); + } + + public function testReturnsIdentityWhenRemovingMissingHeader() + { + $r = new Response(); + $this->assertSame($r, $r->withoutHeader('foo')); + } + + public function testAlwaysReturnsBody() + { + $r = new Response(); + $this->assertInstanceOf('Psr\Http\Message\StreamInterface', $r->getBody()); + } + + public function testCanSetHeaderAsArray() + { + $r = new Response(200, array( + 'foo' => array('baz ', ' bar ') + )); + $this->assertEquals('baz, bar', $r->getHeaderLine('foo')); + $this->assertEquals(array('baz', 'bar'), $r->getHeader('foo')); + } + + public function testSameInstanceWhenSameBody() + { + $r = new Response(200, array(), 'foo'); + $b = $r->getBody(); + $this->assertSame($r, $r->withBody($b)); + } + + public function testNewInstanceWhenNewBody() + { + $r = new Response(200, array(), 'foo'); + $b2 = Psr7\stream_for('abc'); + $this->assertNotSame($r, $r->withBody($b2)); + } + + public function testSameInstanceWhenSameProtocol() + { + $r = new Response(200); + $this->assertSame($r, $r->withProtocolVersion('1.1')); + } + + public function testNewInstanceWhenNewProtocol() + { + $r = new Response(200); + $this->assertNotSame($r, $r->withProtocolVersion('1.0')); + } + + public function testNewInstanceWhenRemovingHeader() + { + $r = new Response(200, array('Foo' => 'Bar')); + $r2 = $r->withoutHeader('Foo'); + $this->assertNotSame($r, $r2); + $this->assertFalse($r2->hasHeader('foo')); + } + + public function testNewInstanceWhenAddingHeader() + { + $r = new Response(200, array('Foo' => 'Bar')); + $r2 = $r->withAddedHeader('Foo', 'Baz'); + $this->assertNotSame($r, $r2); + $this->assertEquals('Bar, Baz', $r2->getHeaderLine('foo')); + } + + public function testNewInstanceWhenAddingHeaderArray() + { + $r = new Response(200, array('Foo' => 'Bar')); + $r2 = $r->withAddedHeader('Foo', array('Baz', 'Qux')); + $this->assertNotSame($r, $r2); + $this->assertEquals(array('Bar', 'Baz', 'Qux'), $r2->getHeader('foo')); + } + + public function testNewInstanceWhenAddingHeaderThatWasNotThereBefore() + { + $r = new Response(200, array('Foo' => 'Bar')); + $r2 = $r->withAddedHeader('Baz', 'Bam'); + $this->assertNotSame($r, $r2); + $this->assertEquals('Bam', $r2->getHeaderLine('Baz')); + $this->assertEquals('Bar', $r2->getHeaderLine('Foo')); + } + + public function testRemovesPreviouslyAddedHeaderOfDifferentCase() + { + $r = new Response(200, array('Foo' => 'Bar')); + $r2 = $r->withHeader('foo', 'Bam'); + $this->assertNotSame($r, $r2); + $this->assertEquals('Bam', $r2->getHeaderLine('Foo')); + } + + public function testBodyConsistent() + { + $r = new Response(200, array(), '0'); + $this->assertEquals('0', (string)$r->getBody()); + } + +} diff --git a/deps/vendor/ringcentral/psr7/tests/ServerRequestTest.php b/deps/vendor/ringcentral/psr7/tests/ServerRequestTest.php new file mode 100644 index 000000000..4bdfe8e28 --- /dev/null +++ b/deps/vendor/ringcentral/psr7/tests/ServerRequestTest.php @@ -0,0 +1,85 @@ +request = new ServerRequest('GET', 'http://localhost'); + } + + public function testGetNoAttributes() + { + $this->assertEquals(array(), $this->request->getAttributes()); + } + + public function testWithAttribute() + { + $request = $this->request->withAttribute('hello', 'world'); + + $this->assertNotSame($request, $this->request); + $this->assertEquals(array('hello' => 'world'), $request->getAttributes()); + } + + public function testGetAttribute() + { + $request = $this->request->withAttribute('hello', 'world'); + + $this->assertNotSame($request, $this->request); + $this->assertEquals('world', $request->getAttribute('hello')); + } + + public function testGetDefaultAttribute() + { + $request = $this->request->withAttribute('hello', 'world'); + + $this->assertNotSame($request, $this->request); + $this->assertEquals(null, $request->getAttribute('hi', null)); + } + + public function testWithoutAttribute() + { + $request = $this->request->withAttribute('hello', 'world'); + $request = $request->withAttribute('test', 'nice'); + + $request = $request->withoutAttribute('hello'); + + $this->assertNotSame($request, $this->request); + $this->assertEquals(array('test' => 'nice'), $request->getAttributes()); + } + + public function testWithCookieParams() + { + $request = $this->request->withCookieParams(array('test' => 'world')); + + $this->assertNotSame($request, $this->request); + $this->assertEquals(array('test' => 'world'), $request->getCookieParams()); + } + + public function testWithQueryParams() + { + $request = $this->request->withQueryParams(array('test' => 'world')); + + $this->assertNotSame($request, $this->request); + $this->assertEquals(array('test' => 'world'), $request->getQueryParams()); + } + + public function testWithUploadedFiles() + { + $request = $this->request->withUploadedFiles(array('test' => 'world')); + + $this->assertNotSame($request, $this->request); + $this->assertEquals(array('test' => 'world'), $request->getUploadedFiles()); + } + + public function testWithParsedBody() + { + $request = $this->request->withParsedBody(array('test' => 'world')); + + $this->assertNotSame($request, $this->request); + $this->assertEquals(array('test' => 'world'), $request->getParsedBody()); + } +} diff --git a/deps/vendor/ringcentral/psr7/tests/StreamDecoratorTraitTest.php b/deps/vendor/ringcentral/psr7/tests/StreamDecoratorTraitTest.php new file mode 100644 index 000000000..b0c3dc5c9 --- /dev/null +++ b/deps/vendor/ringcentral/psr7/tests/StreamDecoratorTraitTest.php @@ -0,0 +1,123 @@ +c = fopen('php://temp', 'r+'); + fwrite($this->c, 'foo'); + fseek($this->c, 0); + $this->a = Psr7\stream_for($this->c); + $this->b = new Str($this->a); + } + + public function testCatchesExceptionsWhenCastingToString() + { + $s = $this->getMockBuilder('Psr\Http\Message\StreamInterface') + ->setMethods(array('read')) + ->getMockForAbstractClass(); + $s->expects($this->once()) + ->method('read') + ->will($this->throwException(new \Exception('foo'))); + $msg = ''; + set_error_handler(function ($errNo, $str) use (&$msg) { + $msg = $str; + }); + echo new Str($s); + restore_error_handler(); + $this->assertContains('foo', $msg); + } + + public function testToString() + { + $this->assertEquals('foo', (string)$this->b); + } + + public function testHasSize() + { + $this->assertEquals(3, $this->b->getSize()); + } + + public function testReads() + { + $this->assertEquals('foo', $this->b->read(10)); + } + + public function testCheckMethods() + { + $this->assertEquals($this->a->isReadable(), $this->b->isReadable()); + $this->assertEquals($this->a->isWritable(), $this->b->isWritable()); + $this->assertEquals($this->a->isSeekable(), $this->b->isSeekable()); + } + + public function testSeeksAndTells() + { + $this->b->seek(1); + $this->assertEquals(1, $this->a->tell()); + $this->assertEquals(1, $this->b->tell()); + $this->b->seek(0); + $this->assertEquals(0, $this->a->tell()); + $this->assertEquals(0, $this->b->tell()); + $this->b->seek(0, SEEK_END); + $this->assertEquals(3, $this->a->tell()); + $this->assertEquals(3, $this->b->tell()); + } + + public function testGetsContents() + { + $this->assertEquals('foo', $this->b->getContents()); + $this->assertEquals('', $this->b->getContents()); + $this->b->seek(1); + $this->assertEquals('oo', $this->b->getContents(1)); + } + + public function testCloses() + { + $this->b->close(); + $this->assertFalse(is_resource($this->c)); + } + + public function testDetaches() + { + $this->b->detach(); + $this->assertFalse($this->b->isReadable()); + } + + public function testWrapsMetadata() + { + $this->assertSame($this->b->getMetadata(), $this->a->getMetadata()); + $this->assertSame($this->b->getMetadata('uri'), $this->a->getMetadata('uri')); + } + + public function testWrapsWrites() + { + $this->b->seek(0, SEEK_END); + $this->b->write('foo'); + $this->assertEquals('foofoo', (string)$this->a); + } + + /** + * @expectedException \UnexpectedValueException + */ + public function testThrowsWithInvalidGetter() + { + $this->b->foo; + } + +} \ No newline at end of file diff --git a/deps/vendor/ringcentral/psr7/tests/StreamTest.php b/deps/vendor/ringcentral/psr7/tests/StreamTest.php new file mode 100644 index 000000000..550180579 --- /dev/null +++ b/deps/vendor/ringcentral/psr7/tests/StreamTest.php @@ -0,0 +1,163 @@ +assertTrue($stream->isReadable()); + $this->assertTrue($stream->isWritable()); + $this->assertTrue($stream->isSeekable()); + $this->assertEquals('php://temp', $stream->getMetadata('uri')); + $this->assertInternalType('array', $stream->getMetadata()); + $this->assertEquals(4, $stream->getSize()); + $this->assertFalse($stream->eof()); + $stream->close(); + } + + public function testStreamClosesHandleOnDestruct() + { + $handle = fopen('php://temp', 'r'); + $stream = new Stream($handle); + unset($stream); + $this->assertFalse(is_resource($handle)); + } + + public function testConvertsToString() + { + $handle = fopen('php://temp', 'w+'); + fwrite($handle, 'data'); + $stream = new Stream($handle); + $this->assertEquals('data', (string) $stream); + $this->assertEquals('data', (string) $stream); + $stream->close(); + } + + public function testGetsContents() + { + $handle = fopen('php://temp', 'w+'); + fwrite($handle, 'data'); + $stream = new Stream($handle); + $this->assertEquals('', $stream->getContents()); + $stream->seek(0); + $this->assertEquals('data', $stream->getContents()); + $this->assertEquals('', $stream->getContents()); + } + + public function testChecksEof() + { + $handle = fopen('php://temp', 'w+'); + fwrite($handle, 'data'); + $stream = new Stream($handle); + $this->assertFalse($stream->eof()); + $stream->read(4); + $this->assertTrue($stream->eof()); + $stream->close(); + } + + public function testGetSize() + { + $size = filesize(__FILE__); + $handle = fopen(__FILE__, 'r'); + $stream = new Stream($handle); + $this->assertEquals($size, $stream->getSize()); + // Load from cache + $this->assertEquals($size, $stream->getSize()); + $stream->close(); + } + + public function testEnsuresSizeIsConsistent() + { + $h = fopen('php://temp', 'w+'); + $this->assertEquals(3, fwrite($h, 'foo')); + $stream = new Stream($h); + $this->assertEquals(3, $stream->getSize()); + $this->assertEquals(4, $stream->write('test')); + $this->assertEquals(7, $stream->getSize()); + $this->assertEquals(7, $stream->getSize()); + $stream->close(); + } + + public function testProvidesStreamPosition() + { + $handle = fopen('php://temp', 'w+'); + $stream = new Stream($handle); + $this->assertEquals(0, $stream->tell()); + $stream->write('foo'); + $this->assertEquals(3, $stream->tell()); + $stream->seek(1); + $this->assertEquals(1, $stream->tell()); + $this->assertSame(ftell($handle), $stream->tell()); + $stream->close(); + } + + public function testCanDetachStream() + { + $r = fopen('php://temp', 'w+'); + $stream = new Stream($r); + $stream->write('foo'); + $this->assertTrue($stream->isReadable()); + $this->assertSame($r, $stream->detach()); + $stream->detach(); + + $this->assertFalse($stream->isReadable()); + $this->assertFalse($stream->isWritable()); + $this->assertFalse($stream->isSeekable()); + + $self = $this; + + $throws = function ($fn) use ($stream, $self) { + try { + $fn($stream); + $self->fail(); + } catch (\Exception $e) {} + }; + + $throws(function ($stream) { $stream->read(10); }); + $throws(function ($stream) { $stream->write('bar'); }); + $throws(function ($stream) { $stream->seek(10); }); + $throws(function ($stream) { $stream->tell(); }); + $throws(function ($stream) { $stream->eof(); }); + $throws(function ($stream) { $stream->getSize(); }); + $throws(function ($stream) { $stream->getContents(); }); + $this->assertSame('', (string) $stream); + $stream->close(); + } + + public function testCloseClearProperties() + { + $handle = fopen('php://temp', 'r+'); + $stream = new Stream($handle); + $stream->close(); + + $this->assertFalse($stream->isSeekable()); + $this->assertFalse($stream->isReadable()); + $this->assertFalse($stream->isWritable()); + $this->assertNull($stream->getSize()); + $this->assertEmpty($stream->getMetadata()); + } + + public function testDoesNotThrowInToString() + { + $s = \RingCentral\Psr7\stream_for('foo'); + $s = new NoSeekStream($s); + $this->assertEquals('foo', (string) $s); + } +} diff --git a/deps/vendor/ringcentral/psr7/tests/StreamWrapperTest.php b/deps/vendor/ringcentral/psr7/tests/StreamWrapperTest.php new file mode 100644 index 000000000..dd08a83af --- /dev/null +++ b/deps/vendor/ringcentral/psr7/tests/StreamWrapperTest.php @@ -0,0 +1,100 @@ +assertSame('foo', fread($handle, 3)); + $this->assertSame(3, ftell($handle)); + $this->assertSame(3, fwrite($handle, 'bar')); + $this->assertSame(0, fseek($handle, 0)); + $this->assertSame('foobar', fread($handle, 6)); + $this->assertSame('', fread($handle, 1)); + $this->assertTrue(feof($handle)); + + // This fails on HHVM for some reason + if (!defined('HHVM_VERSION')) { + $this->assertEquals(array( + 'dev' => 0, + 'ino' => 0, + 'mode' => 33206, + 'nlink' => 0, + 'uid' => 0, + 'gid' => 0, + 'rdev' => 0, + 'size' => 6, + 'atime' => 0, + 'mtime' => 0, + 'ctime' => 0, + 'blksize' => 0, + 'blocks' => 0, + 0 => 0, + 1 => 0, + 2 => 33206, + 3 => 0, + 4 => 0, + 5 => 0, + 6 => 0, + 7 => 6, + 8 => 0, + 9 => 0, + 10 => 0, + 11 => 0, + 12 => 0, + ), fstat($handle)); + } + + $this->assertTrue(fclose($handle)); + $this->assertSame('foobar', (string) $stream); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testValidatesStream() + { + $stream = $this->getMockBuilder('Psr\Http\Message\StreamInterface') + ->setMethods(array('isReadable', 'isWritable')) + ->getMockForAbstractClass(); + $stream->expects($this->once()) + ->method('isReadable') + ->will($this->returnValue(false)); + $stream->expects($this->once()) + ->method('isWritable') + ->will($this->returnValue(false)); + StreamWrapper::getResource($stream); + } + + /** + * @expectedException \PHPUnit_Framework_Error_Warning + */ + public function testReturnsFalseWhenStreamDoesNotExist() + { + fopen('guzzle://foo', 'r'); + } + + public function testCanOpenReadonlyStream() + { + $stream = $this->getMockBuilder('Psr\Http\Message\StreamInterface') + ->setMethods(array('isReadable', 'isWritable')) + ->getMockForAbstractClass(); + $stream->expects($this->once()) + ->method('isReadable') + ->will($this->returnValue(false)); + $stream->expects($this->once()) + ->method('isWritable') + ->will($this->returnValue(true)); + $r = StreamWrapper::getResource($stream); + $this->assertInternalType('resource', $r); + fclose($r); + } +} diff --git a/deps/vendor/ringcentral/psr7/tests/UriTest.php b/deps/vendor/ringcentral/psr7/tests/UriTest.php new file mode 100644 index 000000000..b53c97eb4 --- /dev/null +++ b/deps/vendor/ringcentral/psr7/tests/UriTest.php @@ -0,0 +1,258 @@ +assertEquals( + 'https://michael:test@test.com/path/123?q=abc#test', + (string) $uri + ); + + $this->assertEquals('test', $uri->getFragment()); + $this->assertEquals('test.com', $uri->getHost()); + $this->assertEquals('/path/123', $uri->getPath()); + $this->assertEquals(null, $uri->getPort()); + $this->assertEquals('q=abc', $uri->getQuery()); + $this->assertEquals('https', $uri->getScheme()); + $this->assertEquals('michael:test', $uri->getUserInfo()); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Unable to parse URI + */ + public function testValidatesUriCanBeParsed() + { + // Due to 5.4.7 "Fixed host recognition when scheme is omitted and a leading component separator is present" this does not work in 5.3 + //new Uri('///'); + throw new \InvalidArgumentException('Unable to parse URI'); + } + + public function testCanTransformAndRetrievePartsIndividually() + { + $uri = new Uri(''); + $uri = $uri->withFragment('#test') + ->withHost('example.com') + ->withPath('path/123') + ->withPort(8080) + ->withQuery('?q=abc') + ->withScheme('http') + ->withUserInfo('user', 'pass'); + + // Test getters. + $this->assertEquals('user:pass@example.com:8080', $uri->getAuthority()); + $this->assertEquals('test', $uri->getFragment()); + $this->assertEquals('example.com', $uri->getHost()); + $this->assertEquals('path/123', $uri->getPath()); + $this->assertEquals(8080, $uri->getPort()); + $this->assertEquals('q=abc', $uri->getQuery()); + $this->assertEquals('http', $uri->getScheme()); + $this->assertEquals('user:pass', $uri->getUserInfo()); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testPortMustBeValid() + { + $uri = new Uri(''); + $uri->withPort(100000); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testPathMustBeValid() + { + $uri = new Uri(''); + $uri->withPath(array()); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testQueryMustBeValid() + { + $uri = new Uri(''); + $uri->withQuery(new \stdClass); + } + + public function testAllowsFalseyUrlParts() + { + $url = new Uri('http://a:1/0?0#0'); + $this->assertSame('a', $url->getHost()); + $this->assertEquals(1, $url->getPort()); + $this->assertSame('/0', $url->getPath()); + $this->assertEquals('0', (string) $url->getQuery()); + $this->assertSame('0', $url->getFragment()); + $this->assertEquals('http://a:1/0?0#0', (string) $url); + $url = new Uri(''); + $this->assertSame('', (string) $url); + $url = new Uri('0'); + $this->assertSame('0', (string) $url); + $url = new Uri('/'); + $this->assertSame('/', (string) $url); + } + + /** + * @dataProvider getResolveTestCases + */ + public function testResolvesUris($base, $rel, $expected) + { + $uri = new Uri($base); + $actual = Uri::resolve($uri, $rel); + $this->assertEquals($expected, (string) $actual); + } + + public function getResolveTestCases() + { + return array( + //[self::RFC3986_BASE, 'g:h', 'g:h'], + array(self::RFC3986_BASE, 'g', 'http://a/b/c/g'), + array(self::RFC3986_BASE, './g', 'http://a/b/c/g'), + array(self::RFC3986_BASE, 'g/', 'http://a/b/c/g/'), + array(self::RFC3986_BASE, '/g', 'http://a/g'), + // Due to 5.4.7 "Fixed host recognition when scheme is omitted and a leading component separator is present" this does not work in 5.3 + //array(self::RFC3986_BASE, '//g', 'http://g'), + array(self::RFC3986_BASE, '?y', 'http://a/b/c/d;p?y'), + array(self::RFC3986_BASE, 'g?y', 'http://a/b/c/g?y'), + array(self::RFC3986_BASE, '#s', 'http://a/b/c/d;p?q#s'), + array(self::RFC3986_BASE, 'g#s', 'http://a/b/c/g#s'), + array(self::RFC3986_BASE, 'g?y#s', 'http://a/b/c/g?y#s'), + array(self::RFC3986_BASE, ';x', 'http://a/b/c/;x'), + array(self::RFC3986_BASE, 'g;x', 'http://a/b/c/g;x'), + array(self::RFC3986_BASE, 'g;x?y#s', 'http://a/b/c/g;x?y#s'), + array(self::RFC3986_BASE, '', self::RFC3986_BASE), + array(self::RFC3986_BASE, '.', 'http://a/b/c/'), + array(self::RFC3986_BASE, './', 'http://a/b/c/'), + array(self::RFC3986_BASE, '..', 'http://a/b/'), + array(self::RFC3986_BASE, '../', 'http://a/b/'), + array(self::RFC3986_BASE, '../g', 'http://a/b/g'), + array(self::RFC3986_BASE, '../..', 'http://a/'), + array(self::RFC3986_BASE, '../../', 'http://a/'), + array(self::RFC3986_BASE, '../../g', 'http://a/g'), + array(self::RFC3986_BASE, '../../../g', 'http://a/g'), + array(self::RFC3986_BASE, '../../../../g', 'http://a/g'), + array(self::RFC3986_BASE, '/./g', 'http://a/g'), + array(self::RFC3986_BASE, '/../g', 'http://a/g'), + array(self::RFC3986_BASE, 'g.', 'http://a/b/c/g.'), + array(self::RFC3986_BASE, '.g', 'http://a/b/c/.g'), + array(self::RFC3986_BASE, 'g..', 'http://a/b/c/g..'), + array(self::RFC3986_BASE, '..g', 'http://a/b/c/..g'), + array(self::RFC3986_BASE, './../g', 'http://a/b/g'), + array(self::RFC3986_BASE, 'foo////g', 'http://a/b/c/foo////g'), + array(self::RFC3986_BASE, './g/.', 'http://a/b/c/g/'), + array(self::RFC3986_BASE, 'g/./h', 'http://a/b/c/g/h'), + array(self::RFC3986_BASE, 'g/../h', 'http://a/b/c/h'), + array(self::RFC3986_BASE, 'g;x=1/./y', 'http://a/b/c/g;x=1/y'), + array(self::RFC3986_BASE, 'g;x=1/../y', 'http://a/b/c/y'), + array('http://u@a/b/c/d;p?q', '.', 'http://u@a/b/c/'), + array('http://u:p@a/b/c/d;p?q', '.', 'http://u:p@a/b/c/'), + //[self::RFC3986_BASE, 'http:g', 'http:g'], + ); + } + + public function testAddAndRemoveQueryValues() + { + $uri = new Uri('http://foo.com/bar'); + $uri = Uri::withQueryValue($uri, 'a', 'b'); + $uri = Uri::withQueryValue($uri, 'c', 'd'); + $uri = Uri::withQueryValue($uri, 'e', null); + $this->assertEquals('a=b&c=d&e', $uri->getQuery()); + + $uri = Uri::withoutQueryValue($uri, 'c'); + $uri = Uri::withoutQueryValue($uri, 'e'); + $this->assertEquals('a=b', $uri->getQuery()); + $uri = Uri::withoutQueryValue($uri, 'a'); + $uri = Uri::withoutQueryValue($uri, 'a'); + $this->assertEquals('', $uri->getQuery()); + } + + public function testGetAuthorityReturnsCorrectPort() + { + // HTTPS non-standard port + $uri = new Uri('https://foo.co:99'); + $this->assertEquals('foo.co:99', $uri->getAuthority()); + + // HTTP non-standard port + $uri = new Uri('http://foo.co:99'); + $this->assertEquals('foo.co:99', $uri->getAuthority()); + + // No scheme + $uri = new Uri('foo.co:99'); + $this->assertEquals('foo.co:99', $uri->getAuthority()); + + // No host or port + $uri = new Uri('http:'); + $this->assertEquals('', $uri->getAuthority()); + + // No host or port + $uri = new Uri('http://foo.co'); + $this->assertEquals('foo.co', $uri->getAuthority()); + } + + public function pathTestProvider() + { + return array( + // Percent encode spaces. + array('http://foo.com/baz bar', 'http://foo.com/baz%20bar'), + // Don't encoding something that's already encoded. + array('http://foo.com/baz%20bar', 'http://foo.com/baz%20bar'), + // Percent encode invalid percent encodings + array('http://foo.com/baz%2-bar', 'http://foo.com/baz%252-bar'), + // Don't encode path segments + array('http://foo.com/baz/bar/bam?a', 'http://foo.com/baz/bar/bam?a'), + array('http://foo.com/baz+bar', 'http://foo.com/baz+bar'), + array('http://foo.com/baz:bar', 'http://foo.com/baz:bar'), + array('http://foo.com/baz@bar', 'http://foo.com/baz@bar'), + array('http://foo.com/baz(bar);bam/', 'http://foo.com/baz(bar);bam/'), + array('http://foo.com/a-zA-Z0-9.-_~!$&\'()*+,;=:@', 'http://foo.com/a-zA-Z0-9.-_~!$&\'()*+,;=:@'), + ); + } + + /** + * @dataProvider pathTestProvider + */ + public function testUriEncodesPathProperly($input, $output) + { + $uri = new Uri($input); + $this->assertEquals((string) $uri, $output); + } + + public function testDoesNotAddPortWhenNoPort() + { + // Due to 5.4.7 "Fixed host recognition when scheme is omitted and a leading component separator is present" this does not work in 5.3 + //$uri = new Uri('//bar'); + //$this->assertEquals('bar', (string) $uri); + //$uri = new Uri('//barx'); + //$this->assertEquals('barx', $uri->getHost()); + } + + public function testAllowsForRelativeUri() + { + $uri = new Uri(); + $uri = $uri->withPath('foo'); + $this->assertEquals('foo', $uri->getPath()); + $this->assertEquals('foo', (string) $uri); + } + + public function testAddsSlashForRelativeUriStringWithHost() + { + $uri = new Uri(); + $uri = $uri->withPath('foo')->withHost('bar.com'); + $this->assertEquals('foo', $uri->getPath()); + $this->assertEquals('bar.com/foo', (string) $uri); + } +} diff --git a/deps/vendor/ringcentral/psr7/tests/bootstrap.php b/deps/vendor/ringcentral/psr7/tests/bootstrap.php new file mode 100644 index 000000000..ea6a07914 --- /dev/null +++ b/deps/vendor/ringcentral/psr7/tests/bootstrap.php @@ -0,0 +1,13 @@ +terminal->getHeight()); @@ -778,7 +778,7 @@ public function find(string $name) * * @return Command[] */ - public function all(?string $namespace = null) + public function all(string $namespace = null) { $this->init(); @@ -1147,7 +1147,7 @@ private function getAbbreviationSuggestions(array $abbrevs): string * * @return string */ - public function extractNamespace(string $name, ?int $limit = null) + public function extractNamespace(string $name, int $limit = null) { $parts = explode(':', $name, -1); diff --git a/deps/vendor/symfony/console/CI/GithubActionReporter.php b/deps/vendor/symfony/console/CI/GithubActionReporter.php index 065717854..a15c1ff18 100644 --- a/deps/vendor/symfony/console/CI/GithubActionReporter.php +++ b/deps/vendor/symfony/console/CI/GithubActionReporter.php @@ -57,7 +57,7 @@ public static function isGithubActionEnvironment(): bool * * @see https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#setting-an-error-message */ - public function error(string $message, ?string $file = null, ?int $line = null, ?int $col = null): void + public function error(string $message, string $file = null, int $line = null, int $col = null): void { $this->log('error', $message, $file, $line, $col); } @@ -67,7 +67,7 @@ public function error(string $message, ?string $file = null, ?int $line = null, * * @see https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#setting-a-warning-message */ - public function warning(string $message, ?string $file = null, ?int $line = null, ?int $col = null): void + public function warning(string $message, string $file = null, int $line = null, int $col = null): void { $this->log('warning', $message, $file, $line, $col); } @@ -77,12 +77,12 @@ public function warning(string $message, ?string $file = null, ?int $line = null * * @see https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#setting-a-debug-message */ - public function debug(string $message, ?string $file = null, ?int $line = null, ?int $col = null): void + public function debug(string $message, string $file = null, int $line = null, int $col = null): void { $this->log('debug', $message, $file, $line, $col); } - private function log(string $type, string $message, ?string $file = null, ?int $line = null, ?int $col = null): void + private function log(string $type, string $message, string $file = null, int $line = null, int $col = null): void { // Some values must be encoded. $message = strtr($message, self::ESCAPED_DATA); diff --git a/deps/vendor/symfony/console/Command/Command.php b/deps/vendor/symfony/console/Command/Command.php index d18103670..e0593e17a 100644 --- a/deps/vendor/symfony/console/Command/Command.php +++ b/deps/vendor/symfony/console/Command/Command.php @@ -96,7 +96,7 @@ public static function getDefaultDescription(): ?string * * @throws LogicException When the command name is empty */ - public function __construct(?string $name = null) + public function __construct(string $name = null) { $this->definition = new InputDefinition(); @@ -132,7 +132,7 @@ public function ignoreValidationErrors() $this->ignoreValidationErrors = true; } - public function setApplication(?Application $application = null) + public function setApplication(Application $application = null) { $this->application = $application; if ($application) { @@ -429,11 +429,11 @@ public function getNativeDefinition() * @param int|null $mode The argument mode: InputArgument::REQUIRED or InputArgument::OPTIONAL * @param mixed $default The default value (for InputArgument::OPTIONAL mode only) * - * @return $this - * * @throws InvalidArgumentException When argument mode is not valid + * + * @return $this */ - public function addArgument(string $name, ?int $mode = null, string $description = '', $default = null) + public function addArgument(string $name, int $mode = null, string $description = '', $default = null) { $this->definition->addArgument(new InputArgument($name, $mode, $description, $default)); if (null !== $this->fullDefinition) { @@ -450,11 +450,11 @@ public function addArgument(string $name, ?int $mode = null, string $description * @param int|null $mode The option mode: One of the InputOption::VALUE_* constants * @param mixed $default The default value (must be null for InputOption::VALUE_NONE) * - * @return $this - * * @throws InvalidArgumentException If option mode is invalid or incompatible + * + * @return $this */ - public function addOption(string $name, $shortcut = null, ?int $mode = null, string $description = '', $default = null) + public function addOption(string $name, $shortcut = null, int $mode = null, string $description = '', $default = null) { $this->definition->addOption(new InputOption($name, $shortcut, $mode, $description, $default)); if (null !== $this->fullDefinition) { diff --git a/deps/vendor/symfony/console/Command/CompleteCommand.php b/deps/vendor/symfony/console/Command/CompleteCommand.php index 0e35143c3..11ada4e44 100644 --- a/deps/vendor/symfony/console/Command/CompleteCommand.php +++ b/deps/vendor/symfony/console/Command/CompleteCommand.php @@ -155,10 +155,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int throw $e; } - return 2; + return self::FAILURE; } - return 0; + return self::SUCCESS; } private function createCompletionInput(InputInterface $input): CompletionInput diff --git a/deps/vendor/symfony/console/Command/DumpCompletionCommand.php b/deps/vendor/symfony/console/Command/DumpCompletionCommand.php index eaf22be1a..518d606a0 100644 --- a/deps/vendor/symfony/console/Command/DumpCompletionCommand.php +++ b/deps/vendor/symfony/console/Command/DumpCompletionCommand.php @@ -85,7 +85,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int if ($input->getOption('debug')) { $this->tailDebugLog($commandName, $output); - return 0; + return self::SUCCESS; } $shell = $input->getArgument('shell') ?? self::guessShell(); @@ -102,12 +102,12 @@ protected function execute(InputInterface $input, OutputInterface $output): int $output->writeln(sprintf('Shell not detected, Symfony shell completion only supports "%s").', implode('", "', $supportedShells))); } - return 2; + return self::INVALID; } $output->write(str_replace(['{{ COMMAND_NAME }}', '{{ VERSION }}'], [$commandName, $this->getApplication()->getVersion()], file_get_contents($completionFile))); - return 0; + return self::SUCCESS; } private static function guessShell(): string @@ -132,14 +132,8 @@ private function tailDebugLog(string $commandName, OutputInterface $output): voi */ private function getSupportedShells(): array { - $shells = []; - - foreach (new \DirectoryIterator(__DIR__.'/../Resources/') as $file) { - if (str_starts_with($file->getBasename(), 'completion.') && $file->isFile()) { - $shells[] = $file->getExtension(); - } - } - - return $shells; + return array_map(function ($f) { + return pathinfo($f, \PATHINFO_EXTENSION); + }, glob(__DIR__.'/../Resources/completion.*')); } } diff --git a/deps/vendor/symfony/console/Command/LazyCommand.php b/deps/vendor/symfony/console/Command/LazyCommand.php index 302a0809e..e576ad03f 100644 --- a/deps/vendor/symfony/console/Command/LazyCommand.php +++ b/deps/vendor/symfony/console/Command/LazyCommand.php @@ -43,7 +43,7 @@ public function ignoreValidationErrors(): void $this->getCommand()->ignoreValidationErrors(); } - public function setApplication(?Application $application = null): void + public function setApplication(Application $application = null): void { if ($this->command instanceof parent) { $this->command->setApplication($application); @@ -117,7 +117,7 @@ public function getNativeDefinition(): InputDefinition /** * @return $this */ - public function addArgument(string $name, ?int $mode = null, string $description = '', $default = null): self + public function addArgument(string $name, int $mode = null, string $description = '', $default = null): self { $this->getCommand()->addArgument($name, $mode, $description, $default); @@ -127,7 +127,7 @@ public function addArgument(string $name, ?int $mode = null, string $description /** * @return $this */ - public function addOption(string $name, $shortcut = null, ?int $mode = null, string $description = '', $default = null): self + public function addOption(string $name, $shortcut = null, int $mode = null, string $description = '', $default = null): self { $this->getCommand()->addOption($name, $shortcut, $mode, $description, $default); diff --git a/deps/vendor/symfony/console/Command/LockableTrait.php b/deps/vendor/symfony/console/Command/LockableTrait.php index d21edc2c0..b1856dca7 100644 --- a/deps/vendor/symfony/console/Command/LockableTrait.php +++ b/deps/vendor/symfony/console/Command/LockableTrait.php @@ -30,7 +30,7 @@ trait LockableTrait /** * Locks a command. */ - private function lock(?string $name = null, bool $blocking = false): bool + private function lock(string $name = null, bool $blocking = false): bool { if (!class_exists(SemaphoreStore::class)) { throw new LogicException('To enable the locking feature you must install the symfony/lock component.'); diff --git a/deps/vendor/symfony/console/Completion/CompletionInput.php b/deps/vendor/symfony/console/Completion/CompletionInput.php index 2f631bcd8..368b94507 100644 --- a/deps/vendor/symfony/console/Completion/CompletionInput.php +++ b/deps/vendor/symfony/console/Completion/CompletionInput.php @@ -53,7 +53,7 @@ public static function fromString(string $inputStr, int $currentIndex): self * Create an input based on an COMP_WORDS token list. * * @param string[] $tokens the set of split tokens (e.g. COMP_WORDS or argv) - * @param int $currentIndex the index of the cursor (e.g. COMP_CWORD) + * @param $currentIndex the index of the cursor (e.g. COMP_CWORD) */ public static function fromTokens(array $tokens, int $currentIndex): self { diff --git a/deps/vendor/symfony/console/Descriptor/ApplicationDescription.php b/deps/vendor/symfony/console/Descriptor/ApplicationDescription.php index eb11b4f91..2a3acc99b 100644 --- a/deps/vendor/symfony/console/Descriptor/ApplicationDescription.php +++ b/deps/vendor/symfony/console/Descriptor/ApplicationDescription.php @@ -43,7 +43,7 @@ class ApplicationDescription */ private $aliases; - public function __construct(Application $application, ?string $namespace = null, bool $showHidden = false) + public function __construct(Application $application, string $namespace = null, bool $showHidden = false) { $this->application = $application; $this->namespace = $namespace; diff --git a/deps/vendor/symfony/console/Descriptor/XmlDescriptor.php b/deps/vendor/symfony/console/Descriptor/XmlDescriptor.php index f17e5f1f2..4f7cd8b3e 100644 --- a/deps/vendor/symfony/console/Descriptor/XmlDescriptor.php +++ b/deps/vendor/symfony/console/Descriptor/XmlDescriptor.php @@ -79,7 +79,7 @@ public function getCommandDocument(Command $command, bool $short = false): \DOMD return $dom; } - public function getApplicationDocument(Application $application, ?string $namespace = null, bool $short = false): \DOMDocument + public function getApplicationDocument(Application $application, string $namespace = null, bool $short = false): \DOMDocument { $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->appendChild($rootXml = $dom->createElement('symfony')); diff --git a/deps/vendor/symfony/console/Event/ConsoleCommandEvent.php b/deps/vendor/symfony/console/Event/ConsoleCommandEvent.php index 1b4f9f9b1..08bd18fd1 100644 --- a/deps/vendor/symfony/console/Event/ConsoleCommandEvent.php +++ b/deps/vendor/symfony/console/Event/ConsoleCommandEvent.php @@ -12,10 +12,7 @@ namespace Symfony\Component\Console\Event; /** - * Allows to do things before the command is executed, like skipping the command or executing code before the command is - * going to be executed. - * - * Changing the input arguments will have no effect. + * Allows to do things before the command is executed, like skipping the command or changing the input. * * @author Fabien Potencier */ diff --git a/deps/vendor/symfony/console/Event/ConsoleErrorEvent.php b/deps/vendor/symfony/console/Event/ConsoleErrorEvent.php index d4c26493f..57d9b38ba 100644 --- a/deps/vendor/symfony/console/Event/ConsoleErrorEvent.php +++ b/deps/vendor/symfony/console/Event/ConsoleErrorEvent.php @@ -25,7 +25,7 @@ final class ConsoleErrorEvent extends ConsoleEvent private $error; private $exitCode; - public function __construct(InputInterface $input, OutputInterface $output, \Throwable $error, ?Command $command = null) + public function __construct(InputInterface $input, OutputInterface $output, \Throwable $error, Command $command = null) { parent::__construct($command, $input, $output); diff --git a/deps/vendor/symfony/console/EventListener/ErrorListener.php b/deps/vendor/symfony/console/EventListener/ErrorListener.php index e9c9e3ea4..897d9853f 100644 --- a/deps/vendor/symfony/console/EventListener/ErrorListener.php +++ b/deps/vendor/symfony/console/EventListener/ErrorListener.php @@ -26,7 +26,7 @@ class ErrorListener implements EventSubscriberInterface { private $logger; - public function __construct(?LoggerInterface $logger = null) + public function __construct(LoggerInterface $logger = null) { $this->logger = $logger; } diff --git a/deps/vendor/symfony/console/Exception/CommandNotFoundException.php b/deps/vendor/symfony/console/Exception/CommandNotFoundException.php index 81ec318ab..910ae1928 100644 --- a/deps/vendor/symfony/console/Exception/CommandNotFoundException.php +++ b/deps/vendor/symfony/console/Exception/CommandNotFoundException.php @@ -26,7 +26,7 @@ class CommandNotFoundException extends \InvalidArgumentException implements Exce * @param int $code Exception code * @param \Throwable|null $previous Previous exception used for the exception chaining */ - public function __construct(string $message, array $alternatives = [], int $code = 0, ?\Throwable $previous = null) + public function __construct(string $message, array $alternatives = [], int $code = 0, \Throwable $previous = null) { parent::__construct($message, $code, $previous); diff --git a/deps/vendor/symfony/console/Formatter/NullOutputFormatterStyle.php b/deps/vendor/symfony/console/Formatter/NullOutputFormatterStyle.php index afd3d0043..9232510f4 100644 --- a/deps/vendor/symfony/console/Formatter/NullOutputFormatterStyle.php +++ b/deps/vendor/symfony/console/Formatter/NullOutputFormatterStyle.php @@ -27,7 +27,7 @@ public function apply(string $text): string /** * {@inheritdoc} */ - public function setBackground(?string $color = null): void + public function setBackground(string $color = null): void { // do nothing } @@ -35,7 +35,7 @@ public function setBackground(?string $color = null): void /** * {@inheritdoc} */ - public function setForeground(?string $color = null): void + public function setForeground(string $color = null): void { // do nothing } diff --git a/deps/vendor/symfony/console/Formatter/OutputFormatter.php b/deps/vendor/symfony/console/Formatter/OutputFormatter.php index 4ec600244..603e5dca0 100644 --- a/deps/vendor/symfony/console/Formatter/OutputFormatter.php +++ b/deps/vendor/symfony/console/Formatter/OutputFormatter.php @@ -13,8 +13,6 @@ use Symfony\Component\Console\Exception\InvalidArgumentException; -use function Symfony\Component\String\b; - /** * Formatter class for console output. * @@ -260,7 +258,7 @@ private function applyCurrentStyle(string $text, string $current, int $width, in } preg_match('~(\\n)$~', $text, $matches); - $text = $prefix.$this->addLineBreaks($text, $width); + $text = $prefix.preg_replace('~([^\\n]{'.$width.'})\\ *~', "\$1\n", $text); $text = rtrim($text, "\n").($matches[1] ?? ''); if (!$currentLineLength && '' !== $current && "\n" !== substr($current, -1)) { @@ -284,11 +282,4 @@ private function applyCurrentStyle(string $text, string $current, int $width, in return implode("\n", $lines); } - - private function addLineBreaks(string $text, int $width): string - { - $encoding = mb_detect_encoding($text, null, true) ?: 'UTF-8'; - - return b($text)->toCodePointString($encoding)->wordwrap($width, "\n", true)->toByteString($encoding); - } } diff --git a/deps/vendor/symfony/console/Formatter/OutputFormatterStyle.php b/deps/vendor/symfony/console/Formatter/OutputFormatterStyle.php index d7ae66494..0fb36ac63 100644 --- a/deps/vendor/symfony/console/Formatter/OutputFormatterStyle.php +++ b/deps/vendor/symfony/console/Formatter/OutputFormatterStyle.php @@ -33,7 +33,7 @@ class OutputFormatterStyle implements OutputFormatterStyleInterface * @param string|null $foreground The style foreground color name * @param string|null $background The style background color name */ - public function __construct(?string $foreground = null, ?string $background = null, array $options = []) + public function __construct(string $foreground = null, string $background = null, array $options = []) { $this->color = new Color($this->foreground = $foreground ?: '', $this->background = $background ?: '', $this->options = $options); } @@ -41,7 +41,7 @@ public function __construct(?string $foreground = null, ?string $background = nu /** * {@inheritdoc} */ - public function setForeground(?string $color = null) + public function setForeground(string $color = null) { $this->color = new Color($this->foreground = $color ?: '', $this->background, $this->options); } @@ -49,7 +49,7 @@ public function setForeground(?string $color = null) /** * {@inheritdoc} */ - public function setBackground(?string $color = null) + public function setBackground(string $color = null) { $this->color = new Color($this->foreground, $this->background = $color ?: '', $this->options); } @@ -96,8 +96,7 @@ public function apply(string $text) { if (null === $this->handlesHrefGracefully) { $this->handlesHrefGracefully = 'JetBrains-JediTerm' !== getenv('TERMINAL_EMULATOR') - && (!getenv('KONSOLE_VERSION') || (int) getenv('KONSOLE_VERSION') > 201100) - && !isset($_SERVER['IDEA_INITIAL_DIRECTORY']); + && (!getenv('KONSOLE_VERSION') || (int) getenv('KONSOLE_VERSION') > 201100); } if (null !== $this->href && $this->handlesHrefGracefully) { diff --git a/deps/vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php b/deps/vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php index 89e4d2438..b30560d22 100644 --- a/deps/vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php +++ b/deps/vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php @@ -21,12 +21,12 @@ interface OutputFormatterStyleInterface /** * Sets style foreground color. */ - public function setForeground(?string $color = null); + public function setForeground(string $color = null); /** * Sets style background color. */ - public function setBackground(?string $color = null); + public function setBackground(string $color = null); /** * Sets some specific style option. diff --git a/deps/vendor/symfony/console/Formatter/OutputFormatterStyleStack.php b/deps/vendor/symfony/console/Formatter/OutputFormatterStyleStack.php index 1b9356301..fc48dc0e1 100644 --- a/deps/vendor/symfony/console/Formatter/OutputFormatterStyleStack.php +++ b/deps/vendor/symfony/console/Formatter/OutputFormatterStyleStack.php @@ -26,7 +26,7 @@ class OutputFormatterStyleStack implements ResetInterface private $emptyStyle; - public function __construct(?OutputFormatterStyleInterface $emptyStyle = null) + public function __construct(OutputFormatterStyleInterface $emptyStyle = null) { $this->emptyStyle = $emptyStyle ?? new OutputFormatterStyle(); $this->reset(); @@ -55,7 +55,7 @@ public function push(OutputFormatterStyleInterface $style) * * @throws InvalidArgumentException When style tags incorrectly nested */ - public function pop(?OutputFormatterStyleInterface $style = null) + public function pop(OutputFormatterStyleInterface $style = null) { if (empty($this->styles)) { return $this->emptyStyle; diff --git a/deps/vendor/symfony/console/Helper/Dumper.php b/deps/vendor/symfony/console/Helper/Dumper.php index 605e4d70b..b013b6c52 100644 --- a/deps/vendor/symfony/console/Helper/Dumper.php +++ b/deps/vendor/symfony/console/Helper/Dumper.php @@ -26,7 +26,7 @@ final class Dumper private $cloner; private $handler; - public function __construct(OutputInterface $output, ?CliDumper $dumper = null, ?ClonerInterface $cloner = null) + public function __construct(OutputInterface $output, CliDumper $dumper = null, ClonerInterface $cloner = null) { $this->output = $output; $this->dumper = $dumper; diff --git a/deps/vendor/symfony/console/Helper/Helper.php b/deps/vendor/symfony/console/Helper/Helper.php index 6b3f7f43a..c7d3e25d0 100644 --- a/deps/vendor/symfony/console/Helper/Helper.php +++ b/deps/vendor/symfony/console/Helper/Helper.php @@ -26,7 +26,7 @@ abstract class Helper implements HelperInterface /** * {@inheritdoc} */ - public function setHelperSet(?HelperSet $helperSet = null) + public function setHelperSet(HelperSet $helperSet = null) { $this->helperSet = $helperSet; } @@ -96,7 +96,7 @@ public static function length(?string $string): int * * @return string */ - public static function substr(?string $string, int $from, ?int $length = null) + public static function substr(?string $string, int $from, int $length = null) { $string ?? $string = ''; diff --git a/deps/vendor/symfony/console/Helper/HelperInterface.php b/deps/vendor/symfony/console/Helper/HelperInterface.php index 5bf4d6327..fc952b486 100644 --- a/deps/vendor/symfony/console/Helper/HelperInterface.php +++ b/deps/vendor/symfony/console/Helper/HelperInterface.php @@ -21,7 +21,7 @@ interface HelperInterface /** * Sets the helper set associated with this helper. */ - public function setHelperSet(?HelperSet $helperSet = null); + public function setHelperSet(HelperSet $helperSet = null); /** * Gets the helper set associated with this helper. diff --git a/deps/vendor/symfony/console/Helper/HelperSet.php b/deps/vendor/symfony/console/Helper/HelperSet.php index c870ab997..719762d24 100644 --- a/deps/vendor/symfony/console/Helper/HelperSet.php +++ b/deps/vendor/symfony/console/Helper/HelperSet.php @@ -37,7 +37,7 @@ public function __construct(array $helpers = []) } } - public function set(HelperInterface $helper, ?string $alias = null) + public function set(HelperInterface $helper, string $alias = null) { $this->helpers[$helper->getName()] = $helper; if (null !== $alias) { @@ -76,7 +76,7 @@ public function get(string $name) /** * @deprecated since Symfony 5.4 */ - public function setCommand(?Command $command = null) + public function setCommand(Command $command = null) { trigger_deprecation('symfony/console', '5.4', 'Method "%s()" is deprecated.', __METHOD__); diff --git a/deps/vendor/symfony/console/Helper/ProcessHelper.php b/deps/vendor/symfony/console/Helper/ProcessHelper.php index 86a250b27..4ea3d724d 100644 --- a/deps/vendor/symfony/console/Helper/ProcessHelper.php +++ b/deps/vendor/symfony/console/Helper/ProcessHelper.php @@ -32,7 +32,7 @@ class ProcessHelper extends Helper * @param callable|null $callback A PHP callback to run whenever there is some * output available on STDOUT or STDERR */ - public function run(OutputInterface $output, $cmd, ?string $error = null, ?callable $callback = null, int $verbosity = OutputInterface::VERBOSITY_VERY_VERBOSE): Process + public function run(OutputInterface $output, $cmd, string $error = null, callable $callback = null, int $verbosity = OutputInterface::VERBOSITY_VERY_VERBOSE): Process { if (!class_exists(Process::class)) { throw new \LogicException('The ProcessHelper cannot be run as the Process component is not installed. Try running "compose require symfony/process".'); @@ -98,7 +98,7 @@ public function run(OutputInterface $output, $cmd, ?string $error = null, ?calla * * @see run() */ - public function mustRun(OutputInterface $output, $cmd, ?string $error = null, ?callable $callback = null): Process + public function mustRun(OutputInterface $output, $cmd, string $error = null, callable $callback = null): Process { $process = $this->run($output, $cmd, $error, $callback); @@ -112,7 +112,7 @@ public function mustRun(OutputInterface $output, $cmd, ?string $error = null, ?c /** * Wraps a Process callback to add debugging output. */ - public function wrapCallback(OutputInterface $output, Process $process, ?callable $callback = null): callable + public function wrapCallback(OutputInterface $output, Process $process, callable $callback = null): callable { if ($output instanceof ConsoleOutputInterface) { $output = $output->getErrorOutput(); diff --git a/deps/vendor/symfony/console/Helper/ProgressBar.php b/deps/vendor/symfony/console/Helper/ProgressBar.php index 6250732eb..eb6aacb1a 100644 --- a/deps/vendor/symfony/console/Helper/ProgressBar.php +++ b/deps/vendor/symfony/console/Helper/ProgressBar.php @@ -169,12 +169,9 @@ public function setMessage(string $message, string $name = 'message') $this->messages[$name] = $message; } - /** - * @return string|null - */ public function getMessage(string $name = 'message') { - return $this->messages[$name] ?? null; + return $this->messages[$name]; } public function getStartTime(): int @@ -296,7 +293,7 @@ public function maxSecondsBetweenRedraws(float $seconds): void * * @param int|null $max Number of steps to complete the bar (0 if indeterminate), if null it will be inferred from $iterable */ - public function iterate(iterable $iterable, ?int $max = null): iterable + public function iterate(iterable $iterable, int $max = null): iterable { $this->start($max ?? (is_countable($iterable) ? \count($iterable) : 0)); @@ -314,7 +311,7 @@ public function iterate(iterable $iterable, ?int $max = null): iterable * * @param int|null $max Number of steps to complete the bar (0 if indeterminate), null to leave unchanged */ - public function start(?int $max = null) + public function start(int $max = null) { $this->startTime = time(); $this->step = 0; diff --git a/deps/vendor/symfony/console/Helper/ProgressIndicator.php b/deps/vendor/symfony/console/Helper/ProgressIndicator.php index 3cc0e1451..3482343fc 100644 --- a/deps/vendor/symfony/console/Helper/ProgressIndicator.php +++ b/deps/vendor/symfony/console/Helper/ProgressIndicator.php @@ -50,7 +50,7 @@ class ProgressIndicator * @param int $indicatorChangeInterval Change interval in milliseconds * @param array|null $indicatorValues Animated indicator characters */ - public function __construct(OutputInterface $output, ?string $format = null, int $indicatorChangeInterval = 100, ?array $indicatorValues = null) + public function __construct(OutputInterface $output, string $format = null, int $indicatorChangeInterval = 100, array $indicatorValues = null) { $this->output = $output; @@ -129,6 +129,8 @@ public function advance() /** * Finish the indicator with message. + * + * @param $message */ public function finish(string $message) { diff --git a/deps/vendor/symfony/console/Helper/QuestionHelper.php b/deps/vendor/symfony/console/Helper/QuestionHelper.php index 7b9de9229..10602038c 100644 --- a/deps/vendor/symfony/console/Helper/QuestionHelper.php +++ b/deps/vendor/symfony/console/Helper/QuestionHelper.php @@ -128,18 +128,7 @@ private function doAsk(OutputInterface $output, Question $question) } if (false === $ret) { - $isBlocked = stream_get_meta_data($inputStream)['blocked'] ?? true; - - if (!$isBlocked) { - stream_set_blocking($inputStream, true); - } - $ret = $this->readInput($inputStream, $question); - - if (!$isBlocked) { - stream_set_blocking($inputStream, false); - } - if (false === $ret) { throw new MissingInputException('Aborted.'); } @@ -503,7 +492,21 @@ private function isInteractiveInput($inputStream): bool return self::$stdinIsInteractive; } - return self::$stdinIsInteractive = @stream_isatty(fopen('php://stdin', 'r')); + if (\function_exists('stream_isatty')) { + return self::$stdinIsInteractive = @stream_isatty(fopen('php://stdin', 'r')); + } + + if (\function_exists('posix_isatty')) { + return self::$stdinIsInteractive = @posix_isatty(fopen('php://stdin', 'r')); + } + + if (!\function_exists('exec')) { + return self::$stdinIsInteractive = true; + } + + exec('stty 2> /dev/null', $output, $status); + + return self::$stdinIsInteractive = 1 !== $status; } /** diff --git a/deps/vendor/symfony/console/Helper/Table.php b/deps/vendor/symfony/console/Helper/Table.php index 698f9693b..3f2d99145 100644 --- a/deps/vendor/symfony/console/Helper/Table.php +++ b/deps/vendor/symfony/console/Helper/Table.php @@ -451,7 +451,7 @@ public function render() * * +-----+-----------+-------+ */ - private function renderRowSeparator(int $type = self::SEPARATOR_MID, ?string $title = null, ?string $titleFormat = null) + private function renderRowSeparator(int $type = self::SEPARATOR_MID, string $title = null, string $titleFormat = null) { if (0 === $count = $this->numberOfColumns) { return; @@ -516,7 +516,7 @@ private function renderColumnSeparator(int $type = self::BORDER_OUTSIDE): string * * | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | */ - private function renderRow(array $row, string $cellFormat, ?string $firstCellFormat = null) + private function renderRow(array $row, string $cellFormat, string $firstCellFormat = null) { $rowContent = $this->renderColumnSeparator(self::BORDER_OUTSIDE); $columns = $this->getRowColumns($row); @@ -621,10 +621,9 @@ private function buildTableRows(array $rows): TableRows if (!strstr($cell ?? '', "\n")) { continue; } - $eol = str_contains($cell ?? '', "\r\n") ? "\r\n" : "\n"; - $escaped = implode($eol, array_map([OutputFormatter::class, 'escapeTrailingBackslash'], explode($eol, $cell))); + $escaped = implode("\n", array_map([OutputFormatter::class, 'escapeTrailingBackslash'], explode("\n", $cell))); $cell = $cell instanceof TableCell ? new TableCell($escaped, ['colspan' => $cell->getColspan()]) : $escaped; - $lines = explode($eol, str_replace($eol, ''.$eol, $cell)); + $lines = explode("\n", str_replace("\n", "\n", $cell)); foreach ($lines as $lineKey => $line) { if ($colspan > 1) { $line = new TableCell($line, ['colspan' => $colspan]); @@ -686,9 +685,8 @@ private function fillNextRows(array $rows, int $line): array $nbLines = $cell->getRowspan() - 1; $lines = [$cell]; if (strstr($cell, "\n")) { - $eol = str_contains($cell, "\r\n") ? "\r\n" : "\n"; - $lines = explode($eol, str_replace($eol, ''.$eol.'', $cell)); - $nbLines = \count($lines) > $nbLines ? substr_count($cell, $eol) : $nbLines; + $lines = explode("\n", str_replace("\n", "\n", $cell)); + $nbLines = \count($lines) > $nbLines ? substr_count($cell, "\n") : $nbLines; $rows[$line][$column] = new TableCell($lines[0], ['colspan' => $cell->getColspan(), 'style' => $cell->getStyle()]); unset($lines[0]); @@ -807,7 +805,7 @@ private function calculateColumnsWidth(iterable $groups) $textContent = Helper::removeDecoration($this->output->getFormatter(), $cell); $textLength = Helper::width($textContent); if ($textLength > 0) { - $contentColumns = mb_str_split($textContent, ceil($textLength / $cell->getColspan())); + $contentColumns = str_split($textContent, ceil($textLength / $cell->getColspan())); foreach ($contentColumns as $position => $content) { $row[$i + $position] = $content; } diff --git a/deps/vendor/symfony/console/Helper/TableStyle.php b/deps/vendor/symfony/console/Helper/TableStyle.php index 0643c79eb..dfc41e6a4 100644 --- a/deps/vendor/symfony/console/Helper/TableStyle.php +++ b/deps/vendor/symfony/console/Helper/TableStyle.php @@ -90,7 +90,7 @@ public function getPaddingChar() * * @return $this */ - public function setHorizontalBorderChars(string $outside, ?string $inside = null): self + public function setHorizontalBorderChars(string $outside, string $inside = null): self { $this->horizontalOutsideBorderChar = $outside; $this->horizontalInsideBorderChar = $inside ?? $outside; @@ -115,7 +115,7 @@ public function setHorizontalBorderChars(string $outside, ?string $inside = null * * @return $this */ - public function setVerticalBorderChars(string $outside, ?string $inside = null): self + public function setVerticalBorderChars(string $outside, string $inside = null): self { $this->verticalOutsideBorderChar = $outside; $this->verticalInsideBorderChar = $inside ?? $outside; @@ -169,7 +169,7 @@ public function getBorderChars(): array * * @return $this */ - public function setCrossingChars(string $cross, string $topLeft, string $topMid, string $topRight, string $midRight, string $bottomRight, string $bottomMid, string $bottomLeft, string $midLeft, ?string $topLeftBottom = null, ?string $topMidBottom = null, ?string $topRightBottom = null): self + public function setCrossingChars(string $cross, string $topLeft, string $topMid, string $topRight, string $midRight, string $bottomRight, string $bottomMid, string $bottomLeft, string $midLeft, string $topLeftBottom = null, string $topMidBottom = null, string $topRightBottom = null): self { $this->crossingChar = $cross; $this->crossingTopLeftChar = $topLeft; diff --git a/deps/vendor/symfony/console/Input/ArgvInput.php b/deps/vendor/symfony/console/Input/ArgvInput.php index 0c4b2d25b..675b9ef58 100644 --- a/deps/vendor/symfony/console/Input/ArgvInput.php +++ b/deps/vendor/symfony/console/Input/ArgvInput.php @@ -43,7 +43,7 @@ class ArgvInput extends Input private $tokens; private $parsed; - public function __construct(?array $argv = null, ?InputDefinition $definition = null) + public function __construct(array $argv = null, InputDefinition $definition = null) { $argv = $argv ?? $_SERVER['argv'] ?? []; diff --git a/deps/vendor/symfony/console/Input/ArrayInput.php b/deps/vendor/symfony/console/Input/ArrayInput.php index 21a517cfb..c65161484 100644 --- a/deps/vendor/symfony/console/Input/ArrayInput.php +++ b/deps/vendor/symfony/console/Input/ArrayInput.php @@ -27,7 +27,7 @@ class ArrayInput extends Input { private $parameters; - public function __construct(array $parameters, ?InputDefinition $definition = null) + public function __construct(array $parameters, InputDefinition $definition = null) { $this->parameters = $parameters; diff --git a/deps/vendor/symfony/console/Input/Input.php b/deps/vendor/symfony/console/Input/Input.php index 0faab2cf1..d37460ed3 100644 --- a/deps/vendor/symfony/console/Input/Input.php +++ b/deps/vendor/symfony/console/Input/Input.php @@ -33,7 +33,7 @@ abstract class Input implements InputInterface, StreamableInputInterface protected $arguments = []; protected $interactive = true; - public function __construct(?InputDefinition $definition = null) + public function __construct(InputDefinition $definition = null) { if (null === $definition) { $this->definition = new InputDefinition(); diff --git a/deps/vendor/symfony/console/Input/InputArgument.php b/deps/vendor/symfony/console/Input/InputArgument.php index 1a8bf44b7..ecfcdad58 100644 --- a/deps/vendor/symfony/console/Input/InputArgument.php +++ b/deps/vendor/symfony/console/Input/InputArgument.php @@ -32,13 +32,13 @@ class InputArgument /** * @param string $name The argument name - * @param int|null $mode The argument mode: a bit mask of self::REQUIRED, self::OPTIONAL and self::IS_ARRAY + * @param int|null $mode The argument mode: self::REQUIRED or self::OPTIONAL * @param string $description A description text * @param string|bool|int|float|array|null $default The default value (for self::OPTIONAL mode only) * * @throws InvalidArgumentException When argument mode is not valid */ - public function __construct(string $name, ?int $mode = null, string $description = '', $default = null) + public function __construct(string $name, int $mode = null, string $description = '', $default = null) { if (null === $mode) { $mode = self::OPTIONAL; diff --git a/deps/vendor/symfony/console/Input/InputOption.php b/deps/vendor/symfony/console/Input/InputOption.php index 99807f59e..2bec34fe1 100644 --- a/deps/vendor/symfony/console/Input/InputOption.php +++ b/deps/vendor/symfony/console/Input/InputOption.php @@ -59,7 +59,7 @@ class InputOption * * @throws InvalidArgumentException If option mode is invalid or incompatible */ - public function __construct(string $name, $shortcut = null, ?int $mode = null, string $description = '', $default = null) + public function __construct(string $name, $shortcut = null, int $mode = null, string $description = '', $default = null) { if (str_starts_with($name, '--')) { $name = substr($name, 2); @@ -69,7 +69,7 @@ public function __construct(string $name, $shortcut = null, ?int $mode = null, s throw new InvalidArgumentException('An option name cannot be empty.'); } - if ('' === $shortcut || [] === $shortcut || false === $shortcut) { + if (empty($shortcut)) { $shortcut = null; } @@ -78,10 +78,10 @@ public function __construct(string $name, $shortcut = null, ?int $mode = null, s $shortcut = implode('|', $shortcut); } $shortcuts = preg_split('{(\|)-?}', ltrim($shortcut, '-')); - $shortcuts = array_filter($shortcuts, 'strlen'); + $shortcuts = array_filter($shortcuts); $shortcut = implode('|', $shortcuts); - if ('' === $shortcut) { + if (empty($shortcut)) { throw new InvalidArgumentException('An option shortcut cannot be empty.'); } } diff --git a/deps/vendor/symfony/console/LICENSE b/deps/vendor/symfony/console/LICENSE index 0138f8f07..88bf75bb4 100644 --- a/deps/vendor/symfony/console/LICENSE +++ b/deps/vendor/symfony/console/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-present Fabien Potencier +Copyright (c) 2004-2022 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/deps/vendor/symfony/console/Output/ConsoleOutput.php b/deps/vendor/symfony/console/Output/ConsoleOutput.php index 560aeb581..f19f9ebf4 100644 --- a/deps/vendor/symfony/console/Output/ConsoleOutput.php +++ b/deps/vendor/symfony/console/Output/ConsoleOutput.php @@ -37,7 +37,7 @@ class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface * @param bool|null $decorated Whether to decorate messages (null for auto-guessing) * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter) */ - public function __construct(int $verbosity = self::VERBOSITY_NORMAL, ?bool $decorated = null, ?OutputFormatterInterface $formatter = null) + public function __construct(int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = null, OutputFormatterInterface $formatter = null) { parent::__construct($this->openOutputStream(), $verbosity, $decorated, $formatter); diff --git a/deps/vendor/symfony/console/Output/ConsoleSectionOutput.php b/deps/vendor/symfony/console/Output/ConsoleSectionOutput.php index 70d70c50b..8f1649758 100644 --- a/deps/vendor/symfony/console/Output/ConsoleSectionOutput.php +++ b/deps/vendor/symfony/console/Output/ConsoleSectionOutput.php @@ -43,7 +43,7 @@ public function __construct($stream, array &$sections, int $verbosity, bool $dec * * @param int $lines Number of lines to clear. If null, then the entire output of this section is cleared */ - public function clear(?int $lines = null) + public function clear(int $lines = null) { if (empty($this->content) || !$this->isDecorated()) { return; diff --git a/deps/vendor/symfony/console/Output/Output.php b/deps/vendor/symfony/console/Output/Output.php index 28c40bb3e..d7c5fb2d1 100644 --- a/deps/vendor/symfony/console/Output/Output.php +++ b/deps/vendor/symfony/console/Output/Output.php @@ -37,7 +37,7 @@ abstract class Output implements OutputInterface * @param bool $decorated Whether to decorate messages * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter) */ - public function __construct(?int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = false, ?OutputFormatterInterface $formatter = null) + public function __construct(?int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = false, OutputFormatterInterface $formatter = null) { $this->verbosity = $verbosity ?? self::VERBOSITY_NORMAL; $this->formatter = $formatter ?? new OutputFormatter(); diff --git a/deps/vendor/symfony/console/Output/StreamOutput.php b/deps/vendor/symfony/console/Output/StreamOutput.php index b53955269..7f5551827 100644 --- a/deps/vendor/symfony/console/Output/StreamOutput.php +++ b/deps/vendor/symfony/console/Output/StreamOutput.php @@ -39,7 +39,7 @@ class StreamOutput extends Output * * @throws InvalidArgumentException When first argument is not a real stream */ - public function __construct($stream, int $verbosity = self::VERBOSITY_NORMAL, ?bool $decorated = null, ?OutputFormatterInterface $formatter = null) + public function __construct($stream, int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = null, OutputFormatterInterface $formatter = null) { if (!\is_resource($stream) || 'stream' !== get_resource_type($stream)) { throw new InvalidArgumentException('The StreamOutput class needs a stream as its first argument.'); @@ -64,6 +64,9 @@ public function getStream() return $this->stream; } + /** + * {@inheritdoc} + */ protected function doWrite(string $message, bool $newline) { if ($newline) { @@ -91,33 +94,22 @@ protected function doWrite(string $message, bool $newline) protected function hasColorSupport() { // Follow https://no-color.org/ - if ('' !== (($_SERVER['NO_COLOR'] ?? getenv('NO_COLOR'))[0] ?? '')) { - return false; - } - - // Detect msysgit/mingw and assume this is a tty because detection - // does not work correctly, see https://github.com/composer/composer/issues/9690 - if (!@stream_isatty($this->stream) && !\in_array(strtoupper((string) getenv('MSYSTEM')), ['MINGW32', 'MINGW64'], true)) { + if (isset($_SERVER['NO_COLOR']) || false !== getenv('NO_COLOR')) { return false; } - if ('\\' === \DIRECTORY_SEPARATOR && @sapi_windows_vt100_support($this->stream)) { + if ('Hyper' === getenv('TERM_PROGRAM')) { return true; } - if ('Hyper' === getenv('TERM_PROGRAM') - || false !== getenv('COLORTERM') - || false !== getenv('ANSICON') - || 'ON' === getenv('ConEmuANSI') - ) { - return true; - } - - if ('dumb' === $term = (string) getenv('TERM')) { - return false; + if (\DIRECTORY_SEPARATOR === '\\') { + return (\function_exists('sapi_windows_vt100_support') + && @sapi_windows_vt100_support($this->stream)) + || false !== getenv('ANSICON') + || 'ON' === getenv('ConEmuANSI') + || 'xterm' === getenv('TERM'); } - // See https://github.com/chalk/supports-color/blob/d4f413efaf8da045c5ab440ed418ef02dbb28bf1/index.js#L157 - return preg_match('/^((screen|xterm|vt100|vt220|putty|rxvt|ansi|cygwin|linux).*)|(.*-256(color)?(-bce)?)$/', $term); + return stream_isatty($this->stream); } } diff --git a/deps/vendor/symfony/console/Output/TrimmedBufferOutput.php b/deps/vendor/symfony/console/Output/TrimmedBufferOutput.php index b08503b3a..3f4d375f4 100644 --- a/deps/vendor/symfony/console/Output/TrimmedBufferOutput.php +++ b/deps/vendor/symfony/console/Output/TrimmedBufferOutput.php @@ -24,7 +24,7 @@ class TrimmedBufferOutput extends Output private $maxLength; private $buffer = ''; - public function __construct(int $maxLength, ?int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = false, ?OutputFormatterInterface $formatter = null) + public function __construct(int $maxLength, ?int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = false, OutputFormatterInterface $formatter = null) { if ($maxLength <= 0) { throw new InvalidArgumentException(sprintf('"%s()" expects a strictly positive maxLength. Got %d.', __METHOD__, $maxLength)); diff --git a/deps/vendor/symfony/console/Question/Question.php b/deps/vendor/symfony/console/Question/Question.php index ba5744283..3a73f04b2 100644 --- a/deps/vendor/symfony/console/Question/Question.php +++ b/deps/vendor/symfony/console/Question/Question.php @@ -186,7 +186,7 @@ public function getAutocompleterCallback(): ?callable * * @return $this */ - public function setAutocompleterCallback(?callable $callback = null): self + public function setAutocompleterCallback(callable $callback = null): self { if ($this->hidden && null !== $callback) { throw new LogicException('A hidden question cannot use the autocompleter.'); @@ -202,7 +202,7 @@ public function setAutocompleterCallback(?callable $callback = null): self * * @return $this */ - public function setValidator(?callable $validator = null) + public function setValidator(callable $validator = null) { $this->validator = $validator; diff --git a/deps/vendor/symfony/console/Resources/completion.bash b/deps/vendor/symfony/console/Resources/completion.bash index bb44037b0..64b87ccf7 100644 --- a/deps/vendor/symfony/console/Resources/completion.bash +++ b/deps/vendor/symfony/console/Resources/completion.bash @@ -7,7 +7,7 @@ _sf_{{ COMMAND_NAME }}() { # Use newline as only separator to allow space in completion values - local IFS=$'\n' + IFS=$'\n' local sf_cmd="${COMP_WORDS[0]}" # for an alias, get the real script behind it diff --git a/deps/vendor/symfony/console/SingleCommandApplication.php b/deps/vendor/symfony/console/SingleCommandApplication.php index 774e5d8c4..e93c1821b 100644 --- a/deps/vendor/symfony/console/SingleCommandApplication.php +++ b/deps/vendor/symfony/console/SingleCommandApplication.php @@ -46,7 +46,7 @@ public function setAutoExit(bool $autoExit): self return $this; } - public function run(?InputInterface $input = null, ?OutputInterface $output = null): int + public function run(InputInterface $input = null, OutputInterface $output = null): int { if ($this->running) { return parent::run($input, $output); diff --git a/deps/vendor/symfony/console/Style/StyleInterface.php b/deps/vendor/symfony/console/Style/StyleInterface.php index 9f25a43f6..38d23b77e 100644 --- a/deps/vendor/symfony/console/Style/StyleInterface.php +++ b/deps/vendor/symfony/console/Style/StyleInterface.php @@ -85,14 +85,14 @@ public function table(array $headers, array $rows); * * @return mixed */ - public function ask(string $question, ?string $default = null, ?callable $validator = null); + public function ask(string $question, string $default = null, callable $validator = null); /** * Asks a question with the user input hidden. * * @return mixed */ - public function askHidden(string $question, ?callable $validator = null); + public function askHidden(string $question, callable $validator = null); /** * Asks for confirmation. diff --git a/deps/vendor/symfony/console/Style/SymfonyStyle.php b/deps/vendor/symfony/console/Style/SymfonyStyle.php index 00edf3882..e3c5ac8e7 100644 --- a/deps/vendor/symfony/console/Style/SymfonyStyle.php +++ b/deps/vendor/symfony/console/Style/SymfonyStyle.php @@ -61,7 +61,7 @@ public function __construct(InputInterface $input, OutputInterface $output) * * @param string|array $messages The message to write in the block */ - public function block($messages, ?string $type = null, ?string $style = null, string $prefix = ' ', bool $padding = false, bool $escape = true) + public function block($messages, string $type = null, string $style = null, string $prefix = ' ', bool $padding = false, bool $escape = true) { $messages = \is_array($messages) ? array_values($messages) : [$messages]; @@ -250,7 +250,7 @@ public function definitionList(...$list) /** * {@inheritdoc} */ - public function ask(string $question, ?string $default = null, ?callable $validator = null) + public function ask(string $question, string $default = null, callable $validator = null) { $question = new Question($question, $default); $question->setValidator($validator); @@ -261,7 +261,7 @@ public function ask(string $question, ?string $default = null, ?callable $valida /** * {@inheritdoc} */ - public function askHidden(string $question, ?callable $validator = null) + public function askHidden(string $question, callable $validator = null) { $question = new Question($question); @@ -338,7 +338,7 @@ public function createProgressBar(int $max = 0) /** * @see ProgressBar::iterate() */ - public function progressIterate(iterable $iterable, ?int $max = null): iterable + public function progressIterate(iterable $iterable, int $max = null): iterable { yield from $this->createProgressBar()->iterate($iterable, $max); @@ -463,7 +463,7 @@ private function writeBuffer(string $message, bool $newLine, int $type): void $this->bufferedOutput->write($message, $newLine, $type); } - private function createBlock(iterable $messages, ?string $type = null, ?string $style = null, string $prefix = ' ', bool $padding = false, bool $escape = false): array + private function createBlock(iterable $messages, string $type = null, string $style = null, string $prefix = ' ', bool $padding = false, bool $escape = false): array { $indentLength = 0; $prefixLength = Helper::width(Helper::removeDecoration($this->getFormatter(), $prefix)); diff --git a/deps/vendor/symfony/console/Terminal.php b/deps/vendor/symfony/console/Terminal.php index 948ced4ad..08c53535b 100644 --- a/deps/vendor/symfony/console/Terminal.php +++ b/deps/vendor/symfony/console/Terminal.php @@ -64,19 +64,20 @@ public static function hasSttyAvailable(): bool return self::$stty; } - // skip check if shell_exec function is disabled - if (!\function_exists('shell_exec')) { + // skip check if exec function is disabled + if (!\function_exists('exec')) { return false; } - return self::$stty = (bool) shell_exec('stty 2> '.('\\' === \DIRECTORY_SEPARATOR ? 'NUL' : '/dev/null')); + exec('stty 2>&1', $output, $exitcode); + + return self::$stty = 0 === $exitcode; } private static function initDimensions() { if ('\\' === \DIRECTORY_SEPARATOR) { - $ansicon = getenv('ANSICON'); - if (false !== $ansicon && preg_match('/^(\d+)x(\d+)(?: \((\d+)x(\d+)\))?$/', trim($ansicon), $matches)) { + 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]; @@ -156,9 +157,8 @@ private static function readFromProcess(string $command): ?string 2 => ['pipe', 'w'], ]; - $cp = \function_exists('sapi_windows_cp_set') ? sapi_windows_cp_get() : 0; - - if (!$process = proc_open($command, $descriptorspec, $pipes, null, null, ['suppress_errors' => true])) { + $process = proc_open($command, $descriptorspec, $pipes, null, null, ['suppress_errors' => true]); + if (!\is_resource($process)) { return null; } @@ -167,10 +167,6 @@ private static function readFromProcess(string $command): ?string fclose($pipes[2]); proc_close($process); - if ($cp) { - sapi_windows_cp_set($cp); - } - return $info; } } diff --git a/deps/vendor/symfony/console/Tester/TesterTrait.php b/deps/vendor/symfony/console/Tester/TesterTrait.php index f454bbf9d..40bc58177 100644 --- a/deps/vendor/symfony/console/Tester/TesterTrait.php +++ b/deps/vendor/symfony/console/Tester/TesterTrait.php @@ -35,9 +35,9 @@ trait TesterTrait /** * Gets the display returned by the last execution of the command or application. * - * @return string - * * @throws \RuntimeException If it's called before the execute method + * + * @return string */ public function getDisplay(bool $normalize = false) { @@ -103,9 +103,9 @@ public function getOutput() /** * Gets the status code returned by the last execution of the command or application. * - * @return int - * * @throws \RuntimeException If it's called before the execute method + * + * @return int */ public function getStatusCode() { diff --git a/deps/vendor/symfony/console/composer.json b/deps/vendor/symfony/console/composer.json index 4fa4964a1..9a565068c 100644 --- a/deps/vendor/symfony/console/composer.json +++ b/deps/vendor/symfony/console/composer.json @@ -2,7 +2,7 @@ "name": "symfony/console", "type": "library", "description": "Eases the creation of beautiful and testable command line interfaces", - "keywords": ["console", "cli", "command-line", "terminal"], + "keywords": ["console", "cli", "command line", "terminal"], "homepage": "https://symfony.com", "license": "MIT", "authors": [ diff --git a/deps/vendor/symfony/deprecation-contracts/.gitignore b/deps/vendor/symfony/deprecation-contracts/.gitignore new file mode 100644 index 000000000..c49a5d8df --- /dev/null +++ b/deps/vendor/symfony/deprecation-contracts/.gitignore @@ -0,0 +1,3 @@ +vendor/ +composer.lock +phpunit.xml diff --git a/deps/vendor/symfony/deprecation-contracts/LICENSE b/deps/vendor/symfony/deprecation-contracts/LICENSE index 0ed3a2465..ad85e1737 100644 --- a/deps/vendor/symfony/deprecation-contracts/LICENSE +++ b/deps/vendor/symfony/deprecation-contracts/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2020-present Fabien Potencier +Copyright (c) 2020-2021 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/deps/vendor/symfony/deprecation-contracts/README.md b/deps/vendor/symfony/deprecation-contracts/README.md index 9814864c0..4957933a6 100644 --- a/deps/vendor/symfony/deprecation-contracts/README.md +++ b/deps/vendor/symfony/deprecation-contracts/README.md @@ -22,5 +22,5 @@ trigger_deprecation('symfony/blockchain', '8.9', 'Using "%s" is deprecated, use This will generate the following message: `Since symfony/blockchain 8.9: Using "bitcoin" is deprecated, use "fabcoin" instead.` -While not recommended, the deprecation notices can be completely ignored by declaring an empty +While not necessarily recommended, the deprecation notices can be completely ignored by declaring an empty `function trigger_deprecation() {}` in your application. diff --git a/deps/vendor/symfony/deprecation-contracts/composer.json b/deps/vendor/symfony/deprecation-contracts/composer.json index ceb6c0796..cc7cc1237 100644 --- a/deps/vendor/symfony/deprecation-contracts/composer.json +++ b/deps/vendor/symfony/deprecation-contracts/composer.json @@ -15,7 +15,7 @@ } ], "require": { - "php": ">=8.1" + "php": ">=7.1" }, "autoload": { "files": [ @@ -25,7 +25,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-main": "3.5-dev" + "dev-main": "2.5-dev" }, "thanks": { "name": "symfony/contracts", diff --git a/deps/vendor/symfony/deprecation-contracts/function.php b/deps/vendor/symfony/deprecation-contracts/function.php index 2d56512ba..d4371504a 100644 --- a/deps/vendor/symfony/deprecation-contracts/function.php +++ b/deps/vendor/symfony/deprecation-contracts/function.php @@ -20,7 +20,7 @@ * * @author Nicolas Grekas */ - function trigger_deprecation(string $package, string $version, string $message, mixed ...$args): void + function trigger_deprecation(string $package, string $version, string $message, ...$args): void { @trigger_error(($package || $version ? "Since $package $version: " : '').($args ? vsprintf($message, $args) : $message), \E_USER_DEPRECATED); } diff --git a/deps/vendor/symfony/polyfill-ctype/LICENSE b/deps/vendor/symfony/polyfill-ctype/LICENSE index 7536caeae..3f853aaf3 100644 --- a/deps/vendor/symfony/polyfill-ctype/LICENSE +++ b/deps/vendor/symfony/polyfill-ctype/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2018-present Fabien Potencier +Copyright (c) 2018-2019 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/deps/vendor/symfony/polyfill-ctype/README.md b/deps/vendor/symfony/polyfill-ctype/README.md index b144d03c3..8add1ab00 100644 --- a/deps/vendor/symfony/polyfill-ctype/README.md +++ b/deps/vendor/symfony/polyfill-ctype/README.md @@ -4,7 +4,7 @@ Symfony Polyfill / Ctype This component provides `ctype_*` functions to users who run php versions without the ctype extension. More information can be found in the -[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md). +[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md). License ======= diff --git a/deps/vendor/symfony/polyfill-ctype/composer.json b/deps/vendor/symfony/polyfill-ctype/composer.json index 131ca7adb..ccb8e5703 100644 --- a/deps/vendor/symfony/polyfill-ctype/composer.json +++ b/deps/vendor/symfony/polyfill-ctype/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=7.2" + "php": ">=7.1" }, "provide": { "ext-ctype": "*" @@ -30,6 +30,9 @@ }, "minimum-stability": "dev", "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" diff --git a/deps/vendor/symfony/polyfill-intl-grapheme/Grapheme.php b/deps/vendor/symfony/polyfill-intl-grapheme/Grapheme.php index 5373f1685..6f7c0c78d 100644 --- a/deps/vendor/symfony/polyfill-intl-grapheme/Grapheme.php +++ b/deps/vendor/symfony/polyfill-intl-grapheme/Grapheme.php @@ -48,7 +48,7 @@ public static function grapheme_extract($s, $size, $type = \GRAPHEME_EXTR_COUNT, $start = \strlen($s) + $start; } - if (!\is_scalar($s)) { + if (!is_scalar($s)) { $hasError = false; set_error_handler(function () use (&$hasError) { $hasError = true; }); $next = substr($s, $start); diff --git a/deps/vendor/symfony/polyfill-intl-grapheme/LICENSE b/deps/vendor/symfony/polyfill-intl-grapheme/LICENSE index 6e3afce69..4cd8bdd30 100644 --- a/deps/vendor/symfony/polyfill-intl-grapheme/LICENSE +++ b/deps/vendor/symfony/polyfill-intl-grapheme/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2015-present Fabien Potencier +Copyright (c) 2015-2019 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/deps/vendor/symfony/polyfill-intl-grapheme/README.md b/deps/vendor/symfony/polyfill-intl-grapheme/README.md index f55d92c5c..77523ea27 100644 --- a/deps/vendor/symfony/polyfill-intl-grapheme/README.md +++ b/deps/vendor/symfony/polyfill-intl-grapheme/README.md @@ -23,7 +23,7 @@ This component provides a partial, native PHP implementation of the - [`grapheme_substr`](https://php.net/grapheme_substr): Return part of a string More information can be found in the -[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md). +[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md). License ======= diff --git a/deps/vendor/symfony/polyfill-intl-grapheme/composer.json b/deps/vendor/symfony/polyfill-intl-grapheme/composer.json index 0eea417d7..02c98ee30 100644 --- a/deps/vendor/symfony/polyfill-intl-grapheme/composer.json +++ b/deps/vendor/symfony/polyfill-intl-grapheme/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=7.2" + "php": ">=7.1" }, "autoload": { "psr-4": { "Symfony\\Polyfill\\Intl\\Grapheme\\": "" }, @@ -27,6 +27,9 @@ }, "minimum-stability": "dev", "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" diff --git a/deps/vendor/symfony/polyfill-intl-normalizer/LICENSE b/deps/vendor/symfony/polyfill-intl-normalizer/LICENSE index 6e3afce69..4cd8bdd30 100644 --- a/deps/vendor/symfony/polyfill-intl-normalizer/LICENSE +++ b/deps/vendor/symfony/polyfill-intl-normalizer/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2015-present Fabien Potencier +Copyright (c) 2015-2019 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/deps/vendor/symfony/polyfill-intl-normalizer/Normalizer.php b/deps/vendor/symfony/polyfill-intl-normalizer/Normalizer.php index 81704ab37..4443c2322 100644 --- a/deps/vendor/symfony/polyfill-intl-normalizer/Normalizer.php +++ b/deps/vendor/symfony/polyfill-intl-normalizer/Normalizer.php @@ -90,7 +90,7 @@ public static function normalize(string $s, int $form = self::FORM_C) self::$cC = self::getData('combiningClass'); } - if (null !== $mbEncoding = (2 /* MB_OVERLOAD_STRING */ & (int) \ini_get('mbstring.func_overload')) ? mb_internal_encoding() : null) { + if (null !== $mbEncoding = (2 /* MB_OVERLOAD_STRING */ & (int) ini_get('mbstring.func_overload')) ? mb_internal_encoding() : null) { mb_internal_encoding('8bit'); } diff --git a/deps/vendor/symfony/polyfill-intl-normalizer/README.md b/deps/vendor/symfony/polyfill-intl-normalizer/README.md index b9b762e85..15060c5f1 100644 --- a/deps/vendor/symfony/polyfill-intl-normalizer/README.md +++ b/deps/vendor/symfony/polyfill-intl-normalizer/README.md @@ -6,7 +6,7 @@ This component provides a fallback implementation for the by the [Intl](https://php.net/intl) extension. More information can be found in the -[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md). +[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md). License ======= diff --git a/deps/vendor/symfony/polyfill-intl-normalizer/composer.json b/deps/vendor/symfony/polyfill-intl-normalizer/composer.json index 9bd04e887..393edf701 100644 --- a/deps/vendor/symfony/polyfill-intl-normalizer/composer.json +++ b/deps/vendor/symfony/polyfill-intl-normalizer/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=7.2" + "php": ">=7.1" }, "autoload": { "psr-4": { "Symfony\\Polyfill\\Intl\\Normalizer\\": "" }, @@ -28,6 +28,9 @@ }, "minimum-stability": "dev", "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" diff --git a/deps/vendor/symfony/polyfill-mbstring/LICENSE b/deps/vendor/symfony/polyfill-mbstring/LICENSE index 6e3afce69..4cd8bdd30 100644 --- a/deps/vendor/symfony/polyfill-mbstring/LICENSE +++ b/deps/vendor/symfony/polyfill-mbstring/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2015-present Fabien Potencier +Copyright (c) 2015-2019 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/deps/vendor/symfony/polyfill-mbstring/Mbstring.php b/deps/vendor/symfony/polyfill-mbstring/Mbstring.php index 3d45c9d9a..b65c54a6b 100644 --- a/deps/vendor/symfony/polyfill-mbstring/Mbstring.php +++ b/deps/vendor/symfony/polyfill-mbstring/Mbstring.php @@ -48,11 +48,6 @@ * - mb_strstr - Finds first occurrence of a string within another * - mb_strwidth - Return width of string * - mb_substr_count - Count the number of substring occurrences - * - mb_ucfirst - Make a string's first character uppercase - * - mb_lcfirst - Make a string's first character lowercase - * - mb_trim - Strip whitespace (or other characters) from the beginning and end of a string - * - mb_ltrim - Strip whitespace (or other characters) from the beginning of a string - * - mb_rtrim - Strip whitespace (or other characters) from the end of a string * * Not implemented: * - mb_convert_kana - Convert "kana" one from another ("zen-kaku", "han-kaku" and more) @@ -74,7 +69,7 @@ final class Mbstring { public const MB_CASE_FOLD = \PHP_INT_MAX; - private const SIMPLE_CASE_FOLD = [ + private const CASE_FOLD = [ ['µ', 'ſ', "\xCD\x85", 'ς', "\xCF\x90", "\xCF\x91", "\xCF\x95", "\xCF\x96", "\xCF\xB0", "\xCF\xB1", "\xCF\xB5", "\xE1\xBA\x9B", "\xE1\xBE\xBE"], ['μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', "\xE1\xB9\xA1", 'ι'], ]; @@ -85,16 +80,7 @@ final class Mbstring public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null) { - if (\is_array($s)) { - $r = []; - foreach ($s as $str) { - $r[] = self::mb_convert_encoding($str, $toEncoding, $fromEncoding); - } - - return $r; - } - - if (\is_array($fromEncoding) || (null !== $fromEncoding && false !== strpos($fromEncoding, ','))) { + if (\is_array($fromEncoding) || ($fromEncoding !== null && false !== strpos($fromEncoding, ','))) { $fromEncoding = self::mb_detect_encoding($s, $fromEncoding); } else { $fromEncoding = self::getEncoding($fromEncoding); @@ -116,7 +102,7 @@ public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null $fromEncoding = 'Windows-1252'; } if ('UTF-8' !== $fromEncoding) { - $s = iconv($fromEncoding, 'UTF-8//IGNORE', $s); + $s = \iconv($fromEncoding, 'UTF-8//IGNORE', $s); } return preg_replace_callback('/[\x80-\xFF]+/', [__CLASS__, 'html_encoding_callback'], $s); @@ -127,7 +113,7 @@ public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null $fromEncoding = 'UTF-8'; } - return iconv($fromEncoding, $toEncoding.'//IGNORE', $s); + return \iconv($fromEncoding, $toEncoding.'//IGNORE', $s); } public static function mb_convert_variables($toEncoding, $fromEncoding, &...$vars) @@ -144,7 +130,7 @@ public static function mb_convert_variables($toEncoding, $fromEncoding, &...$var public static function mb_decode_mimeheader($s) { - return iconv_mime_decode($s, 2, self::$internalEncoding); + return \iconv_mime_decode($s, 2, self::$internalEncoding); } public static function mb_encode_mimeheader($s, $charset = null, $transferEncoding = null, $linefeed = null, $indent = null) @@ -154,7 +140,7 @@ public static function mb_encode_mimeheader($s, $charset = null, $transferEncodi public static function mb_decode_numericentity($s, $convmap, $encoding = null) { - if (null !== $s && !\is_scalar($s) && !(\is_object($s) && method_exists($s, '__toString'))) { + if (null !== $s && !is_scalar($s) && !(\is_object($s) && method_exists($s, '__toString'))) { trigger_error('mb_decode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', \E_USER_WARNING); return null; @@ -164,7 +150,7 @@ public static function mb_decode_numericentity($s, $convmap, $encoding = null) return false; } - if (null !== $encoding && !\is_scalar($encoding)) { + if (null !== $encoding && !is_scalar($encoding)) { trigger_error('mb_decode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', \E_USER_WARNING); return ''; // Instead of null (cf. mb_encode_numericentity). @@ -180,10 +166,10 @@ public static function mb_decode_numericentity($s, $convmap, $encoding = null) if ('UTF-8' === $encoding) { $encoding = null; if (!preg_match('//u', $s)) { - $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s); + $s = @\iconv('UTF-8', 'UTF-8//IGNORE', $s); } } else { - $s = iconv($encoding, 'UTF-8//IGNORE', $s); + $s = \iconv($encoding, 'UTF-8//IGNORE', $s); } $cnt = floor(\count($convmap) / 4) * 4; @@ -209,12 +195,12 @@ public static function mb_decode_numericentity($s, $convmap, $encoding = null) return $s; } - return iconv('UTF-8', $encoding.'//IGNORE', $s); + return \iconv('UTF-8', $encoding.'//IGNORE', $s); } public static function mb_encode_numericentity($s, $convmap, $encoding = null, $is_hex = false) { - if (null !== $s && !\is_scalar($s) && !(\is_object($s) && method_exists($s, '__toString'))) { + if (null !== $s && !is_scalar($s) && !(\is_object($s) && method_exists($s, '__toString'))) { trigger_error('mb_encode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', \E_USER_WARNING); return null; @@ -224,13 +210,13 @@ public static function mb_encode_numericentity($s, $convmap, $encoding = null, $ return false; } - if (null !== $encoding && !\is_scalar($encoding)) { + if (null !== $encoding && !is_scalar($encoding)) { trigger_error('mb_encode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', \E_USER_WARNING); return null; // Instead of '' (cf. mb_decode_numericentity). } - if (null !== $is_hex && !\is_scalar($is_hex)) { + if (null !== $is_hex && !is_scalar($is_hex)) { trigger_error('mb_encode_numericentity() expects parameter 4 to be boolean, '.\gettype($s).' given', \E_USER_WARNING); return null; @@ -246,10 +232,10 @@ public static function mb_encode_numericentity($s, $convmap, $encoding = null, $ if ('UTF-8' === $encoding) { $encoding = null; if (!preg_match('//u', $s)) { - $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s); + $s = @\iconv('UTF-8', 'UTF-8//IGNORE', $s); } } else { - $s = iconv($encoding, 'UTF-8//IGNORE', $s); + $s = \iconv($encoding, 'UTF-8//IGNORE', $s); } static $ulenMask = ["\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4]; @@ -279,7 +265,7 @@ public static function mb_encode_numericentity($s, $convmap, $encoding = null, $ return $result; } - return iconv('UTF-8', $encoding.'//IGNORE', $result); + return \iconv('UTF-8', $encoding.'//IGNORE', $result); } public static function mb_convert_case($s, $mode, $encoding = null) @@ -294,10 +280,10 @@ public static function mb_convert_case($s, $mode, $encoding = null) if ('UTF-8' === $encoding) { $encoding = null; if (!preg_match('//u', $s)) { - $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s); + $s = @\iconv('UTF-8', 'UTF-8//IGNORE', $s); } } else { - $s = iconv($encoding, 'UTF-8//IGNORE', $s); + $s = \iconv($encoding, 'UTF-8//IGNORE', $s); } if (\MB_CASE_TITLE == $mode) { @@ -315,11 +301,7 @@ public static function mb_convert_case($s, $mode, $encoding = null) $map = $upper; } else { if (self::MB_CASE_FOLD === $mode) { - static $caseFolding = null; - if (null === $caseFolding) { - $caseFolding = self::getData('caseFolding'); - } - $s = strtr($s, $caseFolding); + $s = str_replace(self::CASE_FOLD[0], self::CASE_FOLD[1], $s); } static $lower = null; @@ -361,7 +343,7 @@ public static function mb_convert_case($s, $mode, $encoding = null) return $s; } - return iconv('UTF-8', $encoding.'//IGNORE', $s); + return \iconv('UTF-8', $encoding.'//IGNORE', $s); } public static function mb_internal_encoding($encoding = null) @@ -372,7 +354,7 @@ public static function mb_internal_encoding($encoding = null) $normalizedEncoding = self::getEncoding($encoding); - if ('UTF-8' === $normalizedEncoding || false !== @iconv($normalizedEncoding, $normalizedEncoding, ' ')) { + if ('UTF-8' === $normalizedEncoding || false !== @\iconv($normalizedEncoding, $normalizedEncoding, ' ')) { self::$internalEncoding = $normalizedEncoding; return true; @@ -431,20 +413,7 @@ public static function mb_check_encoding($var = null, $encoding = null) $encoding = self::$internalEncoding; } - if (!\is_array($var)) { - return self::mb_detect_encoding($var, [$encoding]) || false !== @iconv($encoding, $encoding, $var); - } - - foreach ($var as $key => $value) { - if (!self::mb_check_encoding($key, $encoding)) { - return false; - } - if (!self::mb_check_encoding($value, $encoding)) { - return false; - } - } - - return true; + return self::mb_detect_encoding($var, [$encoding]) || false !== @\iconv($encoding, $encoding, $var); } public static function mb_detect_encoding($str, $encodingList = null, $strict = false) @@ -519,7 +488,7 @@ public static function mb_strlen($s, $encoding = null) return \strlen($s); } - return @iconv_strlen($s, $encoding); + return @\iconv_strlen($s, $encoding); } public static function mb_strpos($haystack, $needle, $offset = 0, $encoding = null) @@ -540,7 +509,7 @@ public static function mb_strpos($haystack, $needle, $offset = 0, $encoding = nu return 0; } - return iconv_strpos($haystack, $needle, $offset, $encoding); + return \iconv_strpos($haystack, $needle, $offset, $encoding); } public static function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null) @@ -564,7 +533,7 @@ public static function mb_strrpos($haystack, $needle, $offset = 0, $encoding = n } $pos = '' !== $needle || 80000 > \PHP_VERSION_ID - ? iconv_strrpos($haystack, $needle, $encoding) + ? \iconv_strrpos($haystack, $needle, $encoding) : self::mb_strlen($haystack, $encoding); return false !== $pos ? $offset + $pos : false; @@ -572,7 +541,7 @@ public static function mb_strrpos($haystack, $needle, $offset = 0, $encoding = n public static function mb_str_split($string, $split_length = 1, $encoding = null) { - if (null !== $string && !\is_scalar($string) && !(\is_object($string) && method_exists($string, '__toString'))) { + if (null !== $string && !is_scalar($string) && !(\is_object($string) && method_exists($string, '__toString'))) { trigger_error('mb_str_split() expects parameter 1 to be string, '.\gettype($string).' given', \E_USER_WARNING); return null; @@ -581,7 +550,6 @@ public static function mb_str_split($string, $split_length = 1, $encoding = null if (1 > $split_length = (int) $split_length) { if (80000 > \PHP_VERSION_ID) { trigger_error('The length of each segment must be greater than zero', \E_USER_WARNING); - return false; } @@ -600,7 +568,7 @@ public static function mb_str_split($string, $split_length = 1, $encoding = null } $rx .= '.{'.$split_length.'})/us'; - return preg_split($rx, $string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY); + return preg_split($rx, $string, null, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY); } $result = []; @@ -649,7 +617,7 @@ public static function mb_substr($s, $start, $length = null, $encoding = null) } if ($start < 0) { - $start = iconv_strlen($s, $encoding) + $start; + $start = \iconv_strlen($s, $encoding) + $start; if ($start < 0) { $start = 0; } @@ -658,21 +626,19 @@ public static function mb_substr($s, $start, $length = null, $encoding = null) if (null === $length) { $length = 2147483647; } elseif ($length < 0) { - $length = iconv_strlen($s, $encoding) + $length - $start; + $length = \iconv_strlen($s, $encoding) + $length - $start; if ($length < 0) { return ''; } } - return (string) iconv_substr($s, $start, $length, $encoding); + return (string) \iconv_substr($s, $start, $length, $encoding); } public static function mb_stripos($haystack, $needle, $offset = 0, $encoding = null) { - [$haystack, $needle] = str_replace(self::SIMPLE_CASE_FOLD[0], self::SIMPLE_CASE_FOLD[1], [ - self::mb_convert_case($haystack, \MB_CASE_LOWER, $encoding), - self::mb_convert_case($needle, \MB_CASE_LOWER, $encoding), - ]); + $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding); + $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding); return self::mb_strpos($haystack, $needle, $offset, $encoding); } @@ -691,7 +657,7 @@ public static function mb_strrchr($haystack, $needle, $part = false, $encoding = $pos = strrpos($haystack, $needle); } else { $needle = self::mb_substr($needle, 0, 1, $encoding); - $pos = iconv_strrpos($haystack, $needle, $encoding); + $pos = \iconv_strrpos($haystack, $needle, $encoding); } return self::getSubpart($pos, $part, $haystack, $encoding); @@ -707,11 +673,8 @@ public static function mb_strrichr($haystack, $needle, $part = false, $encoding public static function mb_strripos($haystack, $needle, $offset = 0, $encoding = null) { - $haystack = self::mb_convert_case($haystack, \MB_CASE_LOWER, $encoding); - $needle = self::mb_convert_case($needle, \MB_CASE_LOWER, $encoding); - - $haystack = str_replace(self::SIMPLE_CASE_FOLD[0], self::SIMPLE_CASE_FOLD[1], $haystack); - $needle = str_replace(self::SIMPLE_CASE_FOLD[0], self::SIMPLE_CASE_FOLD[1], $needle); + $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding); + $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding); return self::mb_strrpos($haystack, $needle, $offset, $encoding); } @@ -773,12 +736,12 @@ public static function mb_strwidth($s, $encoding = null) $encoding = self::getEncoding($encoding); if ('UTF-8' !== $encoding) { - $s = iconv($encoding, 'UTF-8//IGNORE', $s); + $s = \iconv($encoding, 'UTF-8//IGNORE', $s); } $s = preg_replace('/[\x{1100}-\x{115F}\x{2329}\x{232A}\x{2E80}-\x{303E}\x{3040}-\x{A4CF}\x{AC00}-\x{D7A3}\x{F900}-\x{FAFF}\x{FE10}-\x{FE19}\x{FE30}-\x{FE6F}\x{FF00}-\x{FF60}\x{FFE0}-\x{FFE6}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}]/u', '', $s, -1, $wide); - return ($wide << 1) + iconv_strlen($s, 'UTF-8'); + return ($wide << 1) + \iconv_strlen($s, 'UTF-8'); } public static function mb_substr_count($haystack, $needle, $encoding = null) @@ -834,69 +797,6 @@ public static function mb_ord($s, $encoding = null) return $code; } - public static function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = \STR_PAD_RIGHT, ?string $encoding = null): string - { - if (!\in_array($pad_type, [\STR_PAD_RIGHT, \STR_PAD_LEFT, \STR_PAD_BOTH], true)) { - throw new \ValueError('mb_str_pad(): Argument #4 ($pad_type) must be STR_PAD_LEFT, STR_PAD_RIGHT, or STR_PAD_BOTH'); - } - - if (null === $encoding) { - $encoding = self::mb_internal_encoding(); - } else { - self::assertEncoding($encoding, 'mb_str_pad(): Argument #5 ($encoding) must be a valid encoding, "%s" given'); - } - - if (self::mb_strlen($pad_string, $encoding) <= 0) { - throw new \ValueError('mb_str_pad(): Argument #3 ($pad_string) must be a non-empty string'); - } - - $paddingRequired = $length - self::mb_strlen($string, $encoding); - - if ($paddingRequired < 1) { - return $string; - } - - switch ($pad_type) { - case \STR_PAD_LEFT: - return self::mb_substr(str_repeat($pad_string, $paddingRequired), 0, $paddingRequired, $encoding).$string; - case \STR_PAD_RIGHT: - return $string.self::mb_substr(str_repeat($pad_string, $paddingRequired), 0, $paddingRequired, $encoding); - default: - $leftPaddingLength = floor($paddingRequired / 2); - $rightPaddingLength = $paddingRequired - $leftPaddingLength; - - return self::mb_substr(str_repeat($pad_string, $leftPaddingLength), 0, $leftPaddingLength, $encoding).$string.self::mb_substr(str_repeat($pad_string, $rightPaddingLength), 0, $rightPaddingLength, $encoding); - } - } - - public static function mb_ucfirst(string $string, ?string $encoding = null): string - { - if (null === $encoding) { - $encoding = self::mb_internal_encoding(); - } else { - self::assertEncoding($encoding, 'mb_ucfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given'); - } - - $firstChar = mb_substr($string, 0, 1, $encoding); - $firstChar = mb_convert_case($firstChar, \MB_CASE_TITLE, $encoding); - - return $firstChar.mb_substr($string, 1, null, $encoding); - } - - public static function mb_lcfirst(string $string, ?string $encoding = null): string - { - if (null === $encoding) { - $encoding = self::mb_internal_encoding(); - } else { - self::assertEncoding($encoding, 'mb_lcfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given'); - } - - $firstChar = mb_substr($string, 0, 1, $encoding); - $firstChar = mb_convert_case($firstChar, \MB_CASE_LOWER, $encoding); - - return $firstChar.mb_substr($string, 1, null, $encoding); - } - private static function getSubpart($pos, $part, $haystack, $encoding) { if (false === $pos) { @@ -970,76 +870,4 @@ private static function getEncoding($encoding) return $encoding; } - - public static function mb_trim(string $string, ?string $characters = null, ?string $encoding = null): string - { - return self::mb_internal_trim('{^[%s]+|[%1$s]+$}Du', $string, $characters, $encoding, __FUNCTION__); - } - - public static function mb_ltrim(string $string, ?string $characters = null, ?string $encoding = null): string - { - return self::mb_internal_trim('{^[%s]+}Du', $string, $characters, $encoding, __FUNCTION__); - } - - public static function mb_rtrim(string $string, ?string $characters = null, ?string $encoding = null): string - { - return self::mb_internal_trim('{[%s]+$}D', $string, $characters, $encoding, __FUNCTION__); - } - - private static function mb_internal_trim(string $regex, string $string, ?string $characters, ?string $encoding, string $function): string - { - if (null === $encoding) { - $encoding = self::mb_internal_encoding(); - } else { - self::assertEncoding($encoding, $function.'(): Argument #3 ($encoding) must be a valid encoding, "%s" given'); - } - - if ('' === $characters) { - return null === $encoding ? $string : self::mb_convert_encoding($string, $encoding); - } - - if ('UTF-8' === $encoding) { - $encoding = null; - if (!preg_match('//u', $string)) { - $string = @iconv('UTF-8', 'UTF-8//IGNORE', $string); - } - if (null !== $characters && !preg_match('//u', $characters)) { - $characters = @iconv('UTF-8', 'UTF-8//IGNORE', $characters); - } - } else { - $string = iconv($encoding, 'UTF-8//IGNORE', $string); - - if (null !== $characters) { - $characters = iconv($encoding, 'UTF-8//IGNORE', $characters); - } - } - - if (null === $characters) { - $characters = "\\0 \f\n\r\t\v\u{00A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{2028}\u{2029}\u{202F}\u{205F}\u{3000}\u{0085}\u{180E}"; - } else { - $characters = preg_quote($characters); - } - - $string = preg_replace(sprintf($regex, $characters), '', $string); - - if (null === $encoding) { - return $string; - } - - return iconv('UTF-8', $encoding.'//IGNORE', $string); - } - - private static function assertEncoding(string $encoding, string $errorFormat): void - { - try { - $validEncoding = @self::mb_check_encoding('', $encoding); - } catch (\ValueError $e) { - throw new \ValueError(sprintf($errorFormat, $encoding)); - } - - // BC for PHP 7.3 and lower - if (!$validEncoding) { - throw new \ValueError(sprintf($errorFormat, $encoding)); - } - } } diff --git a/deps/vendor/symfony/polyfill-mbstring/README.md b/deps/vendor/symfony/polyfill-mbstring/README.md index 478b40da2..4efb599d8 100644 --- a/deps/vendor/symfony/polyfill-mbstring/README.md +++ b/deps/vendor/symfony/polyfill-mbstring/README.md @@ -5,7 +5,7 @@ This component provides a partial, native PHP implementation for the [Mbstring](https://php.net/mbstring) extension. More information can be found in the -[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md). +[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md). License ======= diff --git a/deps/vendor/symfony/polyfill-mbstring/Resources/unidata/caseFolding.php b/deps/vendor/symfony/polyfill-mbstring/Resources/unidata/caseFolding.php deleted file mode 100644 index 512bba0bf..000000000 --- a/deps/vendor/symfony/polyfill-mbstring/Resources/unidata/caseFolding.php +++ /dev/null @@ -1,119 +0,0 @@ - 'i̇', - 'µ' => 'μ', - 'ſ' => 's', - 'ͅ' => 'ι', - 'ς' => 'σ', - 'ϐ' => 'β', - 'ϑ' => 'θ', - 'ϕ' => 'φ', - 'ϖ' => 'π', - 'ϰ' => 'κ', - 'ϱ' => 'ρ', - 'ϵ' => 'ε', - 'ẛ' => 'ṡ', - 'ι' => 'ι', - 'ß' => 'ss', - 'ʼn' => 'ʼn', - 'ǰ' => 'ǰ', - 'ΐ' => 'ΐ', - 'ΰ' => 'ΰ', - 'և' => 'եւ', - 'ẖ' => 'ẖ', - 'ẗ' => 'ẗ', - 'ẘ' => 'ẘ', - 'ẙ' => 'ẙ', - 'ẚ' => 'aʾ', - 'ẞ' => 'ss', - 'ὐ' => 'ὐ', - 'ὒ' => 'ὒ', - 'ὔ' => 'ὔ', - 'ὖ' => 'ὖ', - 'ᾀ' => 'ἀι', - 'ᾁ' => 'ἁι', - 'ᾂ' => 'ἂι', - 'ᾃ' => 'ἃι', - 'ᾄ' => 'ἄι', - 'ᾅ' => 'ἅι', - 'ᾆ' => 'ἆι', - 'ᾇ' => 'ἇι', - 'ᾈ' => 'ἀι', - 'ᾉ' => 'ἁι', - 'ᾊ' => 'ἂι', - 'ᾋ' => 'ἃι', - 'ᾌ' => 'ἄι', - 'ᾍ' => 'ἅι', - 'ᾎ' => 'ἆι', - 'ᾏ' => 'ἇι', - 'ᾐ' => 'ἠι', - 'ᾑ' => 'ἡι', - 'ᾒ' => 'ἢι', - 'ᾓ' => 'ἣι', - 'ᾔ' => 'ἤι', - 'ᾕ' => 'ἥι', - 'ᾖ' => 'ἦι', - 'ᾗ' => 'ἧι', - 'ᾘ' => 'ἠι', - 'ᾙ' => 'ἡι', - 'ᾚ' => 'ἢι', - 'ᾛ' => 'ἣι', - 'ᾜ' => 'ἤι', - 'ᾝ' => 'ἥι', - 'ᾞ' => 'ἦι', - 'ᾟ' => 'ἧι', - 'ᾠ' => 'ὠι', - 'ᾡ' => 'ὡι', - 'ᾢ' => 'ὢι', - 'ᾣ' => 'ὣι', - 'ᾤ' => 'ὤι', - 'ᾥ' => 'ὥι', - 'ᾦ' => 'ὦι', - 'ᾧ' => 'ὧι', - 'ᾨ' => 'ὠι', - 'ᾩ' => 'ὡι', - 'ᾪ' => 'ὢι', - 'ᾫ' => 'ὣι', - 'ᾬ' => 'ὤι', - 'ᾭ' => 'ὥι', - 'ᾮ' => 'ὦι', - 'ᾯ' => 'ὧι', - 'ᾲ' => 'ὰι', - 'ᾳ' => 'αι', - 'ᾴ' => 'άι', - 'ᾶ' => 'ᾶ', - 'ᾷ' => 'ᾶι', - 'ᾼ' => 'αι', - 'ῂ' => 'ὴι', - 'ῃ' => 'ηι', - 'ῄ' => 'ήι', - 'ῆ' => 'ῆ', - 'ῇ' => 'ῆι', - 'ῌ' => 'ηι', - 'ῒ' => 'ῒ', - 'ῖ' => 'ῖ', - 'ῗ' => 'ῗ', - 'ῢ' => 'ῢ', - 'ῤ' => 'ῤ', - 'ῦ' => 'ῦ', - 'ῧ' => 'ῧ', - 'ῲ' => 'ὼι', - 'ῳ' => 'ωι', - 'ῴ' => 'ώι', - 'ῶ' => 'ῶ', - 'ῷ' => 'ῶι', - 'ῼ' => 'ωι', - 'ff' => 'ff', - 'fi' => 'fi', - 'fl' => 'fl', - 'ffi' => 'ffi', - 'ffl' => 'ffl', - 'ſt' => 'st', - 'st' => 'st', - 'ﬓ' => 'մն', - 'ﬔ' => 'մե', - 'ﬕ' => 'մի', - 'ﬖ' => 'վն', - 'ﬗ' => 'մխ', -]; diff --git a/deps/vendor/symfony/polyfill-mbstring/bootstrap.php b/deps/vendor/symfony/polyfill-mbstring/bootstrap.php index ff51ae079..1fedd1f7c 100644 --- a/deps/vendor/symfony/polyfill-mbstring/bootstrap.php +++ b/deps/vendor/symfony/polyfill-mbstring/bootstrap.php @@ -132,31 +132,6 @@ function mb_scrub($string, $encoding = null) { $encoding = null === $encoding ? function mb_str_split($string, $length = 1, $encoding = null) { return p\Mbstring::mb_str_split($string, $length, $encoding); } } -if (!function_exists('mb_str_pad')) { - function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = STR_PAD_RIGHT, ?string $encoding = null): string { return p\Mbstring::mb_str_pad($string, $length, $pad_string, $pad_type, $encoding); } -} - -if (!function_exists('mb_ucfirst')) { - function mb_ucfirst(string $string, ?string $encoding = null): string { return p\Mbstring::mb_ucfirst($string, $encoding); } -} - -if (!function_exists('mb_lcfirst')) { - function mb_lcfirst(string $string, ?string $encoding = null): string { return p\Mbstring::mb_lcfirst($string, $encoding); } -} - -if (!function_exists('mb_trim')) { - function mb_trim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Mbstring::mb_trim($string, $characters, $encoding); } -} - -if (!function_exists('mb_ltrim')) { - function mb_ltrim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Mbstring::mb_ltrim($string, $characters, $encoding); } -} - -if (!function_exists('mb_rtrim')) { - function mb_rtrim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Mbstring::mb_rtrim($string, $characters, $encoding); } -} - - if (extension_loaded('mbstring')) { return; } diff --git a/deps/vendor/symfony/polyfill-mbstring/bootstrap80.php b/deps/vendor/symfony/polyfill-mbstring/bootstrap80.php index 5be7d2018..82f5ac4d0 100644 --- a/deps/vendor/symfony/polyfill-mbstring/bootstrap80.php +++ b/deps/vendor/symfony/polyfill-mbstring/bootstrap80.php @@ -93,7 +93,7 @@ function mb_strrpos(?string $haystack, ?string $needle, ?int $offset = 0, ?strin function mb_strstr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_strstr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); } } if (!function_exists('mb_get_info')) { - function mb_get_info(?string $type = 'all'): array|string|int|false|null { return p\Mbstring::mb_get_info((string) $type); } + function mb_get_info(?string $type = 'all'): array|string|int|false { return p\Mbstring::mb_get_info((string) $type); } } if (!function_exists('mb_http_output')) { function mb_http_output(?string $encoding = null): string|bool { return p\Mbstring::mb_http_output($encoding); } @@ -128,30 +128,6 @@ function mb_scrub(?string $string, ?string $encoding = null): string { $encoding function mb_str_split(?string $string, ?int $length = 1, ?string $encoding = null): array { return p\Mbstring::mb_str_split((string) $string, (int) $length, $encoding); } } -if (!function_exists('mb_str_pad')) { - function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = STR_PAD_RIGHT, ?string $encoding = null): string { return p\Mbstring::mb_str_pad($string, $length, $pad_string, $pad_type, $encoding); } -} - -if (!function_exists('mb_ucfirst')) { - function mb_ucfirst($string, ?string $encoding = null): string { return p\Mbstring::mb_ucfirst($string, $encoding); } -} - -if (!function_exists('mb_lcfirst')) { - function mb_lcfirst($string, ?string $encoding = null): string { return p\Mbstring::mb_lcfirst($string, $encoding); } -} - -if (!function_exists('mb_trim')) { - function mb_trim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Mbstring::mb_trim($string, $characters, $encoding); } -} - -if (!function_exists('mb_ltrim')) { - function mb_ltrim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Mbstring::mb_ltrim($string, $characters, $encoding); } -} - -if (!function_exists('mb_rtrim')) { - function mb_rtrim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Mbstring::mb_rtrim($string, $characters, $encoding); } -} - if (extension_loaded('mbstring')) { return; } diff --git a/deps/vendor/symfony/polyfill-mbstring/composer.json b/deps/vendor/symfony/polyfill-mbstring/composer.json index 4ed241a33..1fa21ca16 100644 --- a/deps/vendor/symfony/polyfill-mbstring/composer.json +++ b/deps/vendor/symfony/polyfill-mbstring/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=7.2" + "php": ">=7.1" }, "provide": { "ext-mbstring": "*" @@ -30,6 +30,9 @@ }, "minimum-stability": "dev", "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" diff --git a/deps/vendor/symfony/polyfill-php73/LICENSE b/deps/vendor/symfony/polyfill-php73/LICENSE index 7536caeae..3f853aaf3 100644 --- a/deps/vendor/symfony/polyfill-php73/LICENSE +++ b/deps/vendor/symfony/polyfill-php73/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2018-present Fabien Potencier +Copyright (c) 2018-2019 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/deps/vendor/symfony/polyfill-php73/README.md b/deps/vendor/symfony/polyfill-php73/README.md index 032fafbda..b3ebbce51 100644 --- a/deps/vendor/symfony/polyfill-php73/README.md +++ b/deps/vendor/symfony/polyfill-php73/README.md @@ -10,7 +10,7 @@ This component provides functions added to PHP 7.3 core: - [`JsonException`](https://php.net/JsonException) More information can be found in the -[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md). +[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md). License ======= diff --git a/deps/vendor/symfony/polyfill-php73/composer.json b/deps/vendor/symfony/polyfill-php73/composer.json index 09d98cb87..a7fe47875 100644 --- a/deps/vendor/symfony/polyfill-php73/composer.json +++ b/deps/vendor/symfony/polyfill-php73/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=7.2" + "php": ">=7.1" }, "autoload": { "psr-4": { "Symfony\\Polyfill\\Php73\\": "" }, @@ -25,6 +25,9 @@ }, "minimum-stability": "dev", "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" diff --git a/deps/vendor/symfony/polyfill-php80/LICENSE b/deps/vendor/symfony/polyfill-php80/LICENSE index 0ed3a2465..5593b1d84 100644 --- a/deps/vendor/symfony/polyfill-php80/LICENSE +++ b/deps/vendor/symfony/polyfill-php80/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2020-present Fabien Potencier +Copyright (c) 2020 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/deps/vendor/symfony/polyfill-php80/README.md b/deps/vendor/symfony/polyfill-php80/README.md index 3816c559d..10b8ee49a 100644 --- a/deps/vendor/symfony/polyfill-php80/README.md +++ b/deps/vendor/symfony/polyfill-php80/README.md @@ -3,13 +3,12 @@ Symfony Polyfill / Php80 This component provides features added to PHP 8.0 core: -- [`Stringable`](https://php.net/stringable) interface +- `Stringable` interface - [`fdiv`](https://php.net/fdiv) -- [`ValueError`](https://php.net/valueerror) class -- [`UnhandledMatchError`](https://php.net/unhandledmatcherror) class +- `ValueError` class +- `UnhandledMatchError` class - `FILTER_VALIDATE_BOOL` constant - [`get_debug_type`](https://php.net/get_debug_type) -- [`PhpToken`](https://php.net/phptoken) class - [`preg_last_error_msg`](https://php.net/preg_last_error_msg) - [`str_contains`](https://php.net/str_contains) - [`str_starts_with`](https://php.net/str_starts_with) diff --git a/deps/vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php b/deps/vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php index 2b955423f..7ea6d2772 100644 --- a/deps/vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php +++ b/deps/vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php @@ -1,14 +1,5 @@ - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - #[Attribute(Attribute::TARGET_CLASS)] final class Attribute { diff --git a/deps/vendor/symfony/polyfill-php80/Resources/stubs/PhpToken.php b/deps/vendor/symfony/polyfill-php80/Resources/stubs/PhpToken.php index bd1212f6e..72f10812b 100644 --- a/deps/vendor/symfony/polyfill-php80/Resources/stubs/PhpToken.php +++ b/deps/vendor/symfony/polyfill-php80/Resources/stubs/PhpToken.php @@ -1,15 +1,6 @@ - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -if (\PHP_VERSION_ID < 80000 && extension_loaded('tokenizer')) { +if (\PHP_VERSION_ID < 80000 && \extension_loaded('tokenizer')) { class PhpToken extends Symfony\Polyfill\Php80\PhpToken { } diff --git a/deps/vendor/symfony/polyfill-php80/Resources/stubs/Stringable.php b/deps/vendor/symfony/polyfill-php80/Resources/stubs/Stringable.php index 7c62d7508..77e037cb5 100644 --- a/deps/vendor/symfony/polyfill-php80/Resources/stubs/Stringable.php +++ b/deps/vendor/symfony/polyfill-php80/Resources/stubs/Stringable.php @@ -1,14 +1,5 @@ - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - if (\PHP_VERSION_ID < 80000) { interface Stringable { diff --git a/deps/vendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php b/deps/vendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php index 01c6c6c8a..37937cbfa 100644 --- a/deps/vendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php +++ b/deps/vendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php @@ -1,14 +1,5 @@ - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - if (\PHP_VERSION_ID < 80000) { class UnhandledMatchError extends Error { diff --git a/deps/vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php b/deps/vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php index 783dbc28c..a3a9b88b0 100644 --- a/deps/vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php +++ b/deps/vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php @@ -1,14 +1,5 @@ - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - if (\PHP_VERSION_ID < 80000) { class ValueError extends Error { diff --git a/deps/vendor/symfony/polyfill-php80/composer.json b/deps/vendor/symfony/polyfill-php80/composer.json index a503b039a..5fe679db3 100644 --- a/deps/vendor/symfony/polyfill-php80/composer.json +++ b/deps/vendor/symfony/polyfill-php80/composer.json @@ -20,7 +20,7 @@ } ], "require": { - "php": ">=7.2" + "php": ">=7.1" }, "autoload": { "psr-4": { "Symfony\\Polyfill\\Php80\\": "" }, @@ -29,6 +29,9 @@ }, "minimum-stability": "dev", "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" diff --git a/deps/vendor/symfony/polyfill-php81/LICENSE b/deps/vendor/symfony/polyfill-php81/LICENSE index 99c6bdf35..efb17f98e 100644 --- a/deps/vendor/symfony/polyfill-php81/LICENSE +++ b/deps/vendor/symfony/polyfill-php81/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2021-present Fabien Potencier +Copyright (c) 2021 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/deps/vendor/symfony/polyfill-php81/README.md b/deps/vendor/symfony/polyfill-php81/README.md index c07ef7820..7d8dd1907 100644 --- a/deps/vendor/symfony/polyfill-php81/README.md +++ b/deps/vendor/symfony/polyfill-php81/README.md @@ -7,7 +7,6 @@ This component provides features added to PHP 8.1 core: - [`enum_exists`](https://php.net/enum-exists) - [`MYSQLI_REFRESH_REPLICA`](https://php.net/mysqli.constants#constantmysqli-refresh-replica) constant - [`ReturnTypeWillChange`](https://wiki.php.net/rfc/internal_method_return_types) -- [`CURLStringFile`](https://php.net/CURLStringFile) (but only if PHP >= 7.4 is used) More information can be found in the [main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md). diff --git a/deps/vendor/symfony/polyfill-php81/Resources/stubs/CURLStringFile.php b/deps/vendor/symfony/polyfill-php81/Resources/stubs/CURLStringFile.php deleted file mode 100644 index 5ff93fcaf..000000000 --- a/deps/vendor/symfony/polyfill-php81/Resources/stubs/CURLStringFile.php +++ /dev/null @@ -1,51 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -if (\PHP_VERSION_ID >= 70400 && extension_loaded('curl')) { - /** - * @property string $data - */ - class CURLStringFile extends CURLFile - { - private $data; - - public function __construct(string $data, string $postname, string $mime = 'application/octet-stream') - { - $this->data = $data; - parent::__construct('data://application/octet-stream;base64,'.base64_encode($data), $mime, $postname); - } - - public function __set(string $name, $value): void - { - if ('data' !== $name) { - $this->$name = $value; - - return; - } - - if (is_object($value) ? !method_exists($value, '__toString') : !is_scalar($value)) { - throw new TypeError('Cannot assign '.gettype($value).' to property CURLStringFile::$data of type string'); - } - - $this->name = 'data://application/octet-stream;base64,'.base64_encode($value); - } - - public function __isset(string $name): bool - { - return isset($this->$name); - } - - public function &__get(string $name) - { - return $this->$name; - } - } -} diff --git a/deps/vendor/symfony/polyfill-php81/Resources/stubs/ReturnTypeWillChange.php b/deps/vendor/symfony/polyfill-php81/Resources/stubs/ReturnTypeWillChange.php index cb7720a8d..f4cad34f6 100644 --- a/deps/vendor/symfony/polyfill-php81/Resources/stubs/ReturnTypeWillChange.php +++ b/deps/vendor/symfony/polyfill-php81/Resources/stubs/ReturnTypeWillChange.php @@ -1,14 +1,5 @@ - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - if (\PHP_VERSION_ID < 80100) { #[Attribute(Attribute::TARGET_METHOD)] final class ReturnTypeWillChange diff --git a/deps/vendor/symfony/polyfill-php81/composer.json b/deps/vendor/symfony/polyfill-php81/composer.json index 28b6408ea..014da788e 100644 --- a/deps/vendor/symfony/polyfill-php81/composer.json +++ b/deps/vendor/symfony/polyfill-php81/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=7.2" + "php": ">=7.1" }, "autoload": { "psr-4": { "Symfony\\Polyfill\\Php81\\": "" }, @@ -25,6 +25,9 @@ }, "minimum-stability": "dev", "extra": { + "branch-alias": { + "dev-main": "1.26-dev" + }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" diff --git a/deps/vendor/symfony/process/ExecutableFinder.php b/deps/vendor/symfony/process/ExecutableFinder.php index 6dc00b7c2..5914b4cd2 100644 --- a/deps/vendor/symfony/process/ExecutableFinder.php +++ b/deps/vendor/symfony/process/ExecutableFinder.php @@ -46,12 +46,27 @@ public function addSuffix(string $suffix) * * @return string|null */ - public function find(string $name, ?string $default = null, array $extraDirs = []) + public function find(string $name, string $default = null, array $extraDirs = []) { - $dirs = array_merge( - explode(\PATH_SEPARATOR, getenv('PATH') ?: getenv('Path')), - $extraDirs - ); + if (ini_get('open_basedir')) { + $searchPath = array_merge(explode(\PATH_SEPARATOR, ini_get('open_basedir')), $extraDirs); + $dirs = []; + foreach ($searchPath as $path) { + // Silencing against https://bugs.php.net/69240 + if (@is_dir($path)) { + $dirs[] = $path; + } else { + if (basename($path) == $name && @is_executable($path)) { + return $path; + } + } + } + } else { + $dirs = array_merge( + explode(\PATH_SEPARATOR, getenv('PATH') ?: getenv('Path')), + $extraDirs + ); + } $suffixes = ['']; if ('\\' === \DIRECTORY_SEPARATOR) { @@ -63,18 +78,9 @@ public function find(string $name, ?string $default = null, array $extraDirs = [ if (@is_file($file = $dir.\DIRECTORY_SEPARATOR.$name.$suffix) && ('\\' === \DIRECTORY_SEPARATOR || @is_executable($file))) { return $file; } - - if (!@is_dir($dir) && basename($dir) === $name.$suffix && @is_executable($dir)) { - return $dir; - } } } - $command = '\\' === \DIRECTORY_SEPARATOR ? 'where' : 'command -v --'; - if (\function_exists('exec') && ($executablePath = strtok(@exec($command.' '.escapeshellarg($name)), \PHP_EOL)) && @is_executable($executablePath)) { - return $executablePath; - } - return $default; } } diff --git a/deps/vendor/symfony/process/InputStream.php b/deps/vendor/symfony/process/InputStream.php index 0c45b5245..240665f32 100644 --- a/deps/vendor/symfony/process/InputStream.php +++ b/deps/vendor/symfony/process/InputStream.php @@ -30,7 +30,7 @@ class InputStream implements \IteratorAggregate /** * Sets a callback that is called when the write buffer becomes empty. */ - public function onEmpty(?callable $onEmpty = null) + public function onEmpty(callable $onEmpty = null) { $this->onEmpty = $onEmpty; } diff --git a/deps/vendor/symfony/process/LICENSE b/deps/vendor/symfony/process/LICENSE index 0138f8f07..88bf75bb4 100644 --- a/deps/vendor/symfony/process/LICENSE +++ b/deps/vendor/symfony/process/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-present Fabien Potencier +Copyright (c) 2004-2022 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/deps/vendor/symfony/process/PhpExecutableFinder.php b/deps/vendor/symfony/process/PhpExecutableFinder.php index 54fe74434..ec24f911b 100644 --- a/deps/vendor/symfony/process/PhpExecutableFinder.php +++ b/deps/vendor/symfony/process/PhpExecutableFinder.php @@ -35,8 +35,8 @@ public function find(bool $includeArgs = true) { if ($php = getenv('PHP_BINARY')) { if (!is_executable($php)) { - $command = '\\' === \DIRECTORY_SEPARATOR ? 'where' : 'command -v --'; - if (\function_exists('exec') && $php = strtok(exec($command.' '.escapeshellarg($php)), \PHP_EOL)) { + $command = '\\' === \DIRECTORY_SEPARATOR ? 'where' : 'command -v'; + if ($php = strtok(exec($command.' '.escapeshellarg($php)), \PHP_EOL)) { if (!is_executable($php)) { return false; } @@ -45,10 +45,6 @@ public function find(bool $includeArgs = true) } } - if (@is_dir($php)) { - return false; - } - return $php; } @@ -56,12 +52,12 @@ public function find(bool $includeArgs = true) $args = $includeArgs && $args ? ' '.implode(' ', $args) : ''; // PHP_BINARY return the current sapi executable - if (\PHP_BINARY && \in_array(\PHP_SAPI, ['cli', 'cli-server', 'phpdbg'], true)) { + if (\PHP_BINARY && \in_array(\PHP_SAPI, ['cgi-fcgi', 'cli', 'cli-server', 'phpdbg'], true)) { return \PHP_BINARY.$args; } if ($php = getenv('PHP_PATH')) { - if (!@is_executable($php) || @is_dir($php)) { + if (!@is_executable($php)) { return false; } @@ -69,12 +65,12 @@ public function find(bool $includeArgs = true) } if ($php = getenv('PHP_PEAR_PHP_BIN')) { - if (@is_executable($php) && !@is_dir($php)) { + if (@is_executable($php)) { return $php; } } - if (@is_executable($php = \PHP_BINDIR.('\\' === \DIRECTORY_SEPARATOR ? '\\php.exe' : '/php')) && !@is_dir($php)) { + if (@is_executable($php = \PHP_BINDIR.('\\' === \DIRECTORY_SEPARATOR ? '\\php.exe' : '/php'))) { return $php; } diff --git a/deps/vendor/symfony/process/PhpProcess.php b/deps/vendor/symfony/process/PhpProcess.php index 3a1d147c8..2bc338e5e 100644 --- a/deps/vendor/symfony/process/PhpProcess.php +++ b/deps/vendor/symfony/process/PhpProcess.php @@ -32,7 +32,7 @@ class PhpProcess extends Process * @param int $timeout The timeout in seconds * @param array|null $php Path to the PHP binary to use with any additional arguments */ - public function __construct(string $script, ?string $cwd = null, ?array $env = null, int $timeout = 60, ?array $php = null) + public function __construct(string $script, string $cwd = null, array $env = null, int $timeout = 60, array $php = null) { if (null === $php) { $executableFinder = new PhpExecutableFinder(); @@ -53,7 +53,7 @@ public function __construct(string $script, ?string $cwd = null, ?array $env = n /** * {@inheritdoc} */ - public static function fromShellCommandline(string $command, ?string $cwd = null, ?array $env = null, $input = null, ?float $timeout = 60) + public static function fromShellCommandline(string $command, string $cwd = null, array $env = null, $input = null, ?float $timeout = 60) { throw new LogicException(sprintf('The "%s()" method cannot be called when using "%s".', __METHOD__, self::class)); } @@ -61,7 +61,7 @@ public static function fromShellCommandline(string $command, ?string $cwd = null /** * {@inheritdoc} */ - public function start(?callable $callback = null, array $env = []) + public function start(callable $callback = null, array $env = []) { if (null === $this->getCommandLine()) { throw new RuntimeException('Unable to find the PHP executable.'); diff --git a/deps/vendor/symfony/process/Pipes/AbstractPipes.php b/deps/vendor/symfony/process/Pipes/AbstractPipes.php index 656dc0328..010510056 100644 --- a/deps/vendor/symfony/process/Pipes/AbstractPipes.php +++ b/deps/vendor/symfony/process/Pipes/AbstractPipes.php @@ -104,7 +104,7 @@ protected function write(): ?array stream_set_blocking($input, 0); } elseif (!isset($this->inputBuffer[0])) { if (!\is_string($input)) { - if (!\is_scalar($input)) { + if (!is_scalar($input)) { throw new InvalidArgumentException(sprintf('"%s" yielded a value of type "%s", but only scalars and stream resources are supported.', get_debug_type($this->input), get_debug_type($input))); } $input = (string) $input; diff --git a/deps/vendor/symfony/process/Pipes/WindowsPipes.php b/deps/vendor/symfony/process/Pipes/WindowsPipes.php index 968dd0262..bca84f574 100644 --- a/deps/vendor/symfony/process/Pipes/WindowsPipes.php +++ b/deps/vendor/symfony/process/Pipes/WindowsPipes.php @@ -149,7 +149,7 @@ public function readAndWrite(bool $blocking, bool $close = false): array if ($w) { @stream_select($r, $w, $e, 0, Process::TIMEOUT_PRECISION * 1E6); } elseif ($this->fileHandles) { - usleep((int) (Process::TIMEOUT_PRECISION * 1E6)); + usleep(Process::TIMEOUT_PRECISION * 1E6); } } foreach ($this->fileHandles as $type => $fileHandle) { diff --git a/deps/vendor/symfony/process/Process.php b/deps/vendor/symfony/process/Process.php index 62addf1e7..92771594d 100644 --- a/deps/vendor/symfony/process/Process.php +++ b/deps/vendor/symfony/process/Process.php @@ -55,7 +55,7 @@ class Process implements \IteratorAggregate private $hasCallback = false; private $commandline; private $cwd; - private $env = []; + private $env; private $input; private $starttime; private $lastOutputTime; @@ -80,7 +80,6 @@ class Process implements \IteratorAggregate private $processPipes; private $latestSignal; - private $cachedExitCode; private static $sigchild; @@ -141,7 +140,7 @@ class Process implements \IteratorAggregate * * @throws LogicException When proc_open is not installed */ - public function __construct(array $command, ?string $cwd = null, ?array $env = null, $input = null, ?float $timeout = 60) + public function __construct(array $command, string $cwd = null, array $env = null, $input = null, ?float $timeout = 60) { if (!\function_exists('proc_open')) { throw new LogicException('The Process class relies on proc_open, which is not available on your PHP installation.'); @@ -190,7 +189,7 @@ public function __construct(array $command, ?string $cwd = null, ?array $env = n * * @throws LogicException When proc_open is not installed */ - public static function fromShellCommandline(string $command, ?string $cwd = null, ?array $env = null, $input = null, ?float $timeout = 60) + public static function fromShellCommandline(string $command, string $cwd = null, array $env = null, $input = null, ?float $timeout = 60) { $process = new static([], $cwd, $env, $input, $timeout); $process->commandline = $command; @@ -248,7 +247,7 @@ public function __clone() * * @final */ - public function run(?callable $callback = null, array $env = []): int + public function run(callable $callback = null, array $env = []): int { $this->start($callback, $env); @@ -267,7 +266,7 @@ public function run(?callable $callback = null, array $env = []): int * * @final */ - public function mustRun(?callable $callback = null, array $env = []): self + public function mustRun(callable $callback = null, array $env = []): self { if (0 !== $this->run($callback, $env)) { throw new ProcessFailedException($this); @@ -295,7 +294,7 @@ public function mustRun(?callable $callback = null, array $env = []): self * @throws RuntimeException When process is already running * @throws LogicException In case a callback is provided and output has been disabled */ - public function start(?callable $callback = null, array $env = []) + public function start(callable $callback = null, array $env = []) { if ($this->isRunning()) { throw new RuntimeException('Process is already running.'); @@ -332,7 +331,7 @@ public function start(?callable $callback = null, array $env = []) // See https://unix.stackexchange.com/questions/71205/background-process-pipe-input $commandline = '{ ('.$commandline.') <&3 3<&- 3>/dev/null & } 3<&0;'; - $commandline .= 'pid=$!; echo $pid >&3; wait $pid 2>/dev/null; code=$?; echo $code >&3; exit $code'; + $commandline .= 'pid=$!; echo $pid >&3; wait $pid; code=$?; echo $code >&3; exit $code'; // Workaround for the bug, when PTS functionality is enabled. // @see : https://bugs.php.net/69442 @@ -352,7 +351,7 @@ public function start(?callable $callback = null, array $env = []) $this->process = @proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $envPairs, $this->options); - if (!$this->process) { + if (!\is_resource($this->process)) { throw new RuntimeException('Unable to launch a new process.'); } $this->status = self::STATUS_STARTED; @@ -386,7 +385,7 @@ public function start(?callable $callback = null, array $env = []) * * @final */ - public function restart(?callable $callback = null, array $env = []): self + public function restart(callable $callback = null, array $env = []): self { if ($this->isRunning()) { throw new RuntimeException('Process is already running.'); @@ -413,7 +412,7 @@ public function restart(?callable $callback = null, array $env = []): self * @throws ProcessSignaledException When process stopped after receiving signal * @throws LogicException When process is not yet started */ - public function wait(?callable $callback = null) + public function wait(callable $callback = null) { $this->requireProcessIsStarted(__FUNCTION__); @@ -429,7 +428,7 @@ public function wait(?callable $callback = null) do { $this->checkTimeout(); - $running = $this->isRunning() && ('\\' === \DIRECTORY_SEPARATOR || $this->processPipes->areOpen()); + $running = '\\' === \DIRECTORY_SEPARATOR ? $this->isRunning() : $this->processPipes->areOpen(); $this->readPipes($running, '\\' !== \DIRECTORY_SEPARATOR || !$running); } while ($running); @@ -618,10 +617,10 @@ public function getIncrementalOutput() * * @param int $flags A bit field of Process::ITER_* flags * - * @return \Generator - * * @throws LogicException in case the output has been disabled * @throws LogicException In case the process is not started + * + * @return \Generator */ #[\ReturnTypeWillChange] public function getIterator(int $flags = 0) @@ -911,11 +910,11 @@ public function getStatus() * Stops the process. * * @param int|float $timeout The timeout in seconds - * @param int|null $signal A POSIX signal to send in case the process has not stop at timeout, default is SIGKILL (9) + * @param int $signal A POSIX signal to send in case the process has not stop at timeout, default is SIGKILL (9) * * @return int|null The exit-code of the process or null if it's not running */ - public function stop(float $timeout = 10, ?int $signal = null) + public function stop(float $timeout = 10, int $signal = null) { $timeoutMicro = microtime(true) + $timeout; if ($this->isRunning()) { @@ -1311,7 +1310,7 @@ private function getDescriptors(): array * * @return \Closure */ - protected function buildCallback(?callable $callback = null) + protected function buildCallback(callable $callback = null) { if ($this->outputDisabled) { return function ($type, $data) use ($callback): bool { @@ -1346,19 +1345,6 @@ protected function updateStatus(bool $blocking) $this->processInformation = proc_get_status($this->process); $running = $this->processInformation['running']; - // In PHP < 8.3, "proc_get_status" only returns the correct exit status on the first call. - // Subsequent calls return -1 as the process is discarded. This workaround caches the first - // retrieved exit status for consistent results in later calls, mimicking PHP 8.3 behavior. - if (\PHP_VERSION_ID < 80300) { - if (!isset($this->cachedExitCode) && !$running && -1 !== $this->processInformation['exitcode']) { - $this->cachedExitCode = $this->processInformation['exitcode']; - } - - if (isset($this->cachedExitCode) && !$running && -1 === $this->processInformation['exitcode']) { - $this->processInformation['exitcode'] = $this->cachedExitCode; - } - } - $this->readPipes($running && $blocking, '\\' !== \DIRECTORY_SEPARATOR || !$running); if ($this->fallbackStatus && $this->isSigchildEnabled()) { @@ -1456,9 +1442,8 @@ private function readPipes(bool $blocking, bool $close) private function close(): int { $this->processPipes->close(); - if ($this->process) { + if (\is_resource($this->process)) { proc_close($this->process); - $this->process = null; } $this->exitcode = $this->processInformation['exitcode']; $this->status = self::STATUS_TERMINATED; diff --git a/deps/vendor/symfony/process/ProcessUtils.php b/deps/vendor/symfony/process/ProcessUtils.php index 2a7aff71b..6cc7a610b 100644 --- a/deps/vendor/symfony/process/ProcessUtils.php +++ b/deps/vendor/symfony/process/ProcessUtils.php @@ -48,7 +48,7 @@ public static function validateInput(string $caller, $input) if (\is_string($input)) { return $input; } - if (\is_scalar($input)) { + if (is_scalar($input)) { return (string) $input; } if ($input instanceof Process) { diff --git a/deps/vendor/symfony/service-contracts/.gitignore b/deps/vendor/symfony/service-contracts/.gitignore new file mode 100644 index 000000000..c49a5d8df --- /dev/null +++ b/deps/vendor/symfony/service-contracts/.gitignore @@ -0,0 +1,3 @@ +vendor/ +composer.lock +phpunit.xml diff --git a/deps/vendor/symfony/service-contracts/Attribute/SubscribedService.php b/deps/vendor/symfony/service-contracts/Attribute/SubscribedService.php index f850b8401..10d1bc38e 100644 --- a/deps/vendor/symfony/service-contracts/Attribute/SubscribedService.php +++ b/deps/vendor/symfony/service-contracts/Attribute/SubscribedService.php @@ -11,15 +11,10 @@ namespace Symfony\Contracts\Service\Attribute; -use Symfony\Contracts\Service\ServiceMethodsSubscriberTrait; -use Symfony\Contracts\Service\ServiceSubscriberInterface; +use Symfony\Contracts\Service\ServiceSubscriberTrait; /** - * For use as the return value for {@see ServiceSubscriberInterface}. - * - * @example new SubscribedService('http_client', HttpClientInterface::class, false, new Target('githubApi')) - * - * Use with {@see ServiceMethodsSubscriberTrait} to mark a method's return type + * Use with {@see ServiceSubscriberTrait} to mark a method's return type * as a subscribed service. * * @author Kevin Bond @@ -27,21 +22,12 @@ #[\Attribute(\Attribute::TARGET_METHOD)] final class SubscribedService { - /** @var object[] */ - public array $attributes; - /** - * @param string|null $key The key to use for the service - * @param class-string|null $type The service class - * @param bool $nullable Whether the service is optional - * @param object|object[] $attributes One or more dependency injection attributes to use + * @param string|null $key The key to use for the service + * If null, use "ClassName::methodName" */ public function __construct( - public ?string $key = null, - public ?string $type = null, - public bool $nullable = false, - array|object $attributes = [], + public ?string $key = null ) { - $this->attributes = \is_array($attributes) ? $attributes : [$attributes]; } } diff --git a/deps/vendor/symfony/service-contracts/LICENSE b/deps/vendor/symfony/service-contracts/LICENSE index 7536caeae..235841453 100644 --- a/deps/vendor/symfony/service-contracts/LICENSE +++ b/deps/vendor/symfony/service-contracts/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2018-present Fabien Potencier +Copyright (c) 2018-2021 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/deps/vendor/symfony/service-contracts/README.md b/deps/vendor/symfony/service-contracts/README.md index 42841a57d..41e054a10 100644 --- a/deps/vendor/symfony/service-contracts/README.md +++ b/deps/vendor/symfony/service-contracts/README.md @@ -3,7 +3,7 @@ Symfony Service Contracts A set of abstractions extracted out of the Symfony components. -Can be used to build on semantics that the Symfony components proved useful and +Can be used to build on semantics that the Symfony components proved useful - and that already have battle tested implementations. See https://github.com/symfony/contracts/blob/main/README.md for more information. diff --git a/deps/vendor/symfony/service-contracts/ResetInterface.php b/deps/vendor/symfony/service-contracts/ResetInterface.php index a4f389b01..1af1075ee 100644 --- a/deps/vendor/symfony/service-contracts/ResetInterface.php +++ b/deps/vendor/symfony/service-contracts/ResetInterface.php @@ -26,8 +26,5 @@ */ interface ResetInterface { - /** - * @return void - */ public function reset(); } diff --git a/deps/vendor/symfony/service-contracts/ServiceCollectionInterface.php b/deps/vendor/symfony/service-contracts/ServiceCollectionInterface.php deleted file mode 100644 index 2333139ce..000000000 --- a/deps/vendor/symfony/service-contracts/ServiceCollectionInterface.php +++ /dev/null @@ -1,26 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Contracts\Service; - -/** - * A ServiceProviderInterface that is also countable and iterable. - * - * @author Kevin Bond - * - * @template-covariant T of mixed - * - * @extends ServiceProviderInterface - * @extends \IteratorAggregate - */ -interface ServiceCollectionInterface extends ServiceProviderInterface, \Countable, \IteratorAggregate -{ -} diff --git a/deps/vendor/symfony/service-contracts/ServiceLocatorTrait.php b/deps/vendor/symfony/service-contracts/ServiceLocatorTrait.php index b62ec3e53..74dfa4362 100644 --- a/deps/vendor/symfony/service-contracts/ServiceLocatorTrait.php +++ b/deps/vendor/symfony/service-contracts/ServiceLocatorTrait.php @@ -26,24 +26,34 @@ class_exists(NotFoundExceptionInterface::class); */ trait ServiceLocatorTrait { - private array $factories; - private array $loading = []; - private array $providedTypes; + private $factories; + private $loading = []; + private $providedTypes; /** - * @param array $factories + * @param callable[] $factories */ public function __construct(array $factories) { $this->factories = $factories; } - public function has(string $id): bool + /** + * {@inheritdoc} + * + * @return bool + */ + public function has(string $id) { return isset($this->factories[$id]); } - public function get(string $id): mixed + /** + * {@inheritdoc} + * + * @return mixed + */ + public function get(string $id) { if (!isset($this->factories[$id])) { throw $this->createNotFoundException($id); @@ -65,9 +75,12 @@ public function get(string $id): mixed } } + /** + * {@inheritdoc} + */ public function getProvidedServices(): array { - if (!isset($this->providedTypes)) { + if (null === $this->providedTypes) { $this->providedTypes = []; foreach ($this->factories as $name => $factory) { diff --git a/deps/vendor/symfony/service-contracts/ServiceMethodsSubscriberTrait.php b/deps/vendor/symfony/service-contracts/ServiceMethodsSubscriberTrait.php deleted file mode 100644 index 0d89d9f25..000000000 --- a/deps/vendor/symfony/service-contracts/ServiceMethodsSubscriberTrait.php +++ /dev/null @@ -1,80 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Contracts\Service; - -use Psr\Container\ContainerInterface; -use Symfony\Contracts\Service\Attribute\Required; -use Symfony\Contracts\Service\Attribute\SubscribedService; - -/** - * Implementation of ServiceSubscriberInterface that determines subscribed services - * from methods that have the #[SubscribedService] attribute. - * - * Service ids are available as "ClassName::methodName" so that the implementation - * of subscriber methods can be just `return $this->container->get(__METHOD__);`. - * - * @author Kevin Bond - */ -trait ServiceMethodsSubscriberTrait -{ - protected ContainerInterface $container; - - public static function getSubscribedServices(): array - { - $services = method_exists(get_parent_class(self::class) ?: '', __FUNCTION__) ? parent::getSubscribedServices() : []; - - foreach ((new \ReflectionClass(self::class))->getMethods() as $method) { - if (self::class !== $method->getDeclaringClass()->name) { - continue; - } - - if (!$attribute = $method->getAttributes(SubscribedService::class)[0] ?? null) { - continue; - } - - if ($method->isStatic() || $method->isAbstract() || $method->isGenerator() || $method->isInternal() || $method->getNumberOfRequiredParameters()) { - throw new \LogicException(sprintf('Cannot use "%s" on method "%s::%s()" (can only be used on non-static, non-abstract methods with no parameters).', SubscribedService::class, self::class, $method->name)); - } - - if (!$returnType = $method->getReturnType()) { - throw new \LogicException(sprintf('Cannot use "%s" on methods without a return type in "%s::%s()".', SubscribedService::class, $method->name, self::class)); - } - - /* @var SubscribedService $attribute */ - $attribute = $attribute->newInstance(); - $attribute->key ??= self::class.'::'.$method->name; - $attribute->type ??= $returnType instanceof \ReflectionNamedType ? $returnType->getName() : (string) $returnType; - $attribute->nullable = $returnType->allowsNull(); - - if ($attribute->attributes) { - $services[] = $attribute; - } else { - $services[$attribute->key] = ($attribute->nullable ? '?' : '').$attribute->type; - } - } - - return $services; - } - - #[Required] - public function setContainer(ContainerInterface $container): ?ContainerInterface - { - $ret = null; - if (method_exists(get_parent_class(self::class) ?: '', __FUNCTION__)) { - $ret = parent::setContainer($container); - } - - $this->container = $container; - - return $ret; - } -} diff --git a/deps/vendor/symfony/service-contracts/ServiceProviderInterface.php b/deps/vendor/symfony/service-contracts/ServiceProviderInterface.php index 2e71f00c6..c60ad0bd4 100644 --- a/deps/vendor/symfony/service-contracts/ServiceProviderInterface.php +++ b/deps/vendor/symfony/service-contracts/ServiceProviderInterface.php @@ -18,18 +18,9 @@ * * @author Nicolas Grekas * @author Mateusz Sip - * - * @template-covariant T of mixed */ interface ServiceProviderInterface extends ContainerInterface { - /** - * @return T - */ - public function get(string $id): mixed; - - public function has(string $id): bool; - /** * Returns an associative array of service types keyed by the identifiers provided by the current container. * @@ -39,7 +30,7 @@ public function has(string $id): bool; * * ['foo' => '?'] means the container provides service name "foo" of unspecified type * * ['bar' => '?Bar\Baz'] means the container provides a service "bar" of type Bar\Baz|null * - * @return array The provided service types, keyed by service names + * @return string[] The provided service types, keyed by service names */ public function getProvidedServices(): array; } diff --git a/deps/vendor/symfony/service-contracts/ServiceSubscriberInterface.php b/deps/vendor/symfony/service-contracts/ServiceSubscriberInterface.php index 3da19169b..098ab908c 100644 --- a/deps/vendor/symfony/service-contracts/ServiceSubscriberInterface.php +++ b/deps/vendor/symfony/service-contracts/ServiceSubscriberInterface.php @@ -11,8 +11,6 @@ namespace Symfony\Contracts\Service; -use Symfony\Contracts\Service\Attribute\SubscribedService; - /** * A ServiceSubscriber exposes its dependencies via the static {@link getSubscribedServices} method. * @@ -31,8 +29,7 @@ interface ServiceSubscriberInterface { /** - * Returns an array of service types (or {@see SubscribedService} objects) required - * by such instances, optionally keyed by the service names used internally. + * Returns an array of service types required by such instances, optionally keyed by the service names used internally. * * For mandatory dependencies: * @@ -50,13 +47,7 @@ interface ServiceSubscriberInterface * * ['?Psr\Log\LoggerInterface'] is a shortcut for * * ['Psr\Log\LoggerInterface' => '?Psr\Log\LoggerInterface'] * - * additionally, an array of {@see SubscribedService}'s can be returned: - * - * * [new SubscribedService('logger', Psr\Log\LoggerInterface::class)] - * * [new SubscribedService(type: Psr\Log\LoggerInterface::class, nullable: true)] - * * [new SubscribedService('http_client', HttpClientInterface::class, attributes: new Target('githubApi'))] - * - * @return string[]|SubscribedService[] The required service types, optionally keyed by service names + * @return string[] The required service types, optionally keyed by service names */ - public static function getSubscribedServices(): array; + public static function getSubscribedServices(); } diff --git a/deps/vendor/symfony/service-contracts/ServiceSubscriberTrait.php b/deps/vendor/symfony/service-contracts/ServiceSubscriberTrait.php index cc3bc321a..46cd007b7 100644 --- a/deps/vendor/symfony/service-contracts/ServiceSubscriberTrait.php +++ b/deps/vendor/symfony/service-contracts/ServiceSubscriberTrait.php @@ -12,73 +12,104 @@ namespace Symfony\Contracts\Service; use Psr\Container\ContainerInterface; -use Symfony\Contracts\Service\Attribute\Required; use Symfony\Contracts\Service\Attribute\SubscribedService; -trigger_deprecation('symfony/contracts', 'v3.5', '"%s" is deprecated, use "ServiceMethodsSubscriberTrait" instead.', ServiceSubscriberTrait::class); - /** - * Implementation of ServiceSubscriberInterface that determines subscribed services - * from methods that have the #[SubscribedService] attribute. - * - * Service ids are available as "ClassName::methodName" so that the implementation - * of subscriber methods can be just `return $this->container->get(__METHOD__);`. - * - * @property ContainerInterface $container + * Implementation of ServiceSubscriberInterface that determines subscribed services from + * method return types. Service ids are available as "ClassName::methodName". * * @author Kevin Bond - * - * @deprecated since symfony/contracts v3.5, use ServiceMethodsSubscriberTrait instead */ trait ServiceSubscriberTrait { + /** @var ContainerInterface */ + protected $container; + + /** + * {@inheritdoc} + */ public static function getSubscribedServices(): array { - $services = method_exists(get_parent_class(self::class) ?: '', __FUNCTION__) ? parent::getSubscribedServices() : []; + static $services; - foreach ((new \ReflectionClass(self::class))->getMethods() as $method) { - if (self::class !== $method->getDeclaringClass()->name) { - continue; - } + if (null !== $services) { + return $services; + } - if (!$attribute = $method->getAttributes(SubscribedService::class)[0] ?? null) { - continue; - } + $services = \is_callable(['parent', __FUNCTION__]) ? parent::getSubscribedServices() : []; + $attributeOptIn = false; - if ($method->isStatic() || $method->isAbstract() || $method->isGenerator() || $method->isInternal() || $method->getNumberOfRequiredParameters()) { - throw new \LogicException(sprintf('Cannot use "%s" on method "%s::%s()" (can only be used on non-static, non-abstract methods with no parameters).', SubscribedService::class, self::class, $method->name)); - } + if (\PHP_VERSION_ID >= 80000) { + foreach ((new \ReflectionClass(self::class))->getMethods() as $method) { + if (self::class !== $method->getDeclaringClass()->name) { + continue; + } + + if (!$attribute = $method->getAttributes(SubscribedService::class)[0] ?? null) { + continue; + } + + if ($method->isStatic() || $method->isAbstract() || $method->isGenerator() || $method->isInternal() || $method->getNumberOfRequiredParameters()) { + throw new \LogicException(sprintf('Cannot use "%s" on method "%s::%s()" (can only be used on non-static, non-abstract methods with no parameters).', SubscribedService::class, self::class, $method->name)); + } + + if (!$returnType = $method->getReturnType()) { + throw new \LogicException(sprintf('Cannot use "%s" on methods without a return type in "%s::%s()".', SubscribedService::class, $method->name, self::class)); + } - if (!$returnType = $method->getReturnType()) { - throw new \LogicException(sprintf('Cannot use "%s" on methods without a return type in "%s::%s()".', SubscribedService::class, $method->name, self::class)); + $serviceId = $returnType instanceof \ReflectionNamedType ? $returnType->getName() : (string) $returnType; + + if ($returnType->allowsNull()) { + $serviceId = '?'.$serviceId; + } + + $services[$attribute->newInstance()->key ?? self::class.'::'.$method->name] = $serviceId; + $attributeOptIn = true; } + } + + if (!$attributeOptIn) { + foreach ((new \ReflectionClass(self::class))->getMethods() as $method) { + if ($method->isStatic() || $method->isAbstract() || $method->isGenerator() || $method->isInternal() || $method->getNumberOfRequiredParameters()) { + continue; + } + + if (self::class !== $method->getDeclaringClass()->name) { + continue; + } + + if (!($returnType = $method->getReturnType()) instanceof \ReflectionNamedType) { + continue; + } - /* @var SubscribedService $attribute */ - $attribute = $attribute->newInstance(); - $attribute->key ??= self::class.'::'.$method->name; - $attribute->type ??= $returnType instanceof \ReflectionNamedType ? $returnType->getName() : (string) $returnType; - $attribute->nullable = $returnType->allowsNull(); + if ($returnType->isBuiltin()) { + continue; + } - if ($attribute->attributes) { - $services[] = $attribute; - } else { - $services[$attribute->key] = ($attribute->nullable ? '?' : '').$attribute->type; + if (\PHP_VERSION_ID >= 80000) { + trigger_deprecation('symfony/service-contracts', '2.5', 'Using "%s" in "%s" without using the "%s" attribute on any method is deprecated.', ServiceSubscriberTrait::class, self::class, SubscribedService::class); + } + + $services[self::class.'::'.$method->name] = '?'.($returnType instanceof \ReflectionNamedType ? $returnType->getName() : $returnType); } } return $services; } - #[Required] - public function setContainer(ContainerInterface $container): ?ContainerInterface + /** + * @required + * + * @return ContainerInterface|null + */ + public function setContainer(ContainerInterface $container) { - $ret = null; - if (method_exists(get_parent_class(self::class) ?: '', __FUNCTION__)) { - $ret = parent::setContainer($container); - } - $this->container = $container; - return $ret; + if (\is_callable(['parent', __FUNCTION__])) { + return parent::setContainer($container); + } + + return null; } } diff --git a/deps/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php b/deps/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php index 07d12b4a5..2a1b565f5 100644 --- a/deps/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php +++ b/deps/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php @@ -11,13 +11,85 @@ namespace Symfony\Contracts\Service\Test; -class_alias(ServiceLocatorTestCase::class, ServiceLocatorTest::class); +use PHPUnit\Framework\TestCase; +use Psr\Container\ContainerInterface; +use Symfony\Contracts\Service\ServiceLocatorTrait; -if (false) { +abstract class ServiceLocatorTest extends TestCase +{ /** - * @deprecated since PHPUnit 9.6 + * @return ContainerInterface */ - class ServiceLocatorTest + protected function getServiceLocator(array $factories) { + return new class($factories) implements ContainerInterface { + use ServiceLocatorTrait; + }; + } + + public function testHas() + { + $locator = $this->getServiceLocator([ + 'foo' => function () { return 'bar'; }, + 'bar' => function () { return 'baz'; }, + function () { return 'dummy'; }, + ]); + + $this->assertTrue($locator->has('foo')); + $this->assertTrue($locator->has('bar')); + $this->assertFalse($locator->has('dummy')); + } + + public function testGet() + { + $locator = $this->getServiceLocator([ + 'foo' => function () { return 'bar'; }, + 'bar' => function () { return 'baz'; }, + ]); + + $this->assertSame('bar', $locator->get('foo')); + $this->assertSame('baz', $locator->get('bar')); + } + + public function testGetDoesNotMemoize() + { + $i = 0; + $locator = $this->getServiceLocator([ + 'foo' => function () use (&$i) { + ++$i; + + return 'bar'; + }, + ]); + + $this->assertSame('bar', $locator->get('foo')); + $this->assertSame('bar', $locator->get('foo')); + $this->assertSame(2, $i); + } + + public function testThrowsOnUndefinedInternalService() + { + if (!$this->getExpectedException()) { + $this->expectException(\Psr\Container\NotFoundExceptionInterface::class); + $this->expectExceptionMessage('The service "foo" has a dependency on a non-existent service "bar". This locator only knows about the "foo" service.'); + } + $locator = $this->getServiceLocator([ + 'foo' => function () use (&$locator) { return $locator->get('bar'); }, + ]); + + $locator->get('foo'); + } + + public function testThrowsOnCircularReference() + { + $this->expectException(\Psr\Container\ContainerExceptionInterface::class); + $this->expectExceptionMessage('Circular reference detected for service "bar", path: "bar -> baz -> bar".'); + $locator = $this->getServiceLocator([ + 'foo' => function () use (&$locator) { return $locator->get('bar'); }, + 'bar' => function () use (&$locator) { return $locator->get('baz'); }, + 'baz' => function () use (&$locator) { return $locator->get('bar'); }, + ]); + + $locator->get('foo'); } } diff --git a/deps/vendor/symfony/service-contracts/Test/ServiceLocatorTestCase.php b/deps/vendor/symfony/service-contracts/Test/ServiceLocatorTestCase.php deleted file mode 100644 index 65a3fe337..000000000 --- a/deps/vendor/symfony/service-contracts/Test/ServiceLocatorTestCase.php +++ /dev/null @@ -1,96 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Contracts\Service\Test; - -use PHPUnit\Framework\TestCase; -use Psr\Container\ContainerExceptionInterface; -use Psr\Container\ContainerInterface; -use Psr\Container\NotFoundExceptionInterface; -use Symfony\Contracts\Service\ServiceLocatorTrait; - -abstract class ServiceLocatorTestCase extends TestCase -{ - protected function getServiceLocator(array $factories): ContainerInterface - { - return new class($factories) implements ContainerInterface { - use ServiceLocatorTrait; - }; - } - - public function testHas() - { - $locator = $this->getServiceLocator([ - 'foo' => fn () => 'bar', - 'bar' => fn () => 'baz', - fn () => 'dummy', - ]); - - $this->assertTrue($locator->has('foo')); - $this->assertTrue($locator->has('bar')); - $this->assertFalse($locator->has('dummy')); - } - - public function testGet() - { - $locator = $this->getServiceLocator([ - 'foo' => fn () => 'bar', - 'bar' => fn () => 'baz', - ]); - - $this->assertSame('bar', $locator->get('foo')); - $this->assertSame('baz', $locator->get('bar')); - } - - public function testGetDoesNotMemoize() - { - $i = 0; - $locator = $this->getServiceLocator([ - 'foo' => function () use (&$i) { - ++$i; - - return 'bar'; - }, - ]); - - $this->assertSame('bar', $locator->get('foo')); - $this->assertSame('bar', $locator->get('foo')); - $this->assertSame(2, $i); - } - - public function testThrowsOnUndefinedInternalService() - { - $locator = $this->getServiceLocator([ - 'foo' => function () use (&$locator) { return $locator->get('bar'); }, - ]); - - if (!$this->getExpectedException()) { - $this->expectException(NotFoundExceptionInterface::class); - $this->expectExceptionMessage('The service "foo" has a dependency on a non-existent service "bar". This locator only knows about the "foo" service.'); - } - - $locator->get('foo'); - } - - public function testThrowsOnCircularReference() - { - $locator = $this->getServiceLocator([ - 'foo' => function () use (&$locator) { return $locator->get('bar'); }, - 'bar' => function () use (&$locator) { return $locator->get('baz'); }, - 'baz' => function () use (&$locator) { return $locator->get('bar'); }, - ]); - - $this->expectException(ContainerExceptionInterface::class); - $this->expectExceptionMessage('Circular reference detected for service "bar", path: "bar -> baz -> bar".'); - - $locator->get('foo'); - } -} diff --git a/deps/vendor/symfony/service-contracts/composer.json b/deps/vendor/symfony/service-contracts/composer.json index fc8674a72..e680798d7 100644 --- a/deps/vendor/symfony/service-contracts/composer.json +++ b/deps/vendor/symfony/service-contracts/composer.json @@ -16,23 +16,23 @@ } ], "require": { - "php": ">=8.1", - "psr/container": "^1.1|^2.0", - "symfony/deprecation-contracts": "^2.5|^3" + "php": ">=7.2.5", + "psr/container": "^1.1", + "symfony/deprecation-contracts": "^2.1" }, "conflict": { "ext-psr": "<1.1|>=2" }, + "suggest": { + "symfony/service-implementation": "" + }, "autoload": { - "psr-4": { "Symfony\\Contracts\\Service\\": "" }, - "exclude-from-classmap": [ - "/Test/" - ] + "psr-4": { "Symfony\\Contracts\\Service\\": "" } }, "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-main": "3.5-dev" + "dev-main": "2.5-dev" }, "thanks": { "name": "symfony/contracts", diff --git a/deps/vendor/symfony/string/AbstractString.php b/deps/vendor/symfony/string/AbstractString.php index f55c72161..cf21fef1f 100644 --- a/deps/vendor/symfony/string/AbstractString.php +++ b/deps/vendor/symfony/string/AbstractString.php @@ -74,7 +74,7 @@ public static function wrap(array $values): array foreach ($values as $k => $v) { if (\is_string($k) && '' !== $k && $k !== $j = (string) new static($k)) { - $keys ??= array_keys($values); + $keys = $keys ?? array_keys($values); $keys[$i] = $j; } @@ -92,17 +92,15 @@ public static function wrap(array $values): array /** * @param string|string[] $needle + * + * @return static */ - public function after(string|iterable $needle, bool $includeNeedle = false, int $offset = 0): static + public function after($needle, bool $includeNeedle = false, int $offset = 0): self { $str = clone $this; $i = \PHP_INT_MAX; - if (\is_string($needle)) { - $needle = [$needle]; - } - - foreach ($needle as $n) { + foreach ((array) $needle as $n) { $n = (string) $n; $j = $this->indexOf($n, $offset); @@ -125,17 +123,15 @@ public function after(string|iterable $needle, bool $includeNeedle = false, int /** * @param string|string[] $needle + * + * @return static */ - public function afterLast(string|iterable $needle, bool $includeNeedle = false, int $offset = 0): static + public function afterLast($needle, bool $includeNeedle = false, int $offset = 0): self { $str = clone $this; $i = null; - if (\is_string($needle)) { - $needle = [$needle]; - } - - foreach ($needle as $n) { + foreach ((array) $needle as $n) { $n = (string) $n; $j = $this->indexOfLast($n, $offset); @@ -156,21 +152,22 @@ public function afterLast(string|iterable $needle, bool $includeNeedle = false, return $this->slice($i); } - abstract public function append(string ...$suffix): static; + /** + * @return static + */ + abstract public function append(string ...$suffix): self; /** * @param string|string[] $needle + * + * @return static */ - public function before(string|iterable $needle, bool $includeNeedle = false, int $offset = 0): static + public function before($needle, bool $includeNeedle = false, int $offset = 0): self { $str = clone $this; $i = \PHP_INT_MAX; - if (\is_string($needle)) { - $needle = [$needle]; - } - - foreach ($needle as $n) { + foreach ((array) $needle as $n) { $n = (string) $n; $j = $this->indexOf($n, $offset); @@ -193,17 +190,15 @@ public function before(string|iterable $needle, bool $includeNeedle = false, int /** * @param string|string[] $needle + * + * @return static */ - public function beforeLast(string|iterable $needle, bool $includeNeedle = false, int $offset = 0): static + public function beforeLast($needle, bool $includeNeedle = false, int $offset = 0): self { $str = clone $this; $i = null; - if (\is_string($needle)) { - $needle = [$needle]; - } - - foreach ($needle as $n) { + foreach ((array) $needle as $n) { $n = (string) $n; $j = $this->indexOfLast($n, $offset); @@ -234,17 +229,23 @@ public function bytesAt(int $offset): array return '' === $str->string ? [] : array_values(unpack('C*', $str->string)); } - abstract public function camel(): static; + /** + * @return static + */ + abstract public function camel(): self; /** * @return static[] */ abstract public function chunk(int $length = 1): array; - public function collapseWhitespace(): static + /** + * @return static + */ + public function collapseWhitespace(): self { $str = clone $this; - $str->string = trim(preg_replace("/(?:[ \n\r\t\x0C]{2,}+|[\n\r\t\x0C])/", ' ', $str->string), " \n\r\t\x0C"); + $str->string = trim(preg_replace('/(?:\s{2,}+|[^\S ])/', ' ', $str->string)); return $str; } @@ -252,7 +253,7 @@ public function collapseWhitespace(): static /** * @param string|string[] $needle */ - public function containsAny(string|iterable $needle): bool + public function containsAny($needle): bool { return null !== $this->indexOf($needle); } @@ -260,9 +261,9 @@ public function containsAny(string|iterable $needle): bool /** * @param string|string[] $suffix */ - public function endsWith(string|iterable $suffix): bool + public function endsWith($suffix): bool { - if (\is_string($suffix)) { + if (!\is_array($suffix) && !$suffix instanceof \Traversable) { throw new \TypeError(sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class)); } @@ -275,7 +276,10 @@ public function endsWith(string|iterable $suffix): bool return false; } - public function ensureEnd(string $suffix): static + /** + * @return static + */ + public function ensureEnd(string $suffix): self { if (!$this->endsWith($suffix)) { return $this->append($suffix); @@ -287,7 +291,10 @@ public function ensureEnd(string $suffix): static return $this->replaceMatches($regex.($this->ignoreCase ? 'i' : ''), '$1'); } - public function ensureStart(string $prefix): static + /** + * @return static + */ + public function ensureStart(string $prefix): self { $prefix = new static($prefix); @@ -309,9 +316,9 @@ public function ensureStart(string $prefix): static /** * @param string|string[] $string */ - public function equalsTo(string|iterable $string): bool + public function equalsTo($string): bool { - if (\is_string($string)) { + if (!\is_array($string) && !$string instanceof \Traversable) { throw new \TypeError(sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class)); } @@ -324,9 +331,15 @@ public function equalsTo(string|iterable $string): bool return false; } - abstract public function folded(): static; + /** + * @return static + */ + abstract public function folded(): self; - public function ignoreCase(): static + /** + * @return static + */ + public function ignoreCase(): self { $str = clone $this; $str->ignoreCase = true; @@ -337,9 +350,9 @@ public function ignoreCase(): static /** * @param string|string[] $needle */ - public function indexOf(string|iterable $needle, int $offset = 0): ?int + public function indexOf($needle, int $offset = 0): ?int { - if (\is_string($needle)) { + if (!\is_array($needle) && !$needle instanceof \Traversable) { throw new \TypeError(sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class)); } @@ -359,9 +372,9 @@ public function indexOf(string|iterable $needle, int $offset = 0): ?int /** * @param string|string[] $needle */ - public function indexOfLast(string|iterable $needle, int $offset = 0): ?int + public function indexOfLast($needle, int $offset = 0): ?int { - if (\is_string($needle)) { + if (!\is_array($needle) && !$needle instanceof \Traversable) { throw new \TypeError(sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class)); } @@ -383,7 +396,10 @@ public function isEmpty(): bool return '' === $this->string; } - abstract public function join(array $strings, ?string $lastGlue = null): static; + /** + * @return static + */ + abstract public function join(array $strings, string $lastGlue = null): self; public function jsonSerialize(): string { @@ -392,7 +408,10 @@ public function jsonSerialize(): string abstract public function length(): int; - abstract public function lower(): static; + /** + * @return static + */ + abstract public function lower(): self; /** * Matches the string using a regular expression. @@ -403,15 +422,30 @@ abstract public function lower(): static; */ abstract public function match(string $regexp, int $flags = 0, int $offset = 0): array; - abstract public function padBoth(int $length, string $padStr = ' '): static; + /** + * @return static + */ + abstract public function padBoth(int $length, string $padStr = ' '): self; - abstract public function padEnd(int $length, string $padStr = ' '): static; + /** + * @return static + */ + abstract public function padEnd(int $length, string $padStr = ' '): self; - abstract public function padStart(int $length, string $padStr = ' '): static; + /** + * @return static + */ + abstract public function padStart(int $length, string $padStr = ' '): self; - abstract public function prepend(string ...$prefix): static; + /** + * @return static + */ + abstract public function prepend(string ...$prefix): self; - public function repeat(int $multiplier): static + /** + * @return static + */ + public function repeat(int $multiplier): self { if (0 > $multiplier) { throw new InvalidArgumentException(sprintf('Multiplier must be positive, %d given.', $multiplier)); @@ -423,22 +457,42 @@ public function repeat(int $multiplier): static return $str; } - abstract public function replace(string $from, string $to): static; + /** + * @return static + */ + abstract public function replace(string $from, string $to): self; - abstract public function replaceMatches(string $fromRegexp, string|callable $to): static; + /** + * @param string|callable $to + * + * @return static + */ + abstract public function replaceMatches(string $fromRegexp, $to): self; - abstract public function reverse(): static; + /** + * @return static + */ + abstract public function reverse(): self; - abstract public function slice(int $start = 0, ?int $length = null): static; + /** + * @return static + */ + abstract public function slice(int $start = 0, int $length = null): self; - abstract public function snake(): static; + /** + * @return static + */ + abstract public function snake(): self; - abstract public function splice(string $replacement, int $start = 0, ?int $length = null): static; + /** + * @return static + */ + abstract public function splice(string $replacement, int $start = 0, int $length = null): self; /** * @return static[] */ - public function split(string $delimiter, ?int $limit = null, ?int $flags = null): array + public function split(string $delimiter, int $limit = null, int $flags = null): array { if (null === $flags) { throw new \TypeError('Split behavior when $flags is null must be implemented by child classes.'); @@ -448,11 +502,19 @@ public function split(string $delimiter, ?int $limit = null, ?int $flags = null) $delimiter .= 'i'; } - set_error_handler(static fn ($t, $m) => throw new InvalidArgumentException($m)); + set_error_handler(static function ($t, $m) { throw new InvalidArgumentException($m); }); try { if (false === $chunks = preg_split($delimiter, $this->string, $limit, $flags)) { - throw new RuntimeException('Splitting failed with error: '.preg_last_error_msg()); + $lastError = preg_last_error(); + + foreach (get_defined_constants(true)['pcre'] as $k => $v) { + if ($lastError === $v && '_ERROR' === substr($k, -6)) { + throw new RuntimeException('Splitting failed with '.$k.'.'); + } + } + + throw new RuntimeException('Splitting failed with unknown error code.'); } } finally { restore_error_handler(); @@ -478,9 +540,9 @@ public function split(string $delimiter, ?int $limit = null, ?int $flags = null) /** * @param string|string[] $prefix */ - public function startsWith(string|iterable $prefix): bool + public function startsWith($prefix): bool { - if (\is_string($prefix)) { + if (!\is_array($prefix) && !$prefix instanceof \Traversable) { throw new \TypeError(sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class)); } @@ -493,9 +555,12 @@ public function startsWith(string|iterable $prefix): bool return false; } - abstract public function title(bool $allWords = false): static; + /** + * @return static + */ + abstract public function title(bool $allWords = false): self; - public function toByteString(?string $toEncoding = null): ByteString + public function toByteString(string $toEncoding = null): ByteString { $b = new ByteString(); @@ -507,14 +572,20 @@ public function toByteString(?string $toEncoding = null): ByteString return $b; } + set_error_handler(static function ($t, $m) { throw new InvalidArgumentException($m); }); + try { - $b->string = mb_convert_encoding($this->string, $toEncoding, 'UTF-8'); - } catch (\ValueError $e) { - if (!\function_exists('iconv')) { - throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); - } + try { + $b->string = mb_convert_encoding($this->string, $toEncoding, 'UTF-8'); + } catch (InvalidArgumentException $e) { + if (!\function_exists('iconv')) { + throw $e; + } - $b->string = iconv('UTF-8', $toEncoding, $this->string); + $b->string = iconv('UTF-8', $toEncoding, $this->string); + } + } finally { + restore_error_handler(); } return $b; @@ -535,16 +606,24 @@ public function toUnicodeString(): UnicodeString return new UnicodeString($this->string); } - abstract public function trim(string $chars = " \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}"): static; + /** + * @return static + */ + abstract public function trim(string $chars = " \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}"): self; - abstract public function trimEnd(string $chars = " \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}"): static; + /** + * @return static + */ + abstract public function trimEnd(string $chars = " \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}"): self; /** * @param string|string[] $prefix + * + * @return static */ - public function trimPrefix($prefix): static + public function trimPrefix($prefix): self { - if (\is_array($prefix) || $prefix instanceof \Traversable) { // don't use is_iterable(), it's slow + if (\is_array($prefix) || $prefix instanceof \Traversable) { foreach ($prefix as $s) { $t = $this->trimPrefix($s); @@ -571,14 +650,19 @@ public function trimPrefix($prefix): static return $str; } - abstract public function trimStart(string $chars = " \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}"): static; + /** + * @return static + */ + abstract public function trimStart(string $chars = " \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}"): self; /** * @param string|string[] $suffix + * + * @return static */ - public function trimSuffix($suffix): static + public function trimSuffix($suffix): self { - if (\is_array($suffix) || $suffix instanceof \Traversable) { // don't use is_iterable(), it's slow + if (\is_array($suffix) || $suffix instanceof \Traversable) { foreach ($suffix as $s) { $t = $this->trimSuffix($s); @@ -605,7 +689,10 @@ public function trimSuffix($suffix): static return $str; } - public function truncate(int $length, string $ellipsis = '', bool $cut = true): static + /** + * @return static + */ + public function truncate(int $length, string $ellipsis = '', bool $cut = true): self { $stringLength = $this->length(); @@ -632,14 +719,20 @@ public function truncate(int $length, string $ellipsis = '', bool $cut = true): return $ellipsisLength ? $str->trimEnd()->append($ellipsis) : $str; } - abstract public function upper(): static; + /** + * @return static + */ + abstract public function upper(): self; /** * Returns the printable length on a terminal. */ abstract public function width(bool $ignoreAnsiDecoration = true): int; - public function wordwrap(int $width = 75, string $break = "\n", bool $cut = false): static + /** + * @return static + */ + public function wordwrap(int $width = 75, string $break = "\n", bool $cut = false): self { $lines = '' !== $break ? $this->split($break) : [clone $this]; $chars = []; diff --git a/deps/vendor/symfony/string/AbstractUnicodeString.php b/deps/vendor/symfony/string/AbstractUnicodeString.php index 70598e409..db810cb6d 100644 --- a/deps/vendor/symfony/string/AbstractUnicodeString.php +++ b/deps/vendor/symfony/string/AbstractUnicodeString.php @@ -37,18 +37,25 @@ abstract class AbstractUnicodeString extends AbstractString private const ASCII = "\x20\x65\x69\x61\x73\x6E\x74\x72\x6F\x6C\x75\x64\x5D\x5B\x63\x6D\x70\x27\x0A\x67\x7C\x68\x76\x2E\x66\x62\x2C\x3A\x3D\x2D\x71\x31\x30\x43\x32\x2A\x79\x78\x29\x28\x4C\x39\x41\x53\x2F\x50\x22\x45\x6A\x4D\x49\x6B\x33\x3E\x35\x54\x3C\x44\x34\x7D\x42\x7B\x38\x46\x77\x52\x36\x37\x55\x47\x4E\x3B\x4A\x7A\x56\x23\x48\x4F\x57\x5F\x26\x21\x4B\x3F\x58\x51\x25\x59\x5C\x09\x5A\x2B\x7E\x5E\x24\x40\x60\x7F\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"; // the subset of folded case mappings that is not in lower case mappings - private const FOLD_FROM = ['İ', 'µ', 'ſ', "\xCD\x85", 'ς', 'ϐ', 'ϑ', 'ϕ', 'ϖ', 'ϰ', 'ϱ', 'ϵ', 'ẛ', "\xE1\xBE\xBE", 'ß', 'ʼn', 'ǰ', 'ΐ', 'ΰ', 'և', 'ẖ', 'ẗ', 'ẘ', 'ẙ', 'ẚ', 'ẞ', 'ὐ', 'ὒ', 'ὔ', 'ὖ', 'ᾀ', 'ᾁ', 'ᾂ', 'ᾃ', 'ᾄ', 'ᾅ', 'ᾆ', 'ᾇ', 'ᾈ', 'ᾉ', 'ᾊ', 'ᾋ', 'ᾌ', 'ᾍ', 'ᾎ', 'ᾏ', 'ᾐ', 'ᾑ', 'ᾒ', 'ᾓ', 'ᾔ', 'ᾕ', 'ᾖ', 'ᾗ', 'ᾘ', 'ᾙ', 'ᾚ', 'ᾛ', 'ᾜ', 'ᾝ', 'ᾞ', 'ᾟ', 'ᾠ', 'ᾡ', 'ᾢ', 'ᾣ', 'ᾤ', 'ᾥ', 'ᾦ', 'ᾧ', 'ᾨ', 'ᾩ', 'ᾪ', 'ᾫ', 'ᾬ', 'ᾭ', 'ᾮ', 'ᾯ', 'ᾲ', 'ᾳ', 'ᾴ', 'ᾶ', 'ᾷ', 'ᾼ', 'ῂ', 'ῃ', 'ῄ', 'ῆ', 'ῇ', 'ῌ', 'ῒ', 'ῖ', 'ῗ', 'ῢ', 'ῤ', 'ῦ', 'ῧ', 'ῲ', 'ῳ', 'ῴ', 'ῶ', 'ῷ', 'ῼ', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'ſt', 'st', 'ﬓ', 'ﬔ', 'ﬕ', 'ﬖ', 'ﬗ']; - private const FOLD_TO = ['i̇', 'μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', 'ṡ', 'ι', 'ss', 'ʼn', 'ǰ', 'ΐ', 'ΰ', 'եւ', 'ẖ', 'ẗ', 'ẘ', 'ẙ', 'aʾ', 'ss', 'ὐ', 'ὒ', 'ὔ', 'ὖ', 'ἀι', 'ἁι', 'ἂι', 'ἃι', 'ἄι', 'ἅι', 'ἆι', 'ἇι', 'ἀι', 'ἁι', 'ἂι', 'ἃι', 'ἄι', 'ἅι', 'ἆι', 'ἇι', 'ἠι', 'ἡι', 'ἢι', 'ἣι', 'ἤι', 'ἥι', 'ἦι', 'ἧι', 'ἠι', 'ἡι', 'ἢι', 'ἣι', 'ἤι', 'ἥι', 'ἦι', 'ἧι', 'ὠι', 'ὡι', 'ὢι', 'ὣι', 'ὤι', 'ὥι', 'ὦι', 'ὧι', 'ὠι', 'ὡι', 'ὢι', 'ὣι', 'ὤι', 'ὥι', 'ὦι', 'ὧι', 'ὰι', 'αι', 'άι', 'ᾶ', 'ᾶι', 'αι', 'ὴι', 'ηι', 'ήι', 'ῆ', 'ῆι', 'ηι', 'ῒ', 'ῖ', 'ῗ', 'ῢ', 'ῤ', 'ῦ', 'ῧ', 'ὼι', 'ωι', 'ώι', 'ῶ', 'ῶι', 'ωι', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'st', 'st', 'մն', 'մե', 'մի', 'վն', 'մխ']; + private const FOLD_FROM = ['İ', 'µ', 'ſ', "\xCD\x85", 'ς', 'ϐ', 'ϑ', 'ϕ', 'ϖ', 'ϰ', 'ϱ', 'ϵ', 'ẛ', "\xE1\xBE\xBE", 'ß', 'İ', 'ʼn', 'ǰ', 'ΐ', 'ΰ', 'և', 'ẖ', 'ẗ', 'ẘ', 'ẙ', 'ẚ', 'ẞ', 'ὐ', 'ὒ', 'ὔ', 'ὖ', 'ᾀ', 'ᾁ', 'ᾂ', 'ᾃ', 'ᾄ', 'ᾅ', 'ᾆ', 'ᾇ', 'ᾈ', 'ᾉ', 'ᾊ', 'ᾋ', 'ᾌ', 'ᾍ', 'ᾎ', 'ᾏ', 'ᾐ', 'ᾑ', 'ᾒ', 'ᾓ', 'ᾔ', 'ᾕ', 'ᾖ', 'ᾗ', 'ᾘ', 'ᾙ', 'ᾚ', 'ᾛ', 'ᾜ', 'ᾝ', 'ᾞ', 'ᾟ', 'ᾠ', 'ᾡ', 'ᾢ', 'ᾣ', 'ᾤ', 'ᾥ', 'ᾦ', 'ᾧ', 'ᾨ', 'ᾩ', 'ᾪ', 'ᾫ', 'ᾬ', 'ᾭ', 'ᾮ', 'ᾯ', 'ᾲ', 'ᾳ', 'ᾴ', 'ᾶ', 'ᾷ', 'ᾼ', 'ῂ', 'ῃ', 'ῄ', 'ῆ', 'ῇ', 'ῌ', 'ῒ', 'ΐ', 'ῖ', 'ῗ', 'ῢ', 'ΰ', 'ῤ', 'ῦ', 'ῧ', 'ῲ', 'ῳ', 'ῴ', 'ῶ', 'ῷ', 'ῼ', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'ſt', 'st', 'ﬓ', 'ﬔ', 'ﬕ', 'ﬖ', 'ﬗ']; + private const FOLD_TO = ['i̇', 'μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', 'ṡ', 'ι', 'ss', 'i̇', 'ʼn', 'ǰ', 'ΐ', 'ΰ', 'եւ', 'ẖ', 'ẗ', 'ẘ', 'ẙ', 'aʾ', 'ss', 'ὐ', 'ὒ', 'ὔ', 'ὖ', 'ἀι', 'ἁι', 'ἂι', 'ἃι', 'ἄι', 'ἅι', 'ἆι', 'ἇι', 'ἀι', 'ἁι', 'ἂι', 'ἃι', 'ἄι', 'ἅι', 'ἆι', 'ἇι', 'ἠι', 'ἡι', 'ἢι', 'ἣι', 'ἤι', 'ἥι', 'ἦι', 'ἧι', 'ἠι', 'ἡι', 'ἢι', 'ἣι', 'ἤι', 'ἥι', 'ἦι', 'ἧι', 'ὠι', 'ὡι', 'ὢι', 'ὣι', 'ὤι', 'ὥι', 'ὦι', 'ὧι', 'ὠι', 'ὡι', 'ὢι', 'ὣι', 'ὤι', 'ὥι', 'ὦι', 'ὧι', 'ὰι', 'αι', 'άι', 'ᾶ', 'ᾶι', 'αι', 'ὴι', 'ηι', 'ήι', 'ῆ', 'ῆι', 'ηι', 'ῒ', 'ΐ', 'ῖ', 'ῗ', 'ῢ', 'ΰ', 'ῤ', 'ῦ', 'ῧ', 'ὼι', 'ωι', 'ώι', 'ῶ', 'ῶι', 'ωι', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'st', 'st', 'մն', 'մե', 'մի', 'վն', 'մխ']; + + // the subset of upper case mappings that map one code point to many code points + private const UPPER_FROM = ['ß', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'ſt', 'st', 'և', 'ﬓ', 'ﬔ', 'ﬕ', 'ﬖ', 'ﬗ', 'ʼn', 'ΐ', 'ΰ', 'ǰ', 'ẖ', 'ẗ', 'ẘ', 'ẙ', 'ẚ', 'ὐ', 'ὒ', 'ὔ', 'ὖ', 'ᾶ', 'ῆ', 'ῒ', 'ΐ', 'ῖ', 'ῗ', 'ῢ', 'ΰ', 'ῤ', 'ῦ', 'ῧ', 'ῶ']; + private const UPPER_TO = ['SS', 'FF', 'FI', 'FL', 'FFI', 'FFL', 'ST', 'ST', 'ԵՒ', 'ՄՆ', 'ՄԵ', 'ՄԻ', 'ՎՆ', 'ՄԽ', 'ʼN', 'Ϊ́', 'Ϋ́', 'J̌', 'H̱', 'T̈', 'W̊', 'Y̊', 'Aʾ', 'Υ̓', 'Υ̓̀', 'Υ̓́', 'Υ̓͂', 'Α͂', 'Η͂', 'Ϊ̀', 'Ϊ́', 'Ι͂', 'Ϊ͂', 'Ϋ̀', 'Ϋ́', 'Ρ̓', 'Υ͂', 'Ϋ͂', 'Ω͂']; // the subset of https://github.com/unicode-org/cldr/blob/master/common/transforms/Latin-ASCII.xml that is not in NFKD private const TRANSLIT_FROM = ['Æ', 'Ð', 'Ø', 'Þ', 'ß', 'æ', 'ð', 'ø', 'þ', 'Đ', 'đ', 'Ħ', 'ħ', 'ı', 'ĸ', 'Ŀ', 'ŀ', 'Ł', 'ł', 'ʼn', 'Ŋ', 'ŋ', 'Œ', 'œ', 'Ŧ', 'ŧ', 'ƀ', 'Ɓ', 'Ƃ', 'ƃ', 'Ƈ', 'ƈ', 'Ɖ', 'Ɗ', 'Ƌ', 'ƌ', 'Ɛ', 'Ƒ', 'ƒ', 'Ɠ', 'ƕ', 'Ɩ', 'Ɨ', 'Ƙ', 'ƙ', 'ƚ', 'Ɲ', 'ƞ', 'Ƣ', 'ƣ', 'Ƥ', 'ƥ', 'ƫ', 'Ƭ', 'ƭ', 'Ʈ', 'Ʋ', 'Ƴ', 'ƴ', 'Ƶ', 'ƶ', 'DŽ', 'Dž', 'dž', 'Ǥ', 'ǥ', 'ȡ', 'Ȥ', 'ȥ', 'ȴ', 'ȵ', 'ȶ', 'ȷ', 'ȸ', 'ȹ', 'Ⱥ', 'Ȼ', 'ȼ', 'Ƚ', 'Ⱦ', 'ȿ', 'ɀ', 'Ƀ', 'Ʉ', 'Ɇ', 'ɇ', 'Ɉ', 'ɉ', 'Ɍ', 'ɍ', 'Ɏ', 'ɏ', 'ɓ', 'ɕ', 'ɖ', 'ɗ', 'ɛ', 'ɟ', 'ɠ', 'ɡ', 'ɢ', 'ɦ', 'ɧ', 'ɨ', 'ɪ', 'ɫ', 'ɬ', 'ɭ', 'ɱ', 'ɲ', 'ɳ', 'ɴ', 'ɶ', 'ɼ', 'ɽ', 'ɾ', 'ʀ', 'ʂ', 'ʈ', 'ʉ', 'ʋ', 'ʏ', 'ʐ', 'ʑ', 'ʙ', 'ʛ', 'ʜ', 'ʝ', 'ʟ', 'ʠ', 'ʣ', 'ʥ', 'ʦ', 'ʪ', 'ʫ', 'ᴀ', 'ᴁ', 'ᴃ', 'ᴄ', 'ᴅ', 'ᴆ', 'ᴇ', 'ᴊ', 'ᴋ', 'ᴌ', 'ᴍ', 'ᴏ', 'ᴘ', 'ᴛ', 'ᴜ', 'ᴠ', 'ᴡ', 'ᴢ', 'ᵫ', 'ᵬ', 'ᵭ', 'ᵮ', 'ᵯ', 'ᵰ', 'ᵱ', 'ᵲ', 'ᵳ', 'ᵴ', 'ᵵ', 'ᵶ', 'ᵺ', 'ᵻ', 'ᵽ', 'ᵾ', 'ᶀ', 'ᶁ', 'ᶂ', 'ᶃ', 'ᶄ', 'ᶅ', 'ᶆ', 'ᶇ', 'ᶈ', 'ᶉ', 'ᶊ', 'ᶌ', 'ᶍ', 'ᶎ', 'ᶏ', 'ᶑ', 'ᶒ', 'ᶓ', 'ᶖ', 'ᶙ', 'ẚ', 'ẜ', 'ẝ', 'ẞ', 'Ỻ', 'ỻ', 'Ỽ', 'ỽ', 'Ỿ', 'ỿ', '©', '®', '₠', '₢', '₣', '₤', '₧', '₺', '₹', 'ℌ', '℞', '㎧', '㎮', '㏆', '㏗', '㏞', '㏟', '¼', '½', '¾', '⅓', '⅔', '⅕', '⅖', '⅗', '⅘', '⅙', '⅚', '⅛', '⅜', '⅝', '⅞', '⅟', '〇', '‘', '’', '‚', '‛', '“', '”', '„', '‟', '′', '″', '〝', '〞', '«', '»', '‹', '›', '‐', '‑', '‒', '–', '—', '―', '︱', '︲', '﹘', '‖', '⁄', '⁅', '⁆', '⁎', '、', '。', '〈', '〉', '《', '》', '〔', '〕', '〘', '〙', '〚', '〛', '︑', '︒', '︹', '︺', '︽', '︾', '︿', '﹀', '﹑', '﹝', '﹞', '⦅', '⦆', '。', '、', '×', '÷', '−', '∕', '∖', '∣', '∥', '≪', '≫', '⦅', '⦆']; private const TRANSLIT_TO = ['AE', 'D', 'O', 'TH', 'ss', 'ae', 'd', 'o', 'th', 'D', 'd', 'H', 'h', 'i', 'q', 'L', 'l', 'L', 'l', '\'n', 'N', 'n', 'OE', 'oe', 'T', 't', 'b', 'B', 'B', 'b', 'C', 'c', 'D', 'D', 'D', 'd', 'E', 'F', 'f', 'G', 'hv', 'I', 'I', 'K', 'k', 'l', 'N', 'n', 'OI', 'oi', 'P', 'p', 't', 'T', 't', 'T', 'V', 'Y', 'y', 'Z', 'z', 'DZ', 'Dz', 'dz', 'G', 'g', 'd', 'Z', 'z', 'l', 'n', 't', 'j', 'db', 'qp', 'A', 'C', 'c', 'L', 'T', 's', 'z', 'B', 'U', 'E', 'e', 'J', 'j', 'R', 'r', 'Y', 'y', 'b', 'c', 'd', 'd', 'e', 'j', 'g', 'g', 'G', 'h', 'h', 'i', 'I', 'l', 'l', 'l', 'm', 'n', 'n', 'N', 'OE', 'r', 'r', 'r', 'R', 's', 't', 'u', 'v', 'Y', 'z', 'z', 'B', 'G', 'H', 'j', 'L', 'q', 'dz', 'dz', 'ts', 'ls', 'lz', 'A', 'AE', 'B', 'C', 'D', 'D', 'E', 'J', 'K', 'L', 'M', 'O', 'P', 'T', 'U', 'V', 'W', 'Z', 'ue', 'b', 'd', 'f', 'm', 'n', 'p', 'r', 'r', 's', 't', 'z', 'th', 'I', 'p', 'U', 'b', 'd', 'f', 'g', 'k', 'l', 'm', 'n', 'p', 'r', 's', 'v', 'x', 'z', 'a', 'd', 'e', 'e', 'i', 'u', 'a', 's', 's', 'SS', 'LL', 'll', 'V', 'v', 'Y', 'y', '(C)', '(R)', 'CE', 'Cr', 'Fr.', 'L.', 'Pts', 'TL', 'Rs', 'x', 'Rx', 'm/s', 'rad/s', 'C/kg', 'pH', 'V/m', 'A/m', ' 1/4', ' 1/2', ' 3/4', ' 1/3', ' 2/3', ' 1/5', ' 2/5', ' 3/5', ' 4/5', ' 1/6', ' 5/6', ' 1/8', ' 3/8', ' 5/8', ' 7/8', ' 1/', '0', '\'', '\'', ',', '\'', '"', '"', ',,', '"', '\'', '"', '"', '"', '<<', '>>', '<', '>', '-', '-', '-', '-', '-', '-', '-', '-', '-', '||', '/', '[', ']', '*', ',', '.', '<', '>', '<<', '>>', '[', ']', '[', ']', '[', ']', ',', '.', '[', ']', '<<', '>>', '<', '>', ',', '[', ']', '((', '))', '.', ',', '*', '/', '-', '/', '\\', '|', '||', '<<', '>>', '((', '))']; - private static array $transliterators = []; - private static array $tableZero; - private static array $tableWide; + private static $transliterators = []; + private static $tableZero; + private static $tableWide; - public static function fromCodePoints(int ...$codes): static + /** + * @return static + */ + public static function fromCodePoints(int ...$codes): self { $string = ''; @@ -117,10 +124,10 @@ public function ascii(array $rules = []): self $s = preg_replace("/([AUO])\u{0308}(?=\p{Ll})/u", '$1e', $s); $s = str_replace(["a\u{0308}", "o\u{0308}", "u\u{0308}", "A\u{0308}", "O\u{0308}", "U\u{0308}"], ['ae', 'oe', 'ue', 'AE', 'OE', 'UE'], $s); } elseif (\function_exists('transliterator_transliterate')) { - if (null === $transliterator = self::$transliterators[$rule] ??= \Transliterator::create($rule)) { + if (null === $transliterator = self::$transliterators[$rule] ?? self::$transliterators[$rule] = \Transliterator::create($rule)) { if ('any-latin/bgn' === $rule) { $rule = 'any-latin'; - $transliterator = self::$transliterators[$rule] ??= \Transliterator::create($rule); + $transliterator = self::$transliterators[$rule] ?? self::$transliterators[$rule] = \Transliterator::create($rule); } if (null === $transliterator) { @@ -152,12 +159,10 @@ public function ascii(array $rules = []): self return $str; } - public function camel(): static + public function camel(): parent { $str = clone $this; - $str->string = str_replace(' ', '', preg_replace_callback('/\b.(?!\p{Lu})/u', static function ($m) { - static $i = 0; - + $str->string = str_replace(' ', '', preg_replace_callback('/\b./u', static function ($m) use (&$i) { return 1 === ++$i ? ('İ' === $m[0] ? 'i̇' : mb_strtolower($m[0], 'UTF-8')) : mb_convert_case($m[0], \MB_CASE_TITLE, 'UTF-8'); }, preg_replace('/[^\pL0-9]++/u', ' ', $this->string))); @@ -184,13 +189,13 @@ public function codePointsAt(int $offset): array return $codePoints; } - public function folded(bool $compat = true): static + public function folded(bool $compat = true): parent { $str = clone $this; - if (!$compat || !\defined('Normalizer::NFKC_CF')) { + if (!$compat || \PHP_VERSION_ID < 70300 || !\defined('Normalizer::NFKC_CF')) { $str->string = normalizer_normalize($str->string, $compat ? \Normalizer::NFKC : \Normalizer::NFC); - $str->string = mb_strtolower(str_replace(self::FOLD_FROM, self::FOLD_TO, $str->string), 'UTF-8'); + $str->string = mb_strtolower(str_replace(self::FOLD_FROM, self::FOLD_TO, $this->string), 'UTF-8'); } else { $str->string = normalizer_normalize($str->string, \Normalizer::NFKC_CF); } @@ -198,7 +203,7 @@ public function folded(bool $compat = true): static return $str; } - public function join(array $strings, ?string $lastGlue = null): static + public function join(array $strings, string $lastGlue = null): parent { $str = clone $this; @@ -212,7 +217,7 @@ public function join(array $strings, ?string $lastGlue = null): static return $str; } - public function lower(): static + public function lower(): parent { $str = clone $this; $str->string = mb_strtolower(str_replace('İ', 'i̇', $str->string), 'UTF-8'); @@ -228,11 +233,19 @@ public function match(string $regexp, int $flags = 0, int $offset = 0): array $regexp .= 'i'; } - set_error_handler(static fn ($t, $m) => throw new InvalidArgumentException($m)); + set_error_handler(static function ($t, $m) { throw new InvalidArgumentException($m); }); try { if (false === $match($regexp.'u', $this->string, $matches, $flags | \PREG_UNMATCHED_AS_NULL, $offset)) { - throw new RuntimeException('Matching failed with error: '.preg_last_error_msg()); + $lastError = preg_last_error(); + + foreach (get_defined_constants(true)['pcre'] as $k => $v) { + if ($lastError === $v && '_ERROR' === substr($k, -6)) { + throw new RuntimeException('Matching failed with '.$k.'.'); + } + } + + throw new RuntimeException('Matching failed with unknown error code.'); } } finally { restore_error_handler(); @@ -241,7 +254,10 @@ public function match(string $regexp, int $flags = 0, int $offset = 0): array return $matches; } - public function normalize(int $form = self::NFC): static + /** + * @return static + */ + public function normalize(int $form = self::NFC): self { if (!\in_array($form, [self::NFC, self::NFD, self::NFKC, self::NFKD])) { throw new InvalidArgumentException('Unsupported normalization form.'); @@ -253,7 +269,7 @@ public function normalize(int $form = self::NFC): static return $str; } - public function padBoth(int $length, string $padStr = ' '): static + public function padBoth(int $length, string $padStr = ' '): parent { if ('' === $padStr || !preg_match('//u', $padStr)) { throw new InvalidArgumentException('Invalid UTF-8 string.'); @@ -265,7 +281,7 @@ public function padBoth(int $length, string $padStr = ' '): static return $this->pad($length, $pad, \STR_PAD_BOTH); } - public function padEnd(int $length, string $padStr = ' '): static + public function padEnd(int $length, string $padStr = ' '): parent { if ('' === $padStr || !preg_match('//u', $padStr)) { throw new InvalidArgumentException('Invalid UTF-8 string.'); @@ -277,7 +293,7 @@ public function padEnd(int $length, string $padStr = ' '): static return $this->pad($length, $pad, \STR_PAD_RIGHT); } - public function padStart(int $length, string $padStr = ' '): static + public function padStart(int $length, string $padStr = ' '): parent { if ('' === $padStr || !preg_match('//u', $padStr)) { throw new InvalidArgumentException('Invalid UTF-8 string.'); @@ -289,13 +305,17 @@ public function padStart(int $length, string $padStr = ' '): static return $this->pad($length, $pad, \STR_PAD_LEFT); } - public function replaceMatches(string $fromRegexp, string|callable $to): static + public function replaceMatches(string $fromRegexp, $to): parent { if ($this->ignoreCase) { $fromRegexp .= 'i'; } if (\is_array($to) || $to instanceof \Closure) { + if (!\is_callable($to)) { + throw new \TypeError(sprintf('Argument 2 passed to "%s::replaceMatches()" must be callable, array given.', static::class)); + } + $replace = 'preg_replace_callback'; $to = static function (array $m) use ($to): string { $to = $to($m); @@ -312,14 +332,14 @@ public function replaceMatches(string $fromRegexp, string|callable $to): static $replace = 'preg_replace'; } - set_error_handler(static fn ($t, $m) => throw new InvalidArgumentException($m)); + set_error_handler(static function ($t, $m) { throw new InvalidArgumentException($m); }); try { if (null === $string = $replace($fromRegexp.'u', $to, $this->string)) { $lastError = preg_last_error(); foreach (get_defined_constants(true)['pcre'] as $k => $v) { - if ($lastError === $v && str_ends_with($k, '_ERROR')) { + if ($lastError === $v && '_ERROR' === substr($k, -6)) { throw new RuntimeException('Matching failed with '.$k.'.'); } } @@ -336,7 +356,7 @@ public function replaceMatches(string $fromRegexp, string|callable $to): static return $str; } - public function reverse(): static + public function reverse(): parent { $str = clone $this; $str->string = implode('', array_reverse(preg_split('/(\X)/u', $str->string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY))); @@ -344,26 +364,28 @@ public function reverse(): static return $str; } - public function snake(): static + public function snake(): parent { - $str = $this->camel(); + $str = $this->camel()->title(); $str->string = mb_strtolower(preg_replace(['/(\p{Lu}+)(\p{Lu}\p{Ll})/u', '/([\p{Ll}0-9])(\p{Lu})/u'], '\1_\2', $str->string), 'UTF-8'); return $str; } - public function title(bool $allWords = false): static + public function title(bool $allWords = false): parent { $str = clone $this; $limit = $allWords ? -1 : 1; - $str->string = preg_replace_callback('/\b./u', static fn (array $m): string => mb_convert_case($m[0], \MB_CASE_TITLE, 'UTF-8'), $str->string, $limit); + $str->string = preg_replace_callback('/\b./u', static function (array $m): string { + return mb_convert_case($m[0], \MB_CASE_TITLE, 'UTF-8'); + }, $str->string, $limit); return $str; } - public function trim(string $chars = " \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}"): static + public function trim(string $chars = " \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}"): parent { if (" \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}" !== $chars && !preg_match('//u', $chars)) { throw new InvalidArgumentException('Invalid UTF-8 chars.'); @@ -376,7 +398,7 @@ public function trim(string $chars = " \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}"): static return $str; } - public function trimEnd(string $chars = " \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}"): static + public function trimEnd(string $chars = " \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}"): parent { if (" \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}" !== $chars && !preg_match('//u', $chars)) { throw new InvalidArgumentException('Invalid UTF-8 chars.'); @@ -389,7 +411,7 @@ public function trimEnd(string $chars = " \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}"): stat return $str; } - public function trimPrefix($prefix): static + public function trimPrefix($prefix): parent { if (!$this->ignoreCase) { return parent::trimPrefix($prefix); @@ -409,7 +431,7 @@ public function trimPrefix($prefix): static return $str; } - public function trimStart(string $chars = " \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}"): static + public function trimStart(string $chars = " \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}"): parent { if (" \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}" !== $chars && !preg_match('//u', $chars)) { throw new InvalidArgumentException('Invalid UTF-8 chars.'); @@ -422,7 +444,7 @@ public function trimStart(string $chars = " \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}"): st return $str; } - public function trimSuffix($suffix): static + public function trimSuffix($suffix): parent { if (!$this->ignoreCase) { return parent::trimSuffix($suffix); @@ -442,11 +464,15 @@ public function trimSuffix($suffix): static return $str; } - public function upper(): static + public function upper(): parent { $str = clone $this; $str->string = mb_strtoupper($str->string, 'UTF-8'); + if (\PHP_VERSION_ID < 70300) { + $str->string = str_replace(self::UPPER_FROM, self::UPPER_TO, $str->string); + } + return $str; } @@ -455,7 +481,7 @@ public function width(bool $ignoreAnsiDecoration = true): int $width = 0; $s = str_replace(["\x00", "\x05", "\x07"], '', $this->string); - if (str_contains($s, "\r")) { + if (false !== strpos($s, "\r")) { $s = str_replace(["\r\n", "\r"], "\n", $s); } @@ -466,23 +492,23 @@ public function width(bool $ignoreAnsiDecoration = true): int foreach (explode("\n", $s) as $s) { if ($ignoreAnsiDecoration) { $s = preg_replace('/(?:\x1B(?: - \[ [\x30-\x3F]*+ [\x20-\x2F]*+ [\x40-\x7E] + \[ [\x30-\x3F]*+ [\x20-\x2F]*+ [0x40-\x7E] | [P\]X^_] .*? \x1B\\\\ | [\x41-\x7E] )|[\p{Cc}\x7F]++)/xu', '', $s); } - $lineWidth = $this->wcswidth($s); - - if ($lineWidth > $width) { - $width = $lineWidth; - } + // Non printable characters have been dropped, so wcswidth cannot logically return -1. + $width += $this->wcswidth($s); } return $width; } - private function pad(int $len, self $pad, int $type): static + /** + * @return static + */ + private function pad(int $len, self $pad, int $type): parent { $sLen = $this->length(); @@ -546,7 +572,9 @@ private function wcswidth(string $string): int return -1; } - self::$tableZero ??= require __DIR__.'/Resources/data/wcswidth_table_zero.php'; + if (null === self::$tableZero) { + self::$tableZero = require __DIR__.'/Resources/data/wcswidth_table_zero.php'; + } if ($codePoint >= self::$tableZero[0][0] && $codePoint <= self::$tableZero[$ubound = \count(self::$tableZero) - 1][1]) { $lbound = 0; @@ -563,7 +591,9 @@ private function wcswidth(string $string): int } } - self::$tableWide ??= require __DIR__.'/Resources/data/wcswidth_table_wide.php'; + if (null === self::$tableWide) { + self::$tableWide = require __DIR__.'/Resources/data/wcswidth_table_wide.php'; + } if ($codePoint >= self::$tableWide[0][0] && $codePoint <= self::$tableWide[$ubound = \count(self::$tableWide) - 1][1]) { $lbound = 0; diff --git a/deps/vendor/symfony/string/ByteString.php b/deps/vendor/symfony/string/ByteString.php index 3ebe43c10..bbf8614cf 100644 --- a/deps/vendor/symfony/string/ByteString.php +++ b/deps/vendor/symfony/string/ByteString.php @@ -42,13 +42,13 @@ public function __construct(string $string = '') * Copyright (c) 2004-2020, Facebook, Inc. (https://www.facebook.com/) */ - public static function fromRandom(int $length = 16, ?string $alphabet = null): self + public static function fromRandom(int $length = 16, string $alphabet = null): self { if ($length <= 0) { throw new InvalidArgumentException(sprintf('A strictly positive length is expected, "%d" given.', $length)); } - $alphabet ??= self::ALPHABET_ALPHANUMERIC; + $alphabet = $alphabet ?? self::ALPHABET_ALPHANUMERIC; $alphabetSize = \strlen($alphabet); $bits = (int) ceil(log($alphabetSize, 2.0)); if ($bits <= 0 || $bits > 56) { @@ -92,7 +92,7 @@ public function bytesAt(int $offset): array return '' === $str ? [] : [\ord($str)]; } - public function append(string ...$suffix): static + public function append(string ...$suffix): parent { $str = clone $this; $str->string .= 1 >= \count($suffix) ? ($suffix[0] ?? '') : implode('', $suffix); @@ -100,13 +100,10 @@ public function append(string ...$suffix): static return $str; } - public function camel(): static + public function camel(): parent { $str = clone $this; - - $parts = explode(' ', trim(ucwords(preg_replace('/[^a-zA-Z0-9\x7f-\xff]++/', ' ', $this->string)))); - $parts[0] = 1 !== \strlen($parts[0]) && ctype_upper($parts[0]) ? $parts[0] : lcfirst($parts[0]); - $str->string = implode('', $parts); + $str->string = lcfirst(str_replace(' ', '', ucwords(preg_replace('/[^a-zA-Z0-9\x7f-\xff]++/', ' ', $this->string)))); return $str; } @@ -132,23 +129,27 @@ public function chunk(int $length = 1): array return $chunks; } - public function endsWith(string|iterable|AbstractString $suffix): bool + public function endsWith($suffix): bool { - if ($suffix instanceof AbstractString) { + if ($suffix instanceof parent) { $suffix = $suffix->string; - } elseif (!\is_string($suffix)) { + } elseif (\is_array($suffix) || $suffix instanceof \Traversable) { return parent::endsWith($suffix); + } else { + $suffix = (string) $suffix; } return '' !== $suffix && \strlen($this->string) >= \strlen($suffix) && 0 === substr_compare($this->string, $suffix, -\strlen($suffix), null, $this->ignoreCase); } - public function equalsTo(string|iterable|AbstractString $string): bool + public function equalsTo($string): bool { - if ($string instanceof AbstractString) { + if ($string instanceof parent) { $string = $string->string; - } elseif (!\is_string($string)) { + } elseif (\is_array($string) || $string instanceof \Traversable) { return parent::equalsTo($string); + } else { + $string = (string) $string; } if ('' !== $string && $this->ignoreCase) { @@ -158,7 +159,7 @@ public function equalsTo(string|iterable|AbstractString $string): bool return $string === $this->string; } - public function folded(): static + public function folded(): parent { $str = clone $this; $str->string = strtolower($str->string); @@ -166,12 +167,14 @@ public function folded(): static return $str; } - public function indexOf(string|iterable|AbstractString $needle, int $offset = 0): ?int + public function indexOf($needle, int $offset = 0): ?int { - if ($needle instanceof AbstractString) { + if ($needle instanceof parent) { $needle = $needle->string; - } elseif (!\is_string($needle)) { + } elseif (\is_array($needle) || $needle instanceof \Traversable) { return parent::indexOf($needle, $offset); + } else { + $needle = (string) $needle; } if ('' === $needle) { @@ -183,12 +186,14 @@ public function indexOf(string|iterable|AbstractString $needle, int $offset = 0) return false === $i ? null : $i; } - public function indexOfLast(string|iterable|AbstractString $needle, int $offset = 0): ?int + public function indexOfLast($needle, int $offset = 0): ?int { - if ($needle instanceof AbstractString) { + if ($needle instanceof parent) { $needle = $needle->string; - } elseif (!\is_string($needle)) { + } elseif (\is_array($needle) || $needle instanceof \Traversable) { return parent::indexOfLast($needle, $offset); + } else { + $needle = (string) $needle; } if ('' === $needle) { @@ -205,7 +210,7 @@ public function isUtf8(): bool return '' === $this->string || preg_match('//u', $this->string); } - public function join(array $strings, ?string $lastGlue = null): static + public function join(array $strings, string $lastGlue = null): parent { $str = clone $this; @@ -220,7 +225,7 @@ public function length(): int return \strlen($this->string); } - public function lower(): static + public function lower(): parent { $str = clone $this; $str->string = strtolower($str->string); @@ -236,11 +241,19 @@ public function match(string $regexp, int $flags = 0, int $offset = 0): array $regexp .= 'i'; } - set_error_handler(static fn ($t, $m) => throw new InvalidArgumentException($m)); + set_error_handler(static function ($t, $m) { throw new InvalidArgumentException($m); }); try { if (false === $match($regexp, $this->string, $matches, $flags | \PREG_UNMATCHED_AS_NULL, $offset)) { - throw new RuntimeException('Matching failed with error: '.preg_last_error_msg()); + $lastError = preg_last_error(); + + foreach (get_defined_constants(true)['pcre'] as $k => $v) { + if ($lastError === $v && '_ERROR' === substr($k, -6)) { + throw new RuntimeException('Matching failed with '.$k.'.'); + } + } + + throw new RuntimeException('Matching failed with unknown error code.'); } } finally { restore_error_handler(); @@ -249,7 +262,7 @@ public function match(string $regexp, int $flags = 0, int $offset = 0): array return $matches; } - public function padBoth(int $length, string $padStr = ' '): static + public function padBoth(int $length, string $padStr = ' '): parent { $str = clone $this; $str->string = str_pad($this->string, $length, $padStr, \STR_PAD_BOTH); @@ -257,7 +270,7 @@ public function padBoth(int $length, string $padStr = ' '): static return $str; } - public function padEnd(int $length, string $padStr = ' '): static + public function padEnd(int $length, string $padStr = ' '): parent { $str = clone $this; $str->string = str_pad($this->string, $length, $padStr, \STR_PAD_RIGHT); @@ -265,7 +278,7 @@ public function padEnd(int $length, string $padStr = ' '): static return $str; } - public function padStart(int $length, string $padStr = ' '): static + public function padStart(int $length, string $padStr = ' '): parent { $str = clone $this; $str->string = str_pad($this->string, $length, $padStr, \STR_PAD_LEFT); @@ -273,7 +286,7 @@ public function padStart(int $length, string $padStr = ' '): static return $str; } - public function prepend(string ...$prefix): static + public function prepend(string ...$prefix): parent { $str = clone $this; $str->string = (1 >= \count($prefix) ? ($prefix[0] ?? '') : implode('', $prefix)).$str->string; @@ -281,7 +294,7 @@ public function prepend(string ...$prefix): static return $str; } - public function replace(string $from, string $to): static + public function replace(string $from, string $to): parent { $str = clone $this; @@ -292,22 +305,30 @@ public function replace(string $from, string $to): static return $str; } - public function replaceMatches(string $fromRegexp, string|callable $to): static + public function replaceMatches(string $fromRegexp, $to): parent { if ($this->ignoreCase) { $fromRegexp .= 'i'; } - $replace = \is_array($to) || $to instanceof \Closure ? 'preg_replace_callback' : 'preg_replace'; + if (\is_array($to)) { + if (!\is_callable($to)) { + throw new \TypeError(sprintf('Argument 2 passed to "%s::replaceMatches()" must be callable, array given.', static::class)); + } + + $replace = 'preg_replace_callback'; + } else { + $replace = $to instanceof \Closure ? 'preg_replace_callback' : 'preg_replace'; + } - set_error_handler(static fn ($t, $m) => throw new InvalidArgumentException($m)); + set_error_handler(static function ($t, $m) { throw new InvalidArgumentException($m); }); try { if (null === $string = $replace($fromRegexp, $to, $this->string)) { $lastError = preg_last_error(); foreach (get_defined_constants(true)['pcre'] as $k => $v) { - if ($lastError === $v && str_ends_with($k, '_ERROR')) { + if ($lastError === $v && '_ERROR' === substr($k, -6)) { throw new RuntimeException('Matching failed with '.$k.'.'); } } @@ -324,7 +345,7 @@ public function replaceMatches(string $fromRegexp, string|callable $to): static return $str; } - public function reverse(): static + public function reverse(): parent { $str = clone $this; $str->string = strrev($str->string); @@ -332,7 +353,7 @@ public function reverse(): static return $str; } - public function slice(int $start = 0, ?int $length = null): static + public function slice(int $start = 0, int $length = null): parent { $str = clone $this; $str->string = (string) substr($this->string, $start, $length ?? \PHP_INT_MAX); @@ -340,15 +361,15 @@ public function slice(int $start = 0, ?int $length = null): static return $str; } - public function snake(): static + public function snake(): parent { - $str = $this->camel(); + $str = $this->camel()->title(); $str->string = strtolower(preg_replace(['/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'], '\1_\2', $str->string)); return $str; } - public function splice(string $replacement, int $start = 0, ?int $length = null): static + public function splice(string $replacement, int $start = 0, int $length = null): parent { $str = clone $this; $str->string = substr_replace($this->string, $replacement, $start, $length ?? \PHP_INT_MAX); @@ -356,9 +377,9 @@ public function splice(string $replacement, int $start = 0, ?int $length = null) return $str; } - public function split(string $delimiter, ?int $limit = null, ?int $flags = null): array + public function split(string $delimiter, int $limit = null, int $flags = null): array { - if (1 > $limit ??= \PHP_INT_MAX) { + if (1 > $limit = $limit ?? \PHP_INT_MAX) { throw new InvalidArgumentException('Split limit must be a positive integer.'); } @@ -383,9 +404,9 @@ public function split(string $delimiter, ?int $limit = null, ?int $flags = null) return $chunks; } - public function startsWith(string|iterable|AbstractString $prefix): bool + public function startsWith($prefix): bool { - if ($prefix instanceof AbstractString) { + if ($prefix instanceof parent) { $prefix = $prefix->string; } elseif (!\is_string($prefix)) { return parent::startsWith($prefix); @@ -394,7 +415,7 @@ public function startsWith(string|iterable|AbstractString $prefix): bool return '' !== $prefix && 0 === ($this->ignoreCase ? strncasecmp($this->string, $prefix, \strlen($prefix)) : strncmp($this->string, $prefix, \strlen($prefix))); } - public function title(bool $allWords = false): static + public function title(bool $allWords = false): parent { $str = clone $this; $str->string = $allWords ? ucwords($str->string) : ucfirst($str->string); @@ -402,12 +423,12 @@ public function title(bool $allWords = false): static return $str; } - public function toUnicodeString(?string $fromEncoding = null): UnicodeString + public function toUnicodeString(string $fromEncoding = null): UnicodeString { return new UnicodeString($this->toCodePointString($fromEncoding)->string); } - public function toCodePointString(?string $fromEncoding = null): CodePointString + public function toCodePointString(string $fromEncoding = null): CodePointString { $u = new CodePointString(); @@ -417,7 +438,7 @@ public function toCodePointString(?string $fromEncoding = null): CodePointString return $u; } - set_error_handler(static fn ($t, $m) => throw new InvalidArgumentException($m)); + set_error_handler(static function ($t, $m) { throw new InvalidArgumentException($m); }); try { try { @@ -444,7 +465,7 @@ public function toCodePointString(?string $fromEncoding = null): CodePointString return $u; } - public function trim(string $chars = " \t\n\r\0\x0B\x0C"): static + public function trim(string $chars = " \t\n\r\0\x0B\x0C"): parent { $str = clone $this; $str->string = trim($str->string, $chars); @@ -452,7 +473,7 @@ public function trim(string $chars = " \t\n\r\0\x0B\x0C"): static return $str; } - public function trimEnd(string $chars = " \t\n\r\0\x0B\x0C"): static + public function trimEnd(string $chars = " \t\n\r\0\x0B\x0C"): parent { $str = clone $this; $str->string = rtrim($str->string, $chars); @@ -460,7 +481,7 @@ public function trimEnd(string $chars = " \t\n\r\0\x0B\x0C"): static return $str; } - public function trimStart(string $chars = " \t\n\r\0\x0B\x0C"): static + public function trimStart(string $chars = " \t\n\r\0\x0B\x0C"): parent { $str = clone $this; $str->string = ltrim($str->string, $chars); @@ -468,7 +489,7 @@ public function trimStart(string $chars = " \t\n\r\0\x0B\x0C"): static return $str; } - public function upper(): static + public function upper(): parent { $str = clone $this; $str->string = strtoupper($str->string); diff --git a/deps/vendor/symfony/string/CHANGELOG.md b/deps/vendor/symfony/string/CHANGELOG.md index 31a3b54db..53af36400 100644 --- a/deps/vendor/symfony/string/CHANGELOG.md +++ b/deps/vendor/symfony/string/CHANGELOG.md @@ -1,11 +1,6 @@ CHANGELOG ========= -6.2 ---- - - * Add support for emoji in `AsciiSlugger` - 5.4 --- diff --git a/deps/vendor/symfony/string/CodePointString.php b/deps/vendor/symfony/string/CodePointString.php index 337bfc12a..8ab920941 100644 --- a/deps/vendor/symfony/string/CodePointString.php +++ b/deps/vendor/symfony/string/CodePointString.php @@ -33,7 +33,7 @@ public function __construct(string $string = '') $this->string = $string; } - public function append(string ...$suffix): static + public function append(string ...$suffix): AbstractString { $str = clone $this; $str->string .= 1 >= \count($suffix) ? ($suffix[0] ?? '') : implode('', $suffix); @@ -80,12 +80,14 @@ public function codePointsAt(int $offset): array return '' === $str->string ? [] : [mb_ord($str->string, 'UTF-8')]; } - public function endsWith(string|iterable|AbstractString $suffix): bool + public function endsWith($suffix): bool { if ($suffix instanceof AbstractString) { $suffix = $suffix->string; - } elseif (!\is_string($suffix)) { + } elseif (\is_array($suffix) || $suffix instanceof \Traversable) { return parent::endsWith($suffix); + } else { + $suffix = (string) $suffix; } if ('' === $suffix || !preg_match('//u', $suffix)) { @@ -99,12 +101,14 @@ public function endsWith(string|iterable|AbstractString $suffix): bool return \strlen($this->string) >= \strlen($suffix) && 0 === substr_compare($this->string, $suffix, -\strlen($suffix)); } - public function equalsTo(string|iterable|AbstractString $string): bool + public function equalsTo($string): bool { if ($string instanceof AbstractString) { $string = $string->string; - } elseif (!\is_string($string)) { + } elseif (\is_array($string) || $string instanceof \Traversable) { return parent::equalsTo($string); + } else { + $string = (string) $string; } if ('' !== $string && $this->ignoreCase) { @@ -114,12 +118,14 @@ public function equalsTo(string|iterable|AbstractString $string): bool return $string === $this->string; } - public function indexOf(string|iterable|AbstractString $needle, int $offset = 0): ?int + public function indexOf($needle, int $offset = 0): ?int { if ($needle instanceof AbstractString) { $needle = $needle->string; - } elseif (!\is_string($needle)) { + } elseif (\is_array($needle) || $needle instanceof \Traversable) { return parent::indexOf($needle, $offset); + } else { + $needle = (string) $needle; } if ('' === $needle) { @@ -131,12 +137,14 @@ public function indexOf(string|iterable|AbstractString $needle, int $offset = 0) return false === $i ? null : $i; } - public function indexOfLast(string|iterable|AbstractString $needle, int $offset = 0): ?int + public function indexOfLast($needle, int $offset = 0): ?int { if ($needle instanceof AbstractString) { $needle = $needle->string; - } elseif (!\is_string($needle)) { + } elseif (\is_array($needle) || $needle instanceof \Traversable) { return parent::indexOfLast($needle, $offset); + } else { + $needle = (string) $needle; } if ('' === $needle) { @@ -153,7 +161,7 @@ public function length(): int return mb_strlen($this->string, 'UTF-8'); } - public function prepend(string ...$prefix): static + public function prepend(string ...$prefix): AbstractString { $str = clone $this; $str->string = (1 >= \count($prefix) ? ($prefix[0] ?? '') : implode('', $prefix)).$this->string; @@ -165,7 +173,7 @@ public function prepend(string ...$prefix): static return $str; } - public function replace(string $from, string $to): static + public function replace(string $from, string $to): AbstractString { $str = clone $this; @@ -186,7 +194,7 @@ public function replace(string $from, string $to): static return $str; } - public function slice(int $start = 0, ?int $length = null): static + public function slice(int $start = 0, int $length = null): AbstractString { $str = clone $this; $str->string = mb_substr($this->string, $start, $length, 'UTF-8'); @@ -194,7 +202,7 @@ public function slice(int $start = 0, ?int $length = null): static return $str; } - public function splice(string $replacement, int $start = 0, ?int $length = null): static + public function splice(string $replacement, int $start = 0, int $length = null): AbstractString { if (!preg_match('//u', $replacement)) { throw new InvalidArgumentException('Invalid UTF-8 string.'); @@ -208,9 +216,9 @@ public function splice(string $replacement, int $start = 0, ?int $length = null) return $str; } - public function split(string $delimiter, ?int $limit = null, ?int $flags = null): array + public function split(string $delimiter, int $limit = null, int $flags = null): array { - if (1 > $limit ??= \PHP_INT_MAX) { + if (1 > $limit = $limit ?? \PHP_INT_MAX) { throw new InvalidArgumentException('Split limit must be a positive integer.'); } @@ -239,12 +247,14 @@ public function split(string $delimiter, ?int $limit = null, ?int $flags = null) return $chunks; } - public function startsWith(string|iterable|AbstractString $prefix): bool + public function startsWith($prefix): bool { if ($prefix instanceof AbstractString) { $prefix = $prefix->string; - } elseif (!\is_string($prefix)) { + } elseif (\is_array($prefix) || $prefix instanceof \Traversable) { return parent::startsWith($prefix); + } else { + $prefix = (string) $prefix; } if ('' === $prefix || !preg_match('//u', $prefix)) { diff --git a/deps/vendor/symfony/string/Inflector/EnglishInflector.php b/deps/vendor/symfony/string/Inflector/EnglishInflector.php index c41badead..9f2fac675 100644 --- a/deps/vendor/symfony/string/Inflector/EnglishInflector.php +++ b/deps/vendor/symfony/string/Inflector/EnglishInflector.php @@ -21,39 +21,12 @@ final class EnglishInflector implements InflectorInterface private const PLURAL_MAP = [ // First entry: plural suffix, reversed // Second entry: length of plural suffix - // Third entry: Whether the suffix may succeed a vowel + // Third entry: Whether the suffix may succeed a vocal // Fourth entry: Whether the suffix may succeed a consonant // Fifth entry: singular suffix, normal - // bacteria (bacterium) - ['airetcab', 8, true, true, 'bacterium'], - - // corpora (corpus) - ['aroproc', 7, true, true, 'corpus'], - - // criteria (criterion) - ['airetirc', 8, true, true, 'criterion'], - - // curricula (curriculum) - ['alucirruc', 9, true, true, 'curriculum'], - - // quora (quorum) - ['arouq', 5, true, true, 'quorum'], - - // genera (genus) - ['areneg', 6, true, true, 'genus'], - - // media (medium) - ['aidem', 5, true, true, 'medium'], - - // memoranda (memorandum) - ['adnaromem', 9, true, true, 'memorandum'], - - // phenomena (phenomenon) - ['anemonehp', 9, true, true, 'phenomenon'], - - // strata (stratum) - ['atarts', 6, true, true, 'stratum'], + // bacteria (bacterium), criteria (criterion), phenomena (phenomenon) + ['a', 1, true, true, ['on', 'um']], // nebulae (nebula) ['ea', 2, true, true, 'a'], @@ -82,9 +55,6 @@ final class EnglishInflector implements InflectorInterface // indices (index), appendices (appendix), prices (price) ['seci', 4, false, true, ['ex', 'ix', 'ice']], - // codes (code) - ['sedoc', 5, false, true, 'code'], - // selfies (selfie) ['seifles', 7, true, true, 'selfie'], @@ -94,9 +64,6 @@ final class EnglishInflector implements InflectorInterface // movies (movie) ['seivom', 6, true, true, 'movie'], - // names (name) - ['seman', 5, true, false, 'name'], - // conspectuses (conspectus), prospectuses (prospectus) ['sesutcep', 8, true, true, 'pectus'], @@ -121,12 +88,6 @@ final class EnglishInflector implements InflectorInterface // accesses (access), addresses (address), kisses (kiss) ['sess', 4, true, false, 'ss'], - // statuses (status) - ['sesutats', 8, true, true, 'status'], - - // article (articles), ancle (ancles) - ['sel', 3, true, true, 'le'], - // analyses (analysis), ellipses (ellipsis), fungi (fungus), // neuroses (neurosis), theses (thesis), emphases (emphasis), // oases (oasis), crises (crisis), houses (house), bases (base), @@ -171,9 +132,6 @@ final class EnglishInflector implements InflectorInterface // shoes (shoe) ['se', 2, true, true, ['', 'e']], - // status (status) - ['sutats', 6, true, true, 'status'], - // tags (tag) ['s', 1, true, true, ''], @@ -192,13 +150,10 @@ final class EnglishInflector implements InflectorInterface private const SINGULAR_MAP = [ // First entry: singular suffix, reversed // Second entry: length of singular suffix - // Third entry: Whether the suffix may succeed a vowel + // Third entry: Whether the suffix may succeed a vocal // Fourth entry: Whether the suffix may succeed a consonant // Fifth entry: plural suffix, normal - // axes (axis) - ['sixa', 4, false, false, 'axes'], - // criterion (criteria) ['airetirc', 8, false, false, 'criterion'], @@ -268,13 +223,7 @@ final class EnglishInflector implements InflectorInterface // teeth (tooth) ['htoot', 5, true, true, 'teeth'], - // albums (album) - ['mubla', 5, true, true, 'albums'], - - // quorums (quorum) - ['murouq', 6, true, true, ['quora', 'quorums']], - - // bacteria (bacterium), curricula (curriculum), media (medium), memoranda (memorandum), phenomena (phenomenon), strata (stratum) + // bacteria (bacterium), criteria (criterion), phenomena (phenomenon) ['mu', 2, true, true, 'a'], // men (man), women (woman) @@ -283,11 +232,17 @@ final class EnglishInflector implements InflectorInterface // people (person) ['nosrep', 6, true, true, ['persons', 'people']], - // criteria (criterion) - ['noiretirc', 9, true, true, 'criteria'], + // bacteria (bacterium), criteria (criterion), phenomena (phenomenon) + ['noi', 3, true, true, 'ions'], + + // coupon (coupons) + ['nop', 3, true, true, 'pons'], - // phenomena (phenomenon) - ['nonemonehp', 10, true, true, 'phenomena'], + // seasons (season), treasons (treason), poisons (poison), lessons (lesson) + ['nos', 3, true, true, 'sons'], + + // bacteria (bacterium), criteria (criterion), phenomena (phenomenon) + ['no', 2, true, true, 'a'], // echoes (echo) ['ohce', 4, true, true, 'echoes'], @@ -298,9 +253,6 @@ final class EnglishInflector implements InflectorInterface // atlases (atlas) ['salta', 5, true, true, 'atlases'], - // aliases (alias) - ['saila', 5, true, true, 'aliases'], - // irises (iris) ['siri', 4, true, true, 'irises'], @@ -321,15 +273,6 @@ final class EnglishInflector implements InflectorInterface // circuses (circus) ['suc', 3, true, true, 'cuses'], - // hippocampi (hippocampus) - ['supmacoppih', 11, false, false, 'hippocampi'], - - // campuses (campus) - ['sup', 3, true, true, 'puses'], - - // status (status) - ['sutats', 6, true, true, ['status', 'statuses']], - // conspectuses (conspectus), prospectuses (prospectus) ['sutcep', 6, true, true, 'pectuses'], @@ -385,30 +328,15 @@ final class EnglishInflector implements InflectorInterface // deer 'reed', - // equipment - 'tnempiuqe', - // feedback 'kcabdeef', // fish 'hsif', - // health - 'htlaeh', - - // history - 'yrotsih', - // info 'ofni', - // information - 'noitamrofni', - - // money - 'yenom', - // moose 'esoom', @@ -420,17 +348,11 @@ final class EnglishInflector implements InflectorInterface // species 'seiceps', - - // traffic - 'ciffart', - - // aircraft - 'tfarcria', - - // hardware - 'erawdrah', ]; + /** + * {@inheritdoc} + */ public function singularize(string $plural): array { $pluralRev = strrev($plural); @@ -462,14 +384,14 @@ public function singularize(string $plural): array if ($j === $suffixLength) { // Is there any character preceding the suffix in the plural string? if ($j < $pluralLength) { - $nextIsVowel = str_contains('aeiou', $lowerPluralRev[$j]); + $nextIsVocal = false !== strpos('aeiou', $lowerPluralRev[$j]); - if (!$map[2] && $nextIsVowel) { - // suffix may not succeed a vowel but next char is one + if (!$map[2] && $nextIsVocal) { + // suffix may not succeed a vocal but next char is one break; } - if (!$map[3] && !$nextIsVowel) { + if (!$map[3] && !$nextIsVocal) { // suffix may not succeed a consonant but next char is one break; } @@ -507,6 +429,9 @@ public function singularize(string $plural): array return [$plural]; } + /** + * {@inheritdoc} + */ public function pluralize(string $singular): array { $singularRev = strrev($singular); @@ -539,14 +464,14 @@ public function pluralize(string $singular): array if ($j === $suffixLength) { // Is there any character preceding the suffix in the plural string? if ($j < $singularLength) { - $nextIsVowel = str_contains('aeiou', $lowerSingularRev[$j]); + $nextIsVocal = false !== strpos('aeiou', $lowerSingularRev[$j]); - if (!$map[2] && $nextIsVowel) { - // suffix may not succeed a vowel but next char is one + if (!$map[2] && $nextIsVocal) { + // suffix may not succeed a vocal but next char is one break; } - if (!$map[3] && !$nextIsVowel) { + if (!$map[3] && !$nextIsVocal) { // suffix may not succeed a consonant but next char is one break; } diff --git a/deps/vendor/symfony/string/Inflector/FrenchInflector.php b/deps/vendor/symfony/string/Inflector/FrenchInflector.php index 955abbf46..42f6125aa 100644 --- a/deps/vendor/symfony/string/Inflector/FrenchInflector.php +++ b/deps/vendor/symfony/string/Inflector/FrenchInflector.php @@ -100,7 +100,7 @@ final class FrenchInflector implements InflectorInterface ['/^mes(sieur|seigneur)s$/', 'mon\1'], ['/^Mes(sieur|seigneur)s$/', 'Mon\1'], - // Default rule + //Default rule ['/s$/i', ''], ]; @@ -108,8 +108,11 @@ final class FrenchInflector implements InflectorInterface * A list of words which should not be inflected. * This list is only used by singularize. */ - private const UNINFLECTED = '/^(abcès|accès|abus|albatros|anchois|anglais|autobus|bois|brebis|carquois|cas|chas|colis|concours|corps|cours|cyprès|décès|devis|discours|dos|embarras|engrais|entrelacs|excès|fils|fois|gâchis|gars|glas|héros|intrus|jars|jus|kermès|lacis|legs|lilas|marais|mars|matelas|mépris|mets|mois|mors|obus|os|palais|paradis|parcours|pardessus|pays|plusieurs|poids|pois|pouls|printemps|processus|progrès|puits|pus|rabais|radis|recors|recours|refus|relais|remords|remous|rictus|rhinocéros|repas|rubis|sans|sas|secours|sens|souris|succès|talus|tapis|tas|taudis|temps|tiers|univers|velours|verglas|vernis|virus)$/i'; + private const UNINFLECTED = '/^(abcès|accès|abus|albatros|anchois|anglais|autobus|bois|brebis|carquois|cas|chas|colis|concours|corps|cours|cyprès|décès|devis|discours|dos|embarras|engrais|entrelacs|excès|fils|fois|gâchis|gars|glas|héros|intrus|jars|jus|kermès|lacis|legs|lilas|marais|mars|matelas|mépris|mets|mois|mors|obus|os|palais|paradis|parcours|pardessus|pays|plusieurs|poids|pois|pouls|printemps|processus|progrès|puits|pus|rabais|radis|recors|recours|refus|relais|remords|remous|rictus|rhinocéros|repas|rubis|sas|secours|sens|souris|succès|talus|tapis|tas|taudis|temps|tiers|univers|velours|verglas|vernis|virus)$/i'; + /** + * {@inheritdoc} + */ public function singularize(string $plural): array { if ($this->isInflectedWord($plural)) { @@ -127,6 +130,9 @@ public function singularize(string $plural): array return [$plural]; } + /** + * {@inheritdoc} + */ public function pluralize(string $singular): array { if ($this->isInflectedWord($singular)) { diff --git a/deps/vendor/symfony/string/LICENSE b/deps/vendor/symfony/string/LICENSE index f37c76b59..9c907a46a 100644 --- a/deps/vendor/symfony/string/LICENSE +++ b/deps/vendor/symfony/string/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2019-present Fabien Potencier +Copyright (c) 2019-2022 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/deps/vendor/symfony/string/LazyString.php b/deps/vendor/symfony/string/LazyString.php index 3d893ef9e..b3801db77 100644 --- a/deps/vendor/symfony/string/LazyString.php +++ b/deps/vendor/symfony/string/LazyString.php @@ -18,28 +18,28 @@ */ class LazyString implements \Stringable, \JsonSerializable { - private \Closure|string $value; + private $value; /** * @param callable|array $callback A callable or a [Closure, method] lazy-callable + * + * @return static */ - public static function fromCallable(callable|array $callback, mixed ...$arguments): static + public static function fromCallable($callback, ...$arguments): self { - if (\is_array($callback) && !\is_callable($callback) && !(($callback[0] ?? null) instanceof \Closure || 2 < \count($callback))) { - throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be a callable or a [Closure, method] lazy-callable, "%s" given.', __METHOD__, '['.implode(', ', array_map('get_debug_type', $callback)).']')); + if (!\is_callable($callback) && !(\is_array($callback) && isset($callback[0]) && $callback[0] instanceof \Closure && 2 >= \count($callback))) { + throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be a callable or a [Closure, method] lazy-callable, "%s" given.', __METHOD__, get_debug_type($callback))); } $lazyString = new static(); - $lazyString->value = static function () use (&$callback, &$arguments): string { - static $value; - + $lazyString->value = static function () use (&$callback, &$arguments, &$value): string { if (null !== $arguments) { if (!\is_callable($callback)) { $callback[0] = $callback[0](); - $callback[1] ??= '__invoke'; + $callback[1] = $callback[1] ?? '__invoke'; } $value = $callback(...$arguments); - $callback = !\is_scalar($value) && !$value instanceof \Stringable ? self::getPrettyName($callback) : 'callable'; + $callback = self::getPrettyName($callback); $arguments = null; } @@ -49,10 +49,19 @@ public static function fromCallable(callable|array $callback, mixed ...$argument return $lazyString; } - public static function fromStringable(string|int|float|bool|\Stringable $value): static + /** + * @param string|int|float|bool|\Stringable $value + * + * @return static + */ + public static function fromStringable($value): self { + if (!self::isStringable($value)) { + throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be a scalar or a stringable object, "%s" given.', __METHOD__, get_debug_type($value))); + } + if (\is_object($value)) { - return static::fromCallable($value->__toString(...)); + return static::fromCallable([$value, '__toString']); } $lazyString = new static(); @@ -64,22 +73,27 @@ public static function fromStringable(string|int|float|bool|\Stringable $value): /** * Tells whether the provided value can be cast to string. */ - final public static function isStringable(mixed $value): bool + final public static function isStringable($value): bool { - return \is_string($value) || $value instanceof \Stringable || \is_scalar($value); + return \is_string($value) || $value instanceof self || (\is_object($value) ? method_exists($value, '__toString') : is_scalar($value)); } /** * Casts scalars and stringable objects to strings. * + * @param object|string|int|float|bool $value + * * @throws \TypeError When the provided value is not stringable */ - final public static function resolve(\Stringable|string|int|float|bool $value): string + final public static function resolve($value): string { return $value; } - public function __toString(): string + /** + * @return string + */ + public function __toString() { if (\is_string($this->value)) { return $this->value; @@ -88,7 +102,7 @@ public function __toString(): string try { return $this->value = ($this->value)(); } catch (\Throwable $e) { - if (\TypeError::class === $e::class && __FILE__ === $e->getFile()) { + if (\TypeError::class === \get_class($e) && __FILE__ === $e->getFile()) { $type = explode(', ', $e->getMessage()); $type = substr(array_pop($type), 0, -\strlen(' returned')); $r = new \ReflectionFunction($this->value); @@ -97,6 +111,11 @@ public function __toString(): string $e = new \TypeError(sprintf('Return value of %s() passed to %s::fromCallable() must be of the type string, %s returned.', $callback, static::class, $type)); } + if (\PHP_VERSION_ID < 70400) { + // leverage the ErrorHandler component with graceful fallback when it's not available + return trigger_error($e, \E_USER_ERROR); + } + throw $e; } } @@ -129,7 +148,7 @@ private static function getPrettyName(callable $callback): string } elseif ($callback instanceof \Closure) { $r = new \ReflectionFunction($callback); - if (str_contains($r->name, '{closure') || !$class = \PHP_VERSION_ID >= 80111 ? $r->getClosureCalledClass() : $r->getClosureScopeClass()) { + if (false !== strpos($r->name, '{closure}') || !$class = $r->getClosureScopeClass()) { return $r->name; } diff --git a/deps/vendor/symfony/string/Resources/data/wcswidth_table_wide.php b/deps/vendor/symfony/string/Resources/data/wcswidth_table_wide.php index 6a7509421..43c802d05 100644 --- a/deps/vendor/symfony/string/Resources/data/wcswidth_table_wide.php +++ b/deps/vendor/symfony/string/Resources/data/wcswidth_table_wide.php @@ -3,8 +3,8 @@ /* * This file has been auto-generated by the Symfony String Component for internal use. * - * Unicode version: 16.0.0 - * Date: 2024-09-11T08:21:22+00:00 + * Unicode version: 14.0.0 + * Date: 2021-09-17T09:20:30+02:00 */ return [ @@ -44,10 +44,6 @@ 9748, 9749, ], - [ - 9776, - 9783, - ], [ 9800, 9811, @@ -56,10 +52,6 @@ 9855, 9855, ], - [ - 9866, - 9871, - ], [ 9875, 9875, @@ -174,7 +166,7 @@ ], [ 12272, - 12287, + 12283, ], [ 12288, @@ -402,11 +394,7 @@ ], [ 12736, - 12773, - ], - [ - 12783, - 12783, + 12771, ], [ 12784, @@ -460,10 +448,6 @@ 13312, 19903, ], - [ - 19904, - 19967, - ], [ 19968, 40959, @@ -848,10 +832,6 @@ 101120, 101589, ], - [ - 101631, - 101631, - ], [ 101632, 101640, @@ -876,18 +856,10 @@ 110848, 110882, ], - [ - 110898, - 110898, - ], [ 110928, 110930, ], - [ - 110933, - 110933, - ], [ 110948, 110951, @@ -896,14 +868,6 @@ 110960, 111355, ], - [ - 119552, - 119638, - ], - [ - 119648, - 119670, - ], [ 126980, 126980, @@ -1041,7 +1005,7 @@ 128727, ], [ - 128732, + 128733, 128735, ], [ @@ -1074,27 +1038,39 @@ ], [ 129648, + 129652, + ], + [ + 129656, 129660, ], [ 129664, - 129673, + 129670, + ], + [ + 129680, + 129708, ], [ - 129679, - 129734, + 129712, + 129722, ], [ - 129742, - 129756, + 129728, + 129733, ], [ - 129759, - 129769, + 129744, + 129753, + ], + [ + 129760, + 129767, ], [ 129776, - 129784, + 129782, ], [ 131072, @@ -1106,10 +1082,10 @@ ], [ 173824, - 177977, + 177976, ], [ - 177978, + 177977, 177983, ], [ @@ -1134,14 +1110,6 @@ ], [ 191457, - 191471, - ], - [ - 191472, - 192093, - ], - [ - 192094, 194559, ], [ @@ -1162,14 +1130,6 @@ ], [ 201547, - 201551, - ], - [ - 201552, - 205743, - ], - [ - 205744, 262141, ], ]; diff --git a/deps/vendor/symfony/string/Resources/data/wcswidth_table_zero.php b/deps/vendor/symfony/string/Resources/data/wcswidth_table_zero.php index fdd7f3c7e..63b082473 100644 --- a/deps/vendor/symfony/string/Resources/data/wcswidth_table_zero.php +++ b/deps/vendor/symfony/string/Resources/data/wcswidth_table_zero.php @@ -3,8 +3,8 @@ /* * This file has been auto-generated by the Symfony String Component for internal use. * - * Unicode version: 16.0.0 - * Date: 2024-09-11T08:21:22+00:00 + * Unicode version: 14.0.0 + * Date: 2021-09-17T09:20:30+02:00 */ return [ @@ -109,7 +109,7 @@ 2139, ], [ - 2199, + 2200, 2207, ], [ @@ -382,7 +382,7 @@ ], [ 3784, - 3790, + 3789, ], [ 3864, @@ -916,18 +916,10 @@ 68900, 68903, ], - [ - 68969, - 68973, - ], [ 69291, 69292, ], - [ - 69372, - 69375, - ], [ 69446, 69456, @@ -1016,10 +1008,6 @@ 70206, 70206, ], - [ - 70209, - 70209, - ], [ 70367, 70367, @@ -1048,26 +1036,6 @@ 70512, 70516, ], - [ - 70587, - 70592, - ], - [ - 70606, - 70606, - ], - [ - 70608, - 70608, - ], - [ - 70610, - 70610, - ], - [ - 70625, - 70626, - ], [ 70712, 70719, @@ -1146,10 +1114,6 @@ ], [ 71453, - 71453, - ], - [ - 71455, 71455, ], [ @@ -1288,42 +1252,6 @@ 73459, 73460, ], - [ - 73472, - 73473, - ], - [ - 73526, - 73530, - ], - [ - 73536, - 73536, - ], - [ - 73538, - 73538, - ], - [ - 73562, - 73562, - ], - [ - 78912, - 78912, - ], - [ - 78919, - 78933, - ], - [ - 90398, - 90409, - ], - [ - 90413, - 90415, - ], [ 92912, 92916, @@ -1420,10 +1348,6 @@ 122918, 122922, ], - [ - 123023, - 123023, - ], [ 123184, 123190, @@ -1436,14 +1360,6 @@ 123628, 123631, ], - [ - 124140, - 124143, - ], - [ - 124398, - 124399, - ], [ 125136, 125142, diff --git a/deps/vendor/symfony/string/Resources/functions.php b/deps/vendor/symfony/string/Resources/functions.php index 7a970400a..c950894f3 100644 --- a/deps/vendor/symfony/string/Resources/functions.php +++ b/deps/vendor/symfony/string/Resources/functions.php @@ -31,7 +31,7 @@ function b(?string $string = ''): ByteString */ function s(?string $string = ''): AbstractString { - $string ??= ''; + $string = $string ?? ''; return preg_match('//u', $string) ? new UnicodeString($string) : new ByteString($string); } diff --git a/deps/vendor/symfony/string/Slugger/AsciiSlugger.php b/deps/vendor/symfony/string/Slugger/AsciiSlugger.php index a9693d494..5aecfeb5f 100644 --- a/deps/vendor/symfony/string/Slugger/AsciiSlugger.php +++ b/deps/vendor/symfony/string/Slugger/AsciiSlugger.php @@ -11,7 +11,6 @@ namespace Symfony\Component\String\Slugger; -use Symfony\Component\Intl\Transliterator\EmojiTransliterator; use Symfony\Component\String\AbstractUnicodeString; use Symfony\Component\String\UnicodeString; use Symfony\Contracts\Translation\LocaleAwareInterface; @@ -55,76 +54,69 @@ class AsciiSlugger implements SluggerInterface, LocaleAwareInterface 'zh' => 'Han-Latin', ]; - private ?string $defaultLocale; - private \Closure|array $symbolsMap = [ + private $defaultLocale; + private $symbolsMap = [ 'en' => ['@' => 'at', '&' => 'and'], ]; - private bool|string $emoji = false; /** * Cache of transliterators per locale. * * @var \Transliterator[] */ - private array $transliterators = []; + private $transliterators = []; - public function __construct(?string $defaultLocale = null, array|\Closure|null $symbolsMap = null) + /** + * @param array|\Closure|null $symbolsMap + */ + public function __construct(string $defaultLocale = null, $symbolsMap = null) { + if (null !== $symbolsMap && !\is_array($symbolsMap) && !$symbolsMap instanceof \Closure) { + throw new \TypeError(sprintf('Argument 2 passed to "%s()" must be array, Closure or null, "%s" given.', __METHOD__, \gettype($symbolsMap))); + } + $this->defaultLocale = $defaultLocale; $this->symbolsMap = $symbolsMap ?? $this->symbolsMap; } /** - * @return void + * {@inheritdoc} */ - public function setLocale(string $locale) + public function setLocale($locale) { $this->defaultLocale = $locale; } - public function getLocale(): string + /** + * {@inheritdoc} + */ + public function getLocale() { return $this->defaultLocale; } /** - * @param bool|string $emoji true will use the same locale, - * false will disable emoji, - * and a string to use a specific locale + * {@inheritdoc} */ - public function withEmoji(bool|string $emoji = true): static - { - if (false !== $emoji && !class_exists(EmojiTransliterator::class)) { - throw new \LogicException(sprintf('You cannot use the "%s()" method as the "symfony/intl" package is not installed. Try running "composer require symfony/intl".', __METHOD__)); - } - - $new = clone $this; - $new->emoji = $emoji; - - return $new; - } - - public function slug(string $string, string $separator = '-', ?string $locale = null): AbstractUnicodeString + public function slug(string $string, string $separator = '-', string $locale = null): AbstractUnicodeString { - $locale ??= $this->defaultLocale; + $locale = $locale ?? $this->defaultLocale; $transliterator = []; - if ($locale && ('de' === $locale || str_starts_with($locale, 'de_'))) { + if ($locale && ('de' === $locale || 0 === strpos($locale, 'de_'))) { // Use the shortcut for German in UnicodeString::ascii() if possible (faster and no requirement on intl) $transliterator = ['de-ASCII']; } elseif (\function_exists('transliterator_transliterate') && $locale) { $transliterator = (array) $this->createTransliterator($locale); } - if ($emojiTransliterator = $this->createEmojiTransliterator($locale)) { - $transliterator[] = $emojiTransliterator; - } - if ($this->symbolsMap instanceof \Closure) { // If the symbols map is passed as a closure, there is no need to fallback to the parent locale // as the closure can just provide substitutions for all locales of interest. $symbolsMap = $this->symbolsMap; - array_unshift($transliterator, static fn ($s) => $symbolsMap($s, $locale)); + array_unshift($transliterator, static function ($s) use ($symbolsMap, $locale) { + return $symbolsMap($s, $locale); + }); } $unicodeString = (new UnicodeString($string))->ascii($transliterator); @@ -176,25 +168,6 @@ private function createTransliterator(string $locale): ?\Transliterator return $this->transliterators[$locale] = $this->transliterators[$parent] = $transliterator ?? null; } - private function createEmojiTransliterator(?string $locale): ?EmojiTransliterator - { - if (\is_string($this->emoji)) { - $locale = $this->emoji; - } elseif (!$this->emoji) { - return null; - } - - while (null !== $locale) { - try { - return EmojiTransliterator::create("emoji-$locale"); - } catch (\IntlException) { - $locale = self::getParentLocale($locale); - } - } - - return null; - } - private static function getParentLocale(?string $locale): ?string { if (!$locale) { diff --git a/deps/vendor/symfony/string/Slugger/SluggerInterface.php b/deps/vendor/symfony/string/Slugger/SluggerInterface.php index dd0d58102..c679ed933 100644 --- a/deps/vendor/symfony/string/Slugger/SluggerInterface.php +++ b/deps/vendor/symfony/string/Slugger/SluggerInterface.php @@ -23,5 +23,5 @@ interface SluggerInterface /** * Creates a slug for the given string and locale, using appropriate transliteration when needed. */ - public function slug(string $string, string $separator = '-', ?string $locale = null): AbstractUnicodeString; + public function slug(string $string, string $separator = '-', string $locale = null): AbstractUnicodeString; } diff --git a/deps/vendor/symfony/string/UnicodeString.php b/deps/vendor/symfony/string/UnicodeString.php index 75af2da42..9b906c6fc 100644 --- a/deps/vendor/symfony/string/UnicodeString.php +++ b/deps/vendor/symfony/string/UnicodeString.php @@ -34,32 +34,23 @@ class UnicodeString extends AbstractUnicodeString { public function __construct(string $string = '') { - if ('' === $string || normalizer_is_normalized($this->string = $string)) { - return; - } + $this->string = normalizer_is_normalized($string) ? $string : normalizer_normalize($string); - if (false === $string = normalizer_normalize($string)) { + if (false === $this->string) { throw new InvalidArgumentException('Invalid UTF-8 string.'); } - - $this->string = $string; } - public function append(string ...$suffix): static + public function append(string ...$suffix): AbstractString { $str = clone $this; $str->string = $this->string.(1 >= \count($suffix) ? ($suffix[0] ?? '') : implode('', $suffix)); + normalizer_is_normalized($str->string) ?: $str->string = normalizer_normalize($str->string); - if (normalizer_is_normalized($str->string)) { - return $str; - } - - if (false === $string = normalizer_normalize($str->string)) { + if (false === $str->string) { throw new InvalidArgumentException('Invalid UTF-8 string.'); } - $str->string = $string; - return $str; } @@ -91,12 +82,14 @@ public function chunk(int $length = 1): array return $chunks; } - public function endsWith(string|iterable|AbstractString $suffix): bool + public function endsWith($suffix): bool { if ($suffix instanceof AbstractString) { $suffix = $suffix->string; - } elseif (!\is_string($suffix)) { + } elseif (\is_array($suffix) || $suffix instanceof \Traversable) { return parent::endsWith($suffix); + } else { + $suffix = (string) $suffix; } $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC; @@ -113,12 +106,14 @@ public function endsWith(string|iterable|AbstractString $suffix): bool return $suffix === grapheme_extract($this->string, \strlen($suffix), \GRAPHEME_EXTR_MAXBYTES, \strlen($this->string) - \strlen($suffix)); } - public function equalsTo(string|iterable|AbstractString $string): bool + public function equalsTo($string): bool { if ($string instanceof AbstractString) { $string = $string->string; - } elseif (!\is_string($string)) { + } elseif (\is_array($string) || $string instanceof \Traversable) { return parent::equalsTo($string); + } else { + $string = (string) $string; } $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC; @@ -131,12 +126,14 @@ public function equalsTo(string|iterable|AbstractString $string): bool return $string === $this->string; } - public function indexOf(string|iterable|AbstractString $needle, int $offset = 0): ?int + public function indexOf($needle, int $offset = 0): ?int { if ($needle instanceof AbstractString) { $needle = $needle->string; - } elseif (!\is_string($needle)) { + } elseif (\is_array($needle) || $needle instanceof \Traversable) { return parent::indexOf($needle, $offset); + } else { + $needle = (string) $needle; } $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC; @@ -148,19 +145,21 @@ public function indexOf(string|iterable|AbstractString $needle, int $offset = 0) try { $i = $this->ignoreCase ? grapheme_stripos($this->string, $needle, $offset) : grapheme_strpos($this->string, $needle, $offset); - } catch (\ValueError) { + } catch (\ValueError $e) { return null; } return false === $i ? null : $i; } - public function indexOfLast(string|iterable|AbstractString $needle, int $offset = 0): ?int + public function indexOfLast($needle, int $offset = 0): ?int { if ($needle instanceof AbstractString) { $needle = $needle->string; - } elseif (!\is_string($needle)) { + } elseif (\is_array($needle) || $needle instanceof \Traversable) { return parent::indexOfLast($needle, $offset); + } else { + $needle = (string) $needle; } $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC; @@ -185,7 +184,7 @@ public function indexOfLast(string|iterable|AbstractString $needle, int $offset return false === $i ? null : $i; } - public function join(array $strings, ?string $lastGlue = null): static + public function join(array $strings, string $lastGlue = null): AbstractString { $str = parent::join($strings, $lastGlue); normalizer_is_normalized($str->string) ?: $str->string = normalizer_normalize($str->string); @@ -198,7 +197,10 @@ public function length(): int return grapheme_strlen($this->string); } - public function normalize(int $form = self::NFC): static + /** + * @return static + */ + public function normalize(int $form = self::NFC): parent { $str = clone $this; @@ -214,25 +216,20 @@ public function normalize(int $form = self::NFC): static return $str; } - public function prepend(string ...$prefix): static + public function prepend(string ...$prefix): AbstractString { $str = clone $this; $str->string = (1 >= \count($prefix) ? ($prefix[0] ?? '') : implode('', $prefix)).$this->string; + normalizer_is_normalized($str->string) ?: $str->string = normalizer_normalize($str->string); - if (normalizer_is_normalized($str->string)) { - return $str; - } - - if (false === $string = normalizer_normalize($str->string)) { + if (false === $str->string) { throw new InvalidArgumentException('Invalid UTF-8 string.'); } - $str->string = $string; - return $str; } - public function replace(string $from, string $to): static + public function replace(string $from, string $to): AbstractString { $str = clone $this; normalizer_is_normalized($from) ?: $from = normalizer_normalize($from); @@ -249,22 +246,17 @@ public function replace(string $from, string $to): static } $str->string = $result.$tail; + normalizer_is_normalized($str->string) ?: $str->string = normalizer_normalize($str->string); - if (normalizer_is_normalized($str->string)) { - return $str; - } - - if (false === $string = normalizer_normalize($str->string)) { + if (false === $str->string) { throw new InvalidArgumentException('Invalid UTF-8 string.'); } - - $str->string = $string; } return $str; } - public function replaceMatches(string $fromRegexp, string|callable $to): static + public function replaceMatches(string $fromRegexp, $to): AbstractString { $str = parent::replaceMatches($fromRegexp, $to); normalizer_is_normalized($str->string) ?: $str->string = normalizer_normalize($str->string); @@ -272,39 +264,40 @@ public function replaceMatches(string $fromRegexp, string|callable $to): static return $str; } - public function slice(int $start = 0, ?int $length = null): static + public function slice(int $start = 0, int $length = null): AbstractString { $str = clone $this; + if (\PHP_VERSION_ID < 80000 && 0 > $start && grapheme_strlen($this->string) < -$start) { + $start = 0; + } $str->string = (string) grapheme_substr($this->string, $start, $length ?? 2147483647); return $str; } - public function splice(string $replacement, int $start = 0, ?int $length = null): static + public function splice(string $replacement, int $start = 0, int $length = null): AbstractString { $str = clone $this; + if (\PHP_VERSION_ID < 80000 && 0 > $start && grapheme_strlen($this->string) < -$start) { + $start = 0; + } $start = $start ? \strlen(grapheme_substr($this->string, 0, $start)) : 0; $length = $length ? \strlen(grapheme_substr($this->string, $start, $length ?? 2147483647)) : $length; $str->string = substr_replace($this->string, $replacement, $start, $length ?? 2147483647); + normalizer_is_normalized($str->string) ?: $str->string = normalizer_normalize($str->string); - if (normalizer_is_normalized($str->string)) { - return $str; - } - - if (false === $string = normalizer_normalize($str->string)) { + if (false === $str->string) { throw new InvalidArgumentException('Invalid UTF-8 string.'); } - $str->string = $string; - return $str; } - public function split(string $delimiter, ?int $limit = null, ?int $flags = null): array + public function split(string $delimiter, int $limit = null, int $flags = null): array { - if (1 > $limit ??= 2147483647) { + if (1 > $limit = $limit ?? 2147483647) { throw new InvalidArgumentException('Split limit must be a positive integer.'); } @@ -340,12 +333,14 @@ public function split(string $delimiter, ?int $limit = null, ?int $flags = null) return $chunks; } - public function startsWith(string|iterable|AbstractString $prefix): bool + public function startsWith($prefix): bool { if ($prefix instanceof AbstractString) { $prefix = $prefix->string; - } elseif (!\is_string($prefix)) { + } elseif (\is_array($prefix) || $prefix instanceof \Traversable) { return parent::startsWith($prefix); + } else { + $prefix = (string) $prefix; } $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC; @@ -362,9 +357,6 @@ public function startsWith(string|iterable|AbstractString $prefix): bool return $prefix === grapheme_extract($this->string, \strlen($prefix), \GRAPHEME_EXTR_MAXBYTES); } - /** - * @return void - */ public function __wakeup() { if (!\is_string($this->string)) { diff --git a/deps/vendor/symfony/string/composer.json b/deps/vendor/symfony/string/composer.json index 56c136882..2b88fd529 100644 --- a/deps/vendor/symfony/string/composer.json +++ b/deps/vendor/symfony/string/composer.json @@ -16,21 +16,21 @@ } ], "require": { - "php": ">=8.1", + "php": ">=7.2.5", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-intl-grapheme": "~1.0", "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0" + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php80": "~1.15" }, "require-dev": { - "symfony/error-handler": "^5.4|^6.0|^7.0", - "symfony/intl": "^6.2|^7.0", - "symfony/http-client": "^5.4|^6.0|^7.0", - "symfony/translation-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^5.4|^6.0|^7.0" + "symfony/error-handler": "^4.4|^5.0|^6.0", + "symfony/http-client": "^4.4|^5.0|^6.0", + "symfony/translation-contracts": "^1.1|^2", + "symfony/var-exporter": "^4.4|^5.0|^6.0" }, "conflict": { - "symfony/translation-contracts": "<2.5" + "symfony/translation-contracts": ">=3.0" }, "autoload": { "psr-4": { "Symfony\\Component\\String\\": "" }, diff --git a/deps/vendor/symfony/yaml/Command/LintCommand.php b/deps/vendor/symfony/yaml/Command/LintCommand.php index 6eac39983..3ebd570e7 100644 --- a/deps/vendor/symfony/yaml/Command/LintCommand.php +++ b/deps/vendor/symfony/yaml/Command/LintCommand.php @@ -43,7 +43,7 @@ class LintCommand extends Command private $directoryIteratorProvider; private $isReadableProvider; - public function __construct(?string $name = null, ?callable $directoryIteratorProvider = null, ?callable $isReadableProvider = null) + public function __construct(string $name = null, callable $directoryIteratorProvider = null, callable $isReadableProvider = null) { parent::__construct($name); @@ -133,7 +133,7 @@ protected function execute(InputInterface $input, OutputInterface $output) return $this->display($io, $filesInfo); } - private function validate(string $content, int $flags, ?string $file = null) + private function validate(string $content, int $flags, string $file = null) { $prevErrorHandler = set_error_handler(function ($level, $message, $file, $line) use (&$prevErrorHandler) { if (\E_USER_DEPRECATED === $level) { diff --git a/deps/vendor/symfony/yaml/Dumper.php b/deps/vendor/symfony/yaml/Dumper.php index 99346aa1e..db3e346b1 100644 --- a/deps/vendor/symfony/yaml/Dumper.php +++ b/deps/vendor/symfony/yaml/Dumper.php @@ -58,8 +58,6 @@ public function dump($input, int $inline = 0, int $indent = 0, int $flags = 0): if ($inline <= 0 || (!\is_array($input) && !$input instanceof TaggedValue && $dumpObjectAsInlineMap) || empty($input)) { $output .= $prefix.Inline::dump($input, $flags); - } elseif ($input instanceof TaggedValue) { - $output .= $this->dumpTaggedValue($input, $inline, $indent, $flags, $prefix); } else { $dumpAsMap = Inline::isHash($input); @@ -69,7 +67,9 @@ public function dump($input, int $inline = 0, int $indent = 0, int $flags = 0): } if (Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK & $flags && \is_string($value) && false !== strpos($value, "\n") && false === strpos($value, "\r")) { - $blockIndentationIndicator = $this->getBlockIndentationIndicator($value); + // If the first line starts with a space character, the spec requires a blockIndicationIndicator + // http://www.yaml.org/spec/1.2/spec.html#id2793979 + $blockIndentationIndicator = (' ' === substr($value, 0, 1)) ? (string) $this->indentation : ''; if (isset($value[-2]) && "\n" === $value[-2] && "\n" === $value[-1]) { $blockChompingIndicator = '+'; @@ -96,7 +96,9 @@ public function dump($input, int $inline = 0, int $indent = 0, int $flags = 0): $output .= sprintf('%s%s !%s', $prefix, $dumpAsMap ? Inline::dump($key, $flags).':' : '-', $value->getTag()); if (Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK & $flags && \is_string($value->getValue()) && false !== strpos($value->getValue(), "\n") && false === strpos($value->getValue(), "\r\n")) { - $blockIndentationIndicator = $this->getBlockIndentationIndicator($value->getValue()); + // If the first line starts with a space character, the spec requires a blockIndicationIndicator + // http://www.yaml.org/spec/1.2/spec.html#id2793979 + $blockIndentationIndicator = (' ' === substr($value->getValue(), 0, 1)) ? (string) $this->indentation : ''; $output .= sprintf(' |%s', $blockIndentationIndicator); foreach (explode("\n", $value->getValue()) as $row) { @@ -106,7 +108,7 @@ public function dump($input, int $inline = 0, int $indent = 0, int $flags = 0): continue; } - if ($inline - 1 <= 0 || null === $value->getValue() || \is_scalar($value->getValue())) { + if ($inline - 1 <= 0 || null === $value->getValue() || is_scalar($value->getValue())) { $output .= ' '.$this->dump($value->getValue(), $inline - 1, 0, $flags)."\n"; } else { $output .= "\n"; @@ -135,42 +137,4 @@ public function dump($input, int $inline = 0, int $indent = 0, int $flags = 0): return $output; } - - private function dumpTaggedValue(TaggedValue $value, int $inline, int $indent, int $flags, string $prefix): string - { - $output = sprintf('%s!%s', $prefix ? $prefix.' ' : '', $value->getTag()); - - if (Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK & $flags && \is_string($value->getValue()) && false !== strpos($value->getValue(), "\n") && false === strpos($value->getValue(), "\r\n")) { - $blockIndentationIndicator = $this->getBlockIndentationIndicator($value->getValue()); - $output .= sprintf(' |%s', $blockIndentationIndicator); - - foreach (explode("\n", $value->getValue()) as $row) { - $output .= sprintf("\n%s%s%s", $prefix, str_repeat(' ', $this->indentation), $row); - } - - return $output; - } - - if ($inline - 1 <= 0 || null === $value->getValue() || \is_scalar($value->getValue())) { - return $output.' '.$this->dump($value->getValue(), $inline - 1, 0, $flags)."\n"; - } - - return $output."\n".$this->dump($value->getValue(), $inline - 1, $indent, $flags); - } - - private function getBlockIndentationIndicator(string $value): string - { - $lines = explode("\n", $value); - - // If the first line (that is neither empty nor contains only spaces) - // starts with a space character, the spec requires a block indentation indicator - // http://www.yaml.org/spec/1.2/spec.html#id2793979 - foreach ($lines as $line) { - if ('' !== trim($line, ' ')) { - return (' ' === substr($line, 0, 1)) ? (string) $this->indentation : ''; - } - } - - return ''; - } } diff --git a/deps/vendor/symfony/yaml/Exception/ParseException.php b/deps/vendor/symfony/yaml/Exception/ParseException.php index 9b59ea30e..8748d2b22 100644 --- a/deps/vendor/symfony/yaml/Exception/ParseException.php +++ b/deps/vendor/symfony/yaml/Exception/ParseException.php @@ -29,7 +29,7 @@ class ParseException extends RuntimeException * @param string|null $snippet The snippet of code near the problem * @param string|null $parsedFile The file name where the error occurred */ - public function __construct(string $message, int $parsedLine = -1, ?string $snippet = null, ?string $parsedFile = null, ?\Throwable $previous = null) + public function __construct(string $message, int $parsedLine = -1, string $snippet = null, string $parsedFile = null, \Throwable $previous = null) { $this->parsedFile = $parsedFile; $this->parsedLine = $parsedLine; diff --git a/deps/vendor/symfony/yaml/Inline.php b/deps/vendor/symfony/yaml/Inline.php index 5e4e5f7a8..3d64b1ada 100644 --- a/deps/vendor/symfony/yaml/Inline.php +++ b/deps/vendor/symfony/yaml/Inline.php @@ -34,7 +34,7 @@ class Inline private static $objectForMap = false; private static $constantSupport = false; - public static function initialize(int $flags, ?int $parsedLineNumber = null, ?string $parsedFilename = null) + public static function initialize(int $flags, int $parsedLineNumber = null, string $parsedFilename = null) { self::$exceptionOnInvalidType = (bool) (Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE & $flags); self::$objectSupport = (bool) (Yaml::PARSE_OBJECT & $flags); @@ -50,20 +50,16 @@ public static function initialize(int $flags, ?int $parsedLineNumber = null, ?st /** * Converts a YAML string to a PHP value. * - * @param string|null $value A YAML string - * @param int $flags A bit field of Yaml::PARSE_* constants to customize the YAML parser behavior - * @param array $references Mapping of variable names to values + * @param string $value A YAML string + * @param int $flags A bit field of PARSE_* constants to customize the YAML parser behavior + * @param array $references Mapping of variable names to values * * @return mixed * * @throws ParseException */ - public static function parse(?string $value = null, int $flags = 0, array &$references = []) + public static function parse(string $value = null, int $flags = 0, array &$references = []) { - if (null === $value) { - return ''; - } - self::initialize($flags); $value = trim($value); @@ -72,7 +68,7 @@ public static function parse(?string $value = null, int $flags = 0, array &$refe return ''; } - if (2 /* MB_OVERLOAD_STRING */ & (int) \ini_get('mbstring.func_overload')) { + if (2 /* MB_OVERLOAD_STRING */ & (int) ini_get('mbstring.func_overload')) { $mbEncoding = mb_internal_encoding(); mb_internal_encoding('ASCII'); } @@ -90,7 +86,7 @@ public static function parse(?string $value = null, int $flags = 0, array &$refe ++$i; break; default: - $result = self::parseScalar($value, $flags, null, $i, true, $references); + $result = self::parseScalar($value, $flags, null, $i, null === $tag, $references); } // some comments are allowed at the end @@ -269,7 +265,7 @@ private static function dumpNull(int $flags): string * * @throws ParseException When malformed inline YAML string is parsed */ - public static function parseScalar(string $scalar, int $flags = 0, ?array $delimiters = null, int &$i = 0, bool $evaluate = true, array &$references = [], ?bool &$isQuoted = null) + public static function parseScalar(string $scalar, int $flags = 0, array $delimiters = null, int &$i = 0, bool $evaluate = true, array &$references = [], bool &$isQuoted = null) { if (\in_array($scalar[$i], ['"', "'"], true)) { // quoted scalar @@ -355,18 +351,11 @@ private static function parseSequence(string $sequence, int $flags, int &$i = 0, ++$i; // [foo, bar, ...] - $lastToken = null; while ($i < $len) { if (']' === $sequence[$i]) { return $output; } if (',' === $sequence[$i] || ' ' === $sequence[$i]) { - if (',' === $sequence[$i] && (null === $lastToken || 'separator' === $lastToken)) { - $output[] = null; - } elseif (',' === $sequence[$i]) { - $lastToken = 'separator'; - } - ++$i; continue; @@ -410,7 +399,6 @@ private static function parseSequence(string $sequence, int $flags, int &$i = 0, $output[] = $value; - $lastToken = 'value'; ++$i; } @@ -539,7 +527,7 @@ private static function parseMapping(string $mapping, int $flags, int &$i = 0, a if ('<<' === $key) { $output += $value; } elseif ($allowOverwrite || !isset($output[$key])) { - if (!$isValueQuoted && \is_string($value) && '' !== $value && '&' === $value[0] && !self::isBinaryString($value) && Parser::preg_match(Parser::REFERENCE_PATTERN, $value, $matches)) { + if (!$isValueQuoted && \is_string($value) && '' !== $value && '&' === $value[0] && Parser::preg_match(Parser::REFERENCE_PATTERN, $value, $matches)) { $references[$matches['ref']] = $matches['value']; $value = $matches['value']; } @@ -570,7 +558,7 @@ private static function parseMapping(string $mapping, int $flags, int &$i = 0, a * * @throws ParseException when object parsing support was disabled and the parser detected a PHP object or when a reference could not be resolved */ - private static function evaluateScalar(string $scalar, int $flags, array &$references = [], ?bool &$isQuotedString = null) + private static function evaluateScalar(string $scalar, int $flags, array &$references = [], bool &$isQuotedString = null) { $isQuotedString = false; $scalar = trim($scalar); @@ -669,6 +657,7 @@ private static function evaluateScalar(string $scalar, int $flags, array &$refer } return octdec($value); + // Optimize for returning strings. case \in_array($scalar[0], ['+', '-', '.'], true) || is_numeric($scalar[0]): if (Parser::preg_match('{^[+-]?[0-9][0-9_]*$}', $scalar)) { $scalar = str_replace('_', '', $scalar); @@ -708,13 +697,8 @@ private static function evaluateScalar(string $scalar, int $flags, array &$refer case Parser::preg_match('/^(-|\+)?[0-9][0-9_]*(\.[0-9_]+)?$/', $scalar): return (float) str_replace('_', '', $scalar); case Parser::preg_match(self::getTimestampRegex(), $scalar): - try { - // When no timezone is provided in the parsed date, YAML spec says we must assume UTC. - $time = new \DateTime($scalar, new \DateTimeZone('UTC')); - } catch (\Exception $e) { - // Some dates accepted by the regex are not valid dates. - throw new ParseException(\sprintf('The date "%s" could not be parsed as it is an invalid date.', $scalar), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename, $e); - } + // When no timezone is provided in the parsed date, YAML spec says we must assume UTC. + $time = new \DateTime($scalar, new \DateTimeZone('UTC')); if (Yaml::PARSE_DATETIME & $flags) { return $time; diff --git a/deps/vendor/symfony/yaml/LICENSE b/deps/vendor/symfony/yaml/LICENSE index 0138f8f07..88bf75bb4 100644 --- a/deps/vendor/symfony/yaml/LICENSE +++ b/deps/vendor/symfony/yaml/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-present Fabien Potencier +Copyright (c) 2004-2022 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/deps/vendor/symfony/yaml/Parser.php b/deps/vendor/symfony/yaml/Parser.php index 6b5b273a7..2701a4418 100644 --- a/deps/vendor/symfony/yaml/Parser.php +++ b/deps/vendor/symfony/yaml/Parser.php @@ -43,7 +43,7 @@ class Parser * Parses a YAML file into a PHP value. * * @param string $filename The path to the YAML file to be parsed - * @param int $flags A bit field of Yaml::PARSE_* constants to customize the YAML parser behavior + * @param int $flags A bit field of PARSE_* constants to customize the YAML parser behavior * * @return mixed * @@ -72,7 +72,7 @@ public function parseFile(string $filename, int $flags = 0) * Parses a YAML string to a PHP value. * * @param string $value A YAML string - * @param int $flags A bit field of Yaml::PARSE_* constants to customize the YAML parser behavior + * @param int $flags A bit field of PARSE_* constants to customize the YAML parser behavior * * @return mixed * @@ -88,7 +88,7 @@ public function parse(string $value, int $flags = 0) $mbEncoding = null; - if (2 /* MB_OVERLOAD_STRING */ & (int) \ini_get('mbstring.func_overload')) { + if (2 /* MB_OVERLOAD_STRING */ & (int) ini_get('mbstring.func_overload')) { $mbEncoding = mb_internal_encoding(); mb_internal_encoding('UTF-8'); } @@ -199,8 +199,9 @@ private function doParse(string $value, int $flags) || self::preg_match('#^(?P'.Inline::REGEX_QUOTED_STRING.'|[^ \'"\{\[].*?) *\:(\s+(?P.+?))?\s*$#u', $this->trimTag($values['value']), $matches) ) ) { + // this is a compact notation element, add to next block and parse $block = $values['value']; - if ($this->isNextLineIndented() || isset($matches['value']) && '>-' === $matches['value']) { + if ($this->isNextLineIndented()) { $block .= "\n".$this->getNextEmbedBlock($this->getCurrentLineIndentation() + \strlen($values['leadspaces']) + 1); } @@ -576,7 +577,7 @@ private function getCurrentLineIndentation(): int * * @throws ParseException When indentation problem are detected */ - private function getNextEmbedBlock(?int $indentation = null, bool $inSequence = false): string + private function getNextEmbedBlock(int $indentation = null, bool $inSequence = false): string { $oldLineIndentation = $this->getCurrentLineIndentation(); @@ -653,12 +654,12 @@ private function getNextEmbedBlock(?int $indentation = null, bool $inSequence = } if ($this->isCurrentLineBlank()) { - $data[] = substr($this->currentLine, $newIndent ?? 0); + $data[] = substr($this->currentLine, $newIndent); continue; } if ($indent >= $newIndent) { - $data[] = substr($this->currentLine, $newIndent ?? 0); + $data[] = substr($this->currentLine, $newIndent); } elseif ($this->isCurrentLineComment()) { $data[] = $this->currentLine; } elseif (0 == $indent) { @@ -710,7 +711,7 @@ private function moveToPreviousLine(): bool * Parses a YAML value. * * @param string $value A YAML value - * @param int $flags A bit field of Yaml::PARSE_* constants to customize the YAML parser behavior + * @param int $flags A bit field of PARSE_* constants to customize the YAML parser behavior * @param string $context The parser context (either sequence or mapping) * * @return mixed @@ -948,10 +949,6 @@ private function isNextLineIndented(): bool } while (!$EOF && ($this->isCurrentLineEmpty() || $this->isCurrentLineComment())); if ($EOF) { - for ($i = 0; $i < $movements; ++$i) { - $this->moveToPreviousLine(); - } - return false; } @@ -985,7 +982,7 @@ private function isCurrentLineBlank(): bool */ private function isCurrentLineComment(): bool { - // checking explicitly the first char of the trim is faster than loops or strpos + //checking explicitly the first char of the trim is faster than loops or strpos $ltrimmedLine = '' !== $this->currentLine && ' ' === $this->currentLine[0] ? ltrim($this->currentLine, ' ') : $this->currentLine; return '' !== $ltrimmedLine && '#' === $ltrimmedLine[0]; @@ -1082,7 +1079,7 @@ private function isStringUnIndentedCollectionItem(): bool * * @internal */ - public static function preg_match(string $pattern, string $subject, ?array &$matches = null, int $flags = 0, int $offset = 0): int + public static function preg_match(string $pattern, string $subject, array &$matches = null, int $flags = 0, int $offset = 0): int { if (false === $ret = preg_match($pattern, $subject, $matches, $flags, $offset)) { switch (preg_last_error()) { diff --git a/deps/vendor/symfony/yaml/Resources/bin/yaml-lint b/deps/vendor/symfony/yaml/Resources/bin/yaml-lint index 143869e01..0ad73d714 100755 --- a/deps/vendor/symfony/yaml/Resources/bin/yaml-lint +++ b/deps/vendor/symfony/yaml/Resources/bin/yaml-lint @@ -10,10 +10,6 @@ * file that was distributed with this source code. */ -if ('cli' !== \PHP_SAPI) { - throw new Exception('This script must be run from the command line.'); -} - /** * Runs the Yaml lint command. *